UNPKG

@quantumai/quantum-cli-core

Version:

Quantum CLI Core - Multi-LLM Collaboration System

547 lines 18.3 kB
/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { QueryType } from '../types.js'; /** * Default configuration for query analysis */ export const DEFAULT_ANALYZER_CONFIG = { minClassificationConfidence: 0.6, keywordWeight: 0.4, structureWeight: 0.3, complexityWeight: 0.3, customDomains: {}, customFrameworks: {}, }; /** * Query analyzer that classifies and analyzes user queries for smart routing */ export class QueryAnalyzer { config; // Pattern databases for classification codePatterns = { keywords: [ 'function', 'class', 'method', 'variable', 'algorithm', 'debug', 'error', 'implement', 'code', 'programming', 'syntax', 'compile', 'runtime', 'refactor', 'optimize', 'performance', 'bug', 'fix', 'test', 'unit test', ], patterns: [ /```[\s\S]*?```/g, // Code blocks /`[^`]+`/g, // Inline code /\b(function|class|def|let|const|var)\s+\w+/gi, /\b(if|else|for|while|switch|case)\s*\(/gi, /\b(import|require|from|include)\s+/gi, /[{};()[\]]/g, // Code punctuation ], }; creativePatterns = { keywords: [ 'write', 'create', 'story', 'poem', 'essay', 'creative', 'imagine', 'brainstorm', 'ideas', 'marketing', 'content', 'blog', 'article', 'generate', 'draft', 'narrative', 'character', 'plot', 'theme', ], patterns: [ /\b(write|create|generate)\s+(a|an|some)\s+\w+/gi, /\b(story|poem|essay|article|blog|content)\b/gi, /\b(creative|imaginative|brainstorm|ideas)\b/gi, ], }; analysisPatterns = { keywords: [ 'analyze', 'analysis', 'compare', 'comparison', 'evaluate', 'assessment', 'pros and cons', 'advantages', 'disadvantages', 'benefits', 'drawbacks', 'review', 'examine', 'investigate', 'research', 'study', 'report', ], patterns: [ /\b(analyze|analysis|compare|comparison|evaluate|assessment)\b/gi, /\b(pros?\s+and\s+cons?|advantages?\s+and\s+disadvantages?)\b/gi, /\b(what\s+are\s+the|list\s+the|explain\s+the)\s+\w+/gi, ], }; securityPatterns = { keywords: [ 'security', 'vulnerability', 'exploit', 'attack', 'authentication', 'authorization', 'encryption', 'hash', 'password', 'secure', 'safety', 'penetration', 'injection', 'xss', 'csrf', 'sql injection', 'sanitize', ], patterns: [ /\b(security|vulnerability|exploit|attack)\b/gi, /\b(authentication|authorization|encryption)\b/gi, /\b(password|secure|safety|penetration)\b/gi, /\b(injection|xss|csrf|sanitize)\b/gi, ], }; // Programming language detection patterns languagePatterns = { javascript: [ /\b(javascript|js|node\.?js|npm|yarn)\b/gi, /\b(react|vue|angular|express)\b/gi, ], typescript: [/\b(typescript|ts)\b/gi, /\binterface\s+\w+/gi], python: [ /\b(python|py|pip|django|flask|pandas|numpy)\b/gi, /\bdef\s+\w+\(/gi, ], java: [/\b(java|spring|maven|gradle)\b/gi, /\bpublic\s+class\s+\w+/gi], csharp: [/\b(c#|csharp|\.net|asp\.net)\b/gi, /\bpublic\s+class\s+\w+/gi], go: [/\b(golang?|go)\b/gi, /\bfunc\s+\w+\(/gi], rust: [/\b(rust|cargo)\b/gi, /\bfn\s+\w+\(/gi], php: [/\b(php|laravel|symfony|composer)\b/gi, /\$\w+/g], ruby: [/\b(ruby|rails|gem)\b/gi, /\bdef\s+\w+/gi], swift: [/\b(swift|ios|xcode)\b/gi, /\bfunc\s+\w+\(/gi], kotlin: [/\b(kotlin|android)\b/gi], sql: [/\b(sql|mysql|postgresql|sqlite|select|insert|update|delete)\b/gi], }; // Framework and technology detection patterns frameworkPatterns = { react: [/\b(react|jsx|hooks|component)\b/gi], vue: [/\b(vue|vuejs|nuxt)\b/gi], angular: [/\b(angular|ng-|@angular)\b/gi], svelte: [/\b(svelte|sveltekit)\b/gi], express: [/\b(express|expressjs)\b/gi], django: [/\b(django|python)\b/gi], flask: [/\b(flask|python)\b/gi], spring: [/\b(spring|java)\b/gi], laravel: [/\b(laravel|php)\b/gi], rails: [/\b(rails|ruby)\b/gi], docker: [/\b(docker|container|dockerfile)\b/gi], kubernetes: [/\b(kubernetes|k8s|kubectl)\b/gi], aws: [/\b(aws|amazon|s3|ec2|lambda)\b/gi], azure: [/\b(azure|microsoft)\b/gi], gcp: [/\b(gcp|google\s+cloud)\b/gi], }; // Domain-specific keywords domainKeywords = { 'web-development': [ 'frontend', 'backend', 'fullstack', 'web', 'website', 'browser', 'dom', ], 'mobile-development': [ 'mobile', 'ios', 'android', 'app', 'smartphone', 'tablet', ], 'data-science': [ 'data', 'analytics', 'machine learning', 'ai', 'dataset', 'visualization', ], devops: [ 'deployment', 'ci/cd', 'pipeline', 'infrastructure', 'monitoring', 'logging', ], database: ['database', 'db', 'sql', 'nosql', 'schema', 'query', 'index'], api: ['api', 'rest', 'graphql', 'endpoint', 'http', 'request', 'response'], testing: [ 'test', 'testing', 'unit test', 'integration', 'e2e', 'automation', ], performance: [ 'performance', 'optimization', 'speed', 'memory', 'cpu', 'benchmark', ], architecture: [ 'architecture', 'design pattern', 'microservices', 'monolith', 'scalability', ], 'ui-ux': [ 'ui', 'ux', 'design', 'user interface', 'user experience', 'accessibility', ], }; constructor(config = {}) { this.config = { ...DEFAULT_ANALYZER_CONFIG, ...config }; } /** * Analyzes a query and returns classification and metadata */ analyze(query, _context) { const normalizedQuery = query.toLowerCase(); // Calculate type-specific scores const codeScore = this.calculateTypeScore(normalizedQuery, this.codePatterns); const creativeScore = this.calculateTypeScore(normalizedQuery, this.creativePatterns); const analysisScore = this.calculateTypeScore(normalizedQuery, this.analysisPatterns); const securityScore = this.calculateTypeScore(normalizedQuery, this.securityPatterns); // Determine primary type const typeScores = { [QueryType.CODE]: codeScore, [QueryType.CREATIVE]: creativeScore, [QueryType.ANALYSIS]: analysisScore, [QueryType.SECURITY]: securityScore, [QueryType.GENERAL]: 0.1, // Base score for general queries }; const [primaryType, confidence] = this.getBestMatch(typeScores); // Calculate complexity const complexity = this.calculateComplexity(query); // Detect language and frameworks const language = this.detectLanguage(query); const frameworks = this.detectFrameworks(query); // Detect domain const domain = this.detectDomain(normalizedQuery); // Extract keywords that influenced classification const keywords = this.extractInfluentialKeywords(normalizedQuery, primaryType); // Determine response requirements const expectedResponseLength = this.estimateResponseLength(query, complexity); const requiresCodeGeneration = this.requiresCodeGeneration(query, primaryType); const securitySensitive = securityScore > 0.3; // Suggest model capabilities const suggestedModelCapabilities = this.suggestModelCapabilities(primaryType, complexity, requiresCodeGeneration, securitySensitive, frameworks); return { type: primaryType, confidence, complexity, domain, language, frameworks, keywords, expectedResponseLength, requiresCodeGeneration, securitySensitive, suggestedModelCapabilities, }; } /** * Calculates a score for a specific query type based on patterns and keywords */ calculateTypeScore(query, patterns) { let score = 0; // Keyword matching const keywordMatches = patterns.keywords.filter((keyword) => query.includes(keyword.toLowerCase())).length; const keywordScore = (keywordMatches / patterns.keywords.length) * this.config.keywordWeight; // Pattern matching const patternMatches = patterns.patterns.filter((pattern) => pattern.test(query)).length; const patternScore = (patternMatches / patterns.patterns.length) * this.config.structureWeight; score = keywordScore + patternScore; return Math.min(score, 1.0); } /** * Finds the best matching type from type scores */ getBestMatch(typeScores) { let bestType = QueryType.GENERAL; let bestScore = typeScores[QueryType.GENERAL]; for (const [type, score] of Object.entries(typeScores)) { if (score > bestScore) { bestType = type; bestScore = score; } } return [bestType, bestScore]; } /** * Calculates query complexity based on multiple factors */ calculateComplexity(query) { let complexity = 0; // Length factor (longer queries tend to be more complex) const lengthFactor = Math.min(query.length / 1000, 0.3); complexity += lengthFactor; // Sentence count factor const sentences = query.split(/[.!?]+/).filter((s) => s.trim().length > 0); const sentenceFactor = Math.min(sentences.length / 10, 0.2); complexity += sentenceFactor; // Technical term density const technicalTerms = [ 'implement', 'algorithm', 'optimization', 'architecture', 'scalability', 'performance', 'integration', 'deployment', 'configuration', 'framework', ]; const technicalMatches = technicalTerms.filter((term) => query.toLowerCase().includes(term)).length; const technicalFactor = Math.min(technicalMatches / technicalTerms.length, 0.3); complexity += technicalFactor; // Multi-step indicator const stepIndicators = [ 'first', 'then', 'next', 'finally', 'step', 'phase', ]; const stepMatches = stepIndicators.filter((indicator) => query.toLowerCase().includes(indicator)).length; const stepFactor = Math.min(stepMatches / stepIndicators.length, 0.2); complexity += stepFactor; return Math.min(complexity, 1.0); } /** * Detects the primary programming language mentioned in the query */ detectLanguage(query) { const normalizedQuery = query.toLowerCase(); for (const [language, patterns] of Object.entries(this.languagePatterns)) { for (const pattern of patterns) { if (pattern.test(normalizedQuery)) { return language; } } } return undefined; } /** * Detects frameworks and technologies mentioned in the query */ detectFrameworks(query) { const normalizedQuery = query.toLowerCase(); const detectedFrameworks = []; for (const [framework, patterns] of Object.entries(this.frameworkPatterns)) { for (const pattern of patterns) { if (pattern.test(normalizedQuery)) { detectedFrameworks.push(framework); break; } } } // Add custom frameworks from config for (const [framework, patterns] of Object.entries(this.config.customFrameworks)) { for (const pattern of patterns) { if (pattern.test(normalizedQuery)) { detectedFrameworks.push(framework); break; } } } return detectedFrameworks; } /** * Detects the primary domain/subject area of the query */ detectDomain(query) { let bestDomain; let bestScore = 0; // Check built-in domains for (const [domain, keywords] of Object.entries(this.domainKeywords)) { const matches = keywords.filter((keyword) => query.includes(keyword.toLowerCase())).length; const score = matches / keywords.length; if (score > bestScore && score > 0.2) { bestScore = score; bestDomain = domain; } } // Check custom domains from config for (const [domain, keywords] of Object.entries(this.config.customDomains)) { const matches = keywords.filter((keyword) => query.includes(keyword.toLowerCase())).length; const score = matches / keywords.length; if (score > bestScore && score > 0.2) { bestScore = score; bestDomain = domain; } } return bestDomain; } /** * Extracts keywords that influenced the classification decision */ extractInfluentialKeywords(query, type) { const keywords = []; let patterns; switch (type) { case QueryType.CODE: patterns = this.codePatterns; break; case QueryType.CREATIVE: patterns = this.creativePatterns; break; case QueryType.ANALYSIS: patterns = this.analysisPatterns; break; case QueryType.SECURITY: patterns = this.securityPatterns; break; default: return keywords; } // Find matching keywords patterns.keywords.forEach((keyword) => { if (query.toLowerCase().includes(keyword.toLowerCase())) { keywords.push(keyword); } }); return keywords.slice(0, 5); // Limit to top 5 keywords } /** * Estimates the expected response length based on query characteristics */ estimateResponseLength(query, complexity) { if (complexity > 0.7 || query.length > 500) { return 'long'; } else if (complexity > 0.4 || query.length > 200) { return 'medium'; } else { return 'short'; } } /** * Determines if the query requires code generation */ requiresCodeGeneration(query, type) { if (type === QueryType.CODE) { return true; } const codeGenerationIndicators = [ 'write code', 'implement', 'create function', 'write function', 'code example', 'sample code', 'show me code', 'generate code', ]; return codeGenerationIndicators.some((indicator) => query.toLowerCase().includes(indicator)); } /** * Suggests optimal model capabilities based on analysis results */ suggestModelCapabilities(type, complexity, requiresCode, securitySensitive, frameworks) { const capabilities = ['text']; // Type-based capabilities switch (type) { case QueryType.CODE: capabilities.push('code', 'reasoning'); break; case QueryType.CREATIVE: capabilities.push('creative', 'language'); break; case QueryType.ANALYSIS: capabilities.push('reasoning', 'analysis'); break; case QueryType.SECURITY: capabilities.push('security', 'analysis', 'reasoning'); break; default: break; } // Complexity-based capabilities if (complexity > 0.6) { capabilities.push('complex-reasoning', 'multi-step'); } // Code generation requirement if (requiresCode) { capabilities.push('code-generation'); } // Security sensitivity if (securitySensitive) { capabilities.push('security-aware', 'safety-filtering'); } // Framework-specific capabilities if (frameworks.length > 0) { capabilities.push('framework-knowledge'); } return [...new Set(capabilities)]; // Remove duplicates } /** * Updates the analyzer configuration */ updateConfig(newConfig) { this.config = { ...this.config, ...newConfig }; } /** * Gets the current configuration */ getConfig() { return { ...this.config }; } } //# sourceMappingURL=query-analyzer.js.map