@quantumai/quantum-cli-core
Version:
Quantum CLI Core - Multi-LLM Collaboration System
547 lines • 18.3 kB
JavaScript
/**
* @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