/** * 🧠 Neural Similarity API Commands * * CLI interface for semantic similarity, clustering, and neural operations */ import inquirer from 'inquirer'; import chalk from 'chalk'; import ora from 'ora'; import fs from 'fs'; import path from 'path'; import { BrainyData } from '../../brainyData.js'; import { NeuralAPI } from '../../neural/neuralAPI.js'; interface CommandArguments { action?: string; id?: string; query?: string; threshold?: number; format?: string; output?: string; limit?: number; algorithm?: string; dimensions?: number; explain?: boolean; _: string[]; } export const neuralCommand = { command: 'neural [action]', describe: '🧠 Neural similarity and clustering operations', builder: (yargs: any) => { return yargs .positional('action', { describe: 'Neural operation to perform', type: 'string', choices: ['similar', 'clusters', 'hierarchy', 'neighbors', 'path', 'outliers', 'visualize'] }) .option('id', { describe: 'Item ID for similarity operations', type: 'string', alias: 'i' }) .option('query', { describe: 'Query text for similarity search', type: 'string', alias: 'q' }) .option('threshold', { describe: 'Similarity threshold (0-1)', type: 'number', default: 0.7, alias: 't' }) .option('format', { describe: 'Output format', type: 'string', choices: ['json', 'table', 'tree', 'graph'], default: 'table', alias: 'f' }) .option('output', { describe: 'Output file path', type: 'string', alias: 'o' }) .option('limit', { describe: 'Maximum number of results', type: 'number', default: 10, alias: 'l' }) .option('algorithm', { describe: 'Clustering algorithm', type: 'string', choices: ['hierarchical', 'kmeans', 'dbscan', 'auto'], default: 'auto', alias: 'a' }) .option('dimensions', { describe: 'Visualization dimensions (2 or 3)', type: 'number', choices: [2, 3], default: 2, alias: 'd' }) .option('explain', { describe: 'Include detailed explanations', type: 'boolean', default: false, alias: 'e' }); }, handler: async (argv: CommandArguments) => { console.log(chalk.cyan('\n🧠 NEURAL SIMILARITY API')); console.log(chalk.gray('━'.repeat(50))); // Initialize Brainy and Neural API const brain = new BrainyData(); const neural = new NeuralAPI(brain); try { const action = argv.action || await promptForAction(); switch (action) { case 'similar': await handleSimilarCommand(neural, argv); break; case 'clusters': await handleClustersCommand(neural, argv); break; case 'hierarchy': await handleHierarchyCommand(neural, argv); break; case 'neighbors': await handleNeighborsCommand(neural, argv); break; case 'path': await handlePathCommand(neural, argv); break; case 'outliers': await handleOutliersCommand(neural, argv); break; case 'visualize': await handleVisualizeCommand(neural, argv); break; default: console.log(chalk.red(`❌ Unknown action: ${action}`)); showHelp(); } } catch (error) { console.error(chalk.red('πŸ’₯ Error:'), error instanceof Error ? error.message : error); process.exit(1); } } }; async function promptForAction(): Promise { const answer = await inquirer.prompt([{ type: 'list', name: 'action', message: 'Choose a neural operation:', choices: [ { name: 'πŸ”— Calculate similarity between items', value: 'similar' }, { name: '🎯 Find semantic clusters', value: 'clusters' }, { name: '🌳 Show item hierarchy', value: 'hierarchy' }, { name: 'πŸ•ΈοΈ Find semantic neighbors', value: 'neighbors' }, { name: 'πŸ›£οΈ Find semantic path between items', value: 'path' }, { name: '🚨 Detect outliers', value: 'outliers' }, { name: 'πŸ“Š Generate visualization data', value: 'visualize' } ] }]); return answer.action; } async function handleSimilarCommand(neural: NeuralAPI, argv: CommandArguments): Promise { const spinner = ora('🧠 Calculating semantic similarity...').start(); try { let itemA: string, itemB: string; if (argv.id && argv.query) { itemA = argv.id; itemB = argv.query; } else if (argv._ && argv._.length >= 3) { itemA = argv._[1]; itemB = argv._[2]; } else { spinner.stop(); const answers = await inquirer.prompt([ { type: 'input', name: 'itemA', message: 'First item (ID or text):', validate: (input: string) => input.length > 0 }, { type: 'input', name: 'itemB', message: 'Second item (ID or text):', validate: (input: string) => input.length > 0 } ]); itemA = answers.itemA; itemB = answers.itemB; spinner.start(); } const result = await neural.similar(itemA, itemB, { explain: argv.explain, includeBreakdown: argv.explain }); spinner.succeed('βœ… Similarity calculated'); if (typeof result === 'number') { console.log(`\nπŸ”— Similarity: ${chalk.cyan((result * 100).toFixed(1))}%`); } else { console.log(`\nπŸ”— Similarity: ${chalk.cyan((result.score * 100).toFixed(1))}%`); if (result.explanation) { console.log(`πŸ’­ Explanation: ${result.explanation}`); } if (result.breakdown) { console.log('\nπŸ“Š Breakdown:'); console.log(` Semantic: ${chalk.yellow((result.breakdown.semantic! * 100).toFixed(1))}%`); if (result.breakdown.taxonomic !== undefined) { console.log(` Taxonomic: ${chalk.yellow((result.breakdown.taxonomic * 100).toFixed(1))}%`); } if (result.breakdown.contextual !== undefined) { console.log(` Contextual: ${chalk.yellow((result.breakdown.contextual * 100).toFixed(1))}%`); } } if (result.hierarchy) { console.log(`\n🌳 Hierarchy: ${result.hierarchy.sharedParent ? `Shared parent at distance ${result.hierarchy.distance}` : 'No shared parent found'}`); } } if (argv.output) { await saveToFile(argv.output, result, argv.format!); } } catch (error) { spinner.fail('πŸ’₯ Failed to calculate similarity'); throw error; } } async function handleClustersCommand(neural: NeuralAPI, argv: CommandArguments): Promise { const spinner = ora('🎯 Finding semantic clusters...').start(); try { const options = { algorithm: argv.algorithm as any, threshold: argv.threshold, maxClusters: argv.limit }; const clusters = await neural.clusters(argv.query || options); spinner.succeed(`βœ… Found ${clusters.length} clusters`); if (argv.format === 'json') { console.log(JSON.stringify(clusters, null, 2)); } else { console.log(`\n🎯 ${chalk.cyan(clusters.length)} Semantic Clusters:\n`); clusters.forEach((cluster, index) => { console.log(`${chalk.yellow(`Cluster ${index + 1}:`)} ${cluster.label || cluster.id}`); console.log(` πŸ“Š Confidence: ${chalk.green((cluster.confidence * 100).toFixed(1))}%`); console.log(` πŸ‘₯ Members: ${cluster.members.length}`); if (cluster.members.length <= 5) { cluster.members.forEach(member => { console.log(` β€’ ${member}`); }); } else { cluster.members.slice(0, 3).forEach(member => { console.log(` β€’ ${member}`); }); console.log(` ... and ${cluster.members.length - 3} more`); } console.log(); }); } if (argv.output) { await saveToFile(argv.output, clusters, argv.format!); } } catch (error) { spinner.fail('πŸ’₯ Failed to find clusters'); throw error; } } async function handleHierarchyCommand(neural: NeuralAPI, argv: CommandArguments): Promise { const spinner = ora('🌳 Building semantic hierarchy...').start(); try { const id = argv.id || argv._[1]; if (!id) { spinner.stop(); const answer = await inquirer.prompt([{ type: 'input', name: 'id', message: 'Enter item ID:', validate: (input: string) => input.length > 0 }]); spinner.start(); const hierarchy = await neural.hierarchy(answer.id); displayHierarchy(hierarchy); } else { const hierarchy = await neural.hierarchy(id); spinner.succeed('βœ… Hierarchy built'); displayHierarchy(hierarchy); } if (argv.output) { const hierarchy = await neural.hierarchy(id || argv._[1]); await saveToFile(argv.output, hierarchy, argv.format!); } } catch (error) { spinner.fail('πŸ’₯ Failed to build hierarchy'); throw error; } } function displayHierarchy(hierarchy: any): void { console.log(`\n🌳 Semantic Hierarchy for ${chalk.cyan(hierarchy.self.id)}:`); if (hierarchy.root) { console.log(`πŸ” Root: ${hierarchy.root.id} (${(hierarchy.root.similarity * 100).toFixed(1)}%)`); } if (hierarchy.grandparent) { console.log(`πŸ‘΄ Grandparent: ${hierarchy.grandparent.id} (${(hierarchy.grandparent.similarity * 100).toFixed(1)}%)`); } if (hierarchy.parent) { console.log(`πŸ‘¨ Parent: ${hierarchy.parent.id} (${(hierarchy.parent.similarity * 100).toFixed(1)}%)`); } console.log(`🎯 ${chalk.bold('Self:')} ${hierarchy.self.id}`); if (hierarchy.siblings && hierarchy.siblings.length > 0) { console.log(`πŸ‘₯ Siblings: ${hierarchy.siblings.length}`); hierarchy.siblings.forEach((sibling: any) => { console.log(` β€’ ${sibling.id} (${(sibling.similarity * 100).toFixed(1)}%)`); }); } if (hierarchy.children && hierarchy.children.length > 0) { console.log(`πŸ‘Ά Children: ${hierarchy.children.length}`); hierarchy.children.forEach((child: any) => { console.log(` β€’ ${child.id} (${(child.similarity * 100).toFixed(1)}%)`); }); } } async function handleNeighborsCommand(neural: NeuralAPI, argv: CommandArguments): Promise { const spinner = ora('πŸ•ΈοΈ Finding semantic neighbors...').start(); try { const id = argv.id || argv._[1]; if (!id) { spinner.stop(); const answer = await inquirer.prompt([{ type: 'input', name: 'id', message: 'Enter item ID:', validate: (input: string) => input.length > 0 }]); spinner.start(); } const targetId = id || (await inquirer.prompt([{ type: 'input', name: 'id', message: 'Enter item ID:', validate: (input: string) => input.length > 0 }])).id; const graph = await neural.neighbors(targetId, { limit: argv.limit, includeEdges: true }); spinner.succeed(`βœ… Found ${graph.neighbors.length} neighbors`); console.log(`\nπŸ•ΈοΈ Neighbors of ${chalk.cyan(graph.center)}:`); graph.neighbors.forEach((neighbor, index) => { console.log(`${index + 1}. ${neighbor.id} (${(neighbor.similarity * 100).toFixed(1)}%)`); if (neighbor.type) { console.log(` Type: ${neighbor.type}`); } if (neighbor.connections) { console.log(` Connections: ${neighbor.connections}`); } }); if (graph.edges && graph.edges.length > 0) { console.log(`\nπŸ”— ${graph.edges.length} semantic connections found`); } if (argv.output) { await saveToFile(argv.output, graph, argv.format!); } } catch (error) { spinner.fail('πŸ’₯ Failed to find neighbors'); throw error; } } async function handlePathCommand(neural: NeuralAPI, argv: CommandArguments): Promise { const spinner = ora('πŸ›£οΈ Finding semantic path...').start(); try { let fromId: string, toId: string; if (argv._ && argv._.length >= 3) { fromId = argv._[1]; toId = argv._[2]; } else { spinner.stop(); const answers = await inquirer.prompt([ { type: 'input', name: 'from', message: 'From item ID:', validate: (input: string) => input.length > 0 }, { type: 'input', name: 'to', message: 'To item ID:', validate: (input: string) => input.length > 0 } ]); fromId = answers.from; toId = answers.to; spinner.start(); } const path = await neural.semanticPath(fromId, toId); if (path.length === 0) { spinner.warn('🚫 No semantic path found'); console.log(`No path found between ${chalk.cyan(fromId)} and ${chalk.cyan(toId)}`); } else { spinner.succeed(`βœ… Found path with ${path.length} hops`); console.log(`\nπŸ›£οΈ Semantic Path from ${chalk.cyan(fromId)} to ${chalk.cyan(toId)}:`); console.log(`${chalk.cyan(fromId)} (start)`); path.forEach((hop, index) => { console.log(`${' '.repeat(index + 1)}↓ ${(hop.similarity * 100).toFixed(1)}%`); console.log(`${' '.repeat(index + 1)}${hop.id} (hop ${hop.hop})`); }); } if (argv.output) { await saveToFile(argv.output, path, argv.format!); } } catch (error) { spinner.fail('πŸ’₯ Failed to find path'); throw error; } } async function handleOutliersCommand(neural: NeuralAPI, argv: CommandArguments): Promise { const spinner = ora('🚨 Detecting semantic outliers...').start(); try { const outliers = await neural.outliers(argv.threshold); spinner.succeed(`βœ… Found ${outliers.length} outliers`); if (outliers.length === 0) { console.log('\nπŸŽ‰ No outliers detected - all items are well connected!'); } else { console.log(`\n🚨 ${chalk.red(outliers.length)} Semantic Outliers:`); outliers.forEach((outlier, index) => { console.log(`${index + 1}. ${outlier}`); }); console.log(`\nπŸ’‘ These items have similarity < ${argv.threshold} to their nearest neighbors`); } if (argv.output) { await saveToFile(argv.output, outliers, argv.format!); } } catch (error) { spinner.fail('πŸ’₯ Failed to detect outliers'); throw error; } } async function handleVisualizeCommand(neural: NeuralAPI, argv: CommandArguments): Promise { const spinner = ora('πŸ“Š Generating visualization data...').start(); try { const vizData = await neural.visualize({ dimensions: argv.dimensions as 2 | 3, maxNodes: argv.limit }); spinner.succeed('βœ… Visualization data generated'); console.log(`\nπŸ“Š Visualization Data (${vizData.format} layout):`); console.log(`πŸ“ Nodes: ${vizData.nodes.length}`); console.log(`πŸ”— Edges: ${vizData.edges.length}`); console.log(`🎯 Clusters: ${vizData.clusters?.length || 0}`); console.log(`πŸ“ Dimensions: ${vizData.layout?.dimensions}D`); if (argv.format === 'json') { console.log('\nData:'); console.log(JSON.stringify(vizData, null, 2)); } else { console.log('\n🎨 Style Settings:'); console.log(` Node Colors: ${vizData.style?.nodeColors}`); console.log(` Edge Width: ${vizData.style?.edgeWidth}`); console.log(` Labels: ${vizData.style?.labels}`); } if (argv.output) { await saveToFile(argv.output, vizData, 'json'); console.log(`\nπŸ’Ύ Visualization data saved to: ${chalk.green(argv.output)}`); } else { console.log(`\nπŸ’‘ Use --output to save visualization data for external tools`); } } catch (error) { spinner.fail('πŸ’₯ Failed to generate visualization'); throw error; } } async function saveToFile(filepath: string, data: any, format: string): Promise { const dir = path.dirname(filepath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } let output: string; switch (format) { case 'json': output = JSON.stringify(data, null, 2); break; case 'table': output = formatAsTable(data); break; default: output = JSON.stringify(data, null, 2); } fs.writeFileSync(filepath, output, 'utf8'); console.log(`πŸ’Ύ Saved to: ${chalk.green(filepath)}`); } function formatAsTable(data: any): string { // Simple table formatting - could be enhanced with a table library if (Array.isArray(data)) { return data.map((item, index) => `${index + 1}. ${JSON.stringify(item)}`).join('\n'); } return JSON.stringify(data, null, 2); } function showHelp(): void { console.log('\n🧠 Neural Similarity API Commands:'); console.log(''); console.log(' brainy neural similar Calculate similarity'); console.log(' brainy neural clusters Find semantic clusters'); console.log(' brainy neural hierarchy Show item hierarchy'); console.log(' brainy neural neighbors Find semantic neighbors'); console.log(' brainy neural path Find semantic path'); console.log(' brainy neural outliers Detect outliers'); console.log(' brainy neural visualize Generate visualization data'); console.log(''); console.log('Options:'); console.log(' --threshold, -t Similarity threshold (0-1)'); console.log(' --format, -f Output format (json|table|tree|graph)'); console.log(' --output, -o Save to file'); console.log(' --limit, -l Maximum results'); console.log(' --explain, -e Include explanations'); console.log(''); } export default neuralCommand;