Skip to main content
Glama
problem-complexity-analyzer.ts15.4 kB
/** * Problem Complexity Analyzer * * Analyzes problem complexity based on word count and patterns to scale * analysis depth appropriately. Simple problems get concise responses, * complex problems get thorough multi-step analysis. * * Requirements: 15.1, 15.2 */ /** * Complexity level enumeration * * Classifies problems into four complexity tiers that determine * the appropriate depth of analysis. */ export enum ComplexityLevel { /** Very simple, direct questions (e.g., "What is 2+2?") */ TRIVIAL = "trivial", /** Simple problems requiring minimal analysis */ SIMPLE = "simple", /** Moderate problems requiring structured analysis */ MODERATE = "moderate", /** Complex problems requiring thorough multi-step analysis */ COMPLEX = "complex", } /** * Factors contributing to complexity assessment * * Tracks individual factors that influence the overall complexity score. */ export interface ComplexityFactors { /** Word count of the problem statement */ wordCount: number; /** Number of distinct questions or parts */ questionCount: number; /** Density of technical terms (0-1) */ technicalDensity: number; /** Number of nested clauses or conditions */ nestedClauseCount: number; /** Whether problem involves multiple domains */ multiDomain: boolean; /** Whether problem requires temporal reasoning */ temporalReasoning: boolean; /** Whether problem involves trade-offs or comparisons */ hasTradeoffs: boolean; } /** * Result of complexity analysis * * Contains the complexity level, numeric score, contributing factors, * and recommended analysis depth. */ export interface ComplexityAnalysis { /** Classified complexity level */ level: ComplexityLevel; /** Numeric complexity score (0-1) */ score: number; /** Factors that contributed to the assessment */ factors: ComplexityFactors; /** Recommended analysis depth (1-5) */ recommendedDepth: number; /** Recommended number of reasoning steps */ recommendedSteps: number; /** Whether to include detailed sub-problem decomposition */ shouldDecompose: boolean; } /** * Simple question patterns that indicate trivial complexity */ const TRIVIAL_PATTERNS = [ /^what is \d+\s*[+\-*/]\s*\d+\??$/i, // "What is 2+2?" /^what('s| is) the (sum|difference|product|quotient) of \d+ and \d+\??$/i, /^how much is \d+\s*[+\-*/]\s*\d+\??$/i, /^define \w+\.?$/i, // "Define X" /^what does \w+ mean\??$/i, // "What does X mean?" /^what is (a|an|the) \w+\??$/i, // "What is a X?" /^is \w+ (true|false|correct|wrong)\??$/i, // "Is X true?" /^yes or no:/i, // "Yes or no: ..." /^true or false:/i, // "True or false: ..." ]; /** * Patterns indicating complex multi-part questions */ const COMPLEX_PATTERNS = [ /\b(and|or)\b.*\b(and|or)\b/i, // Multiple conjunctions /\b(compare|contrast|analyze|evaluate|assess)\b/i, /\b(trade-?off|pros and cons|advantages and disadvantages)\b/i, /\b(design|architect|implement|build|create) (a|an|the)? (system|application|platform|solution)\b/i, /\b(optimize|improve|enhance|scale)\b.*\b(while|without|maintaining)\b/i, /\b(if|when|unless|provided that|assuming)\b.*\b(then|otherwise|else)\b/i, /\b(first|second|third|finally|additionally|moreover|furthermore)\b/i, /\b(considering|given|taking into account)\b/i, ]; /** * Technical domain keywords */ const TECHNICAL_TERMS = new Set([ // Software engineering "api", "database", "algorithm", "architecture", "microservice", "kubernetes", "docker", "ci/cd", "deployment", "scalability", "latency", "throughput", "concurrency", "parallelism", "distributed", "cache", "queue", "async", "synchronous", "asynchronous", "middleware", "framework", "library", "dependency", "injection", "interface", "abstraction", "polymorphism", "inheritance", "encapsulation", "refactor", "optimization", "performance", // Data science / ML "machine learning", "neural network", "deep learning", "model", "training", "inference", "dataset", "feature", "regression", "classification", "clustering", "embedding", "transformer", "attention", "gradient", "backpropagation", // Business / Strategy "stakeholder", "roi", "kpi", "metric", "strategy", "roadmap", "milestone", "deliverable", "requirement", "specification", "constraint", "scope", // Security "authentication", "authorization", "encryption", "vulnerability", "exploit", "penetration", "firewall", "ssl", "tls", "certificate", "token", "oauth", ]); /** * Stop words to exclude from word count analysis */ const STOP_WORDS = new Set([ "the", "a", "an", "and", "or", "but", "in", "on", "at", "to", "for", "of", "with", "by", "from", "as", "is", "was", "are", "were", "been", "be", "have", "has", "had", "do", "does", "did", "will", "would", "could", "should", "may", "might", "must", "shall", "can", "need", "that", "this", "these", "those", "it", "its", "i", "we", "you", "they", "he", "she", "my", "our", "your", "their", "what", "which", "who", "whom", "how", "when", "where", "why", ]); /** * Problem Complexity Analyzer * * Analyzes problem statements to determine appropriate analysis depth. * Uses word count, pattern matching, and domain detection to classify * problems and recommend analysis parameters. */ export class ProblemComplexityAnalyzer { /** * Analyze problem complexity * * @param problem - Problem statement to analyze * @param context - Optional additional context * @returns Complexity analysis result */ analyze(problem: string, context?: string): ComplexityAnalysis { // Calculate individual factors const factors = this.calculateFactors(problem, context); // Calculate overall complexity score const score = this.calculateScore(factors, problem); // Determine complexity level const level = this.determineLevel(score, problem); // Calculate recommended parameters const recommendedDepth = this.calculateRecommendedDepth(level, factors); const recommendedSteps = this.calculateRecommendedSteps(level, factors); const shouldDecompose = this.shouldDecompose(level, factors); return { level, score, factors, recommendedDepth, recommendedSteps, shouldDecompose, }; } /** * Calculate complexity factors from problem text */ private calculateFactors(problem: string, context?: string): ComplexityFactors { const fullText = context ? `${problem} ${context}` : problem; return { wordCount: this.countMeaningfulWords(fullText), questionCount: this.countQuestions(problem), technicalDensity: this.calculateTechnicalDensity(fullText), nestedClauseCount: this.countNestedClauses(problem), multiDomain: this.detectMultipleDomains(fullText), temporalReasoning: this.detectTemporalReasoning(problem), hasTradeoffs: this.detectTradeoffs(problem), }; } /** * Count meaningful words (excluding stop words) */ private countMeaningfulWords(text: string): number { const words = text .toLowerCase() .replace(/[^\w\s]/g, " ") .split(/\s+/) .filter((w) => w.length > 1 && !STOP_WORDS.has(w)); return words.length; } /** * Count distinct questions in the pro */ private countQuestions(text: string): number { // Count question marks const questionMarks = (text.match(/\?/g) ?? []).length; // Count question words at sentence starts const questionStarts = ( text.match( /(?:^|[.!?]\s*)(what|who|when|where|why|how|which|can|could|would|should|is|are|do|does)/gi ) ?? [] ).length; // Count enumerated items (1., 2., a., b., etc.) const enumeratedItems = (text.match(/(?:^|\n)\s*(?:\d+\.|[a-z]\.|[-•])\s/gi) ?? []).length; return Math.max(1, questionMarks + Math.floor(questionStarts / 2) + enumeratedItems); } /** * Calculate density of technical terms */ private calculateTechnicalDensity(text: string): number { const words = text .toLowerCase() .replace(/[^\w\s-]/g, " ") .split(/\s+/) .filter((w) => w.length > 2); if (words.length === 0) return 0; let technicalCount = 0; for (const word of words) { if (TECHNICAL_TERMS.has(word)) { technicalCount++; } } // Also check for compound technical terms const textLower = text.toLowerCase(); for (const term of TECHNICAL_TERMS) { if (term.includes(" ") && textLower.includes(term)) { technicalCount++; } } return Math.min(1, technicalCount / Math.max(10, words.length / 5)); } /** * Count nested clauses and conditions */ private countNestedClauses(text: string): number { const clauseIndicators = [ /\b(if|when|while|unless|although|because|since|whereas|provided|assuming)\b/gi, /\b(that|which|who|whom|whose)\b/gi, /[,;]\s*(and|but|or|however|therefore|thus|hence)\b/gi, ]; let count = 0; for (const pattern of clauseIndicators) { const matches = text.match(pattern); if (matches) { count += matches.length; } } return count; } /** * Detect if problem spans multiple domains */ private detectMultipleDomains(text: string): boolean { const domains = { technical: /\b(code|software|system|api|database|server|application)\b/i, business: /\b(customer|revenue|cost|profit|market|strategy|stakeholder)\b/i, design: /\b(user|interface|experience|ux|ui|design|layout|visual)\b/i, data: /\b(data|analytics|metrics|report|dashboard|insight)\b/i, security: /\b(security|auth|permission|access|encrypt|protect)\b/i, operations: /\b(deploy|monitor|scale|maintain|operate|infrastructure)\b/i, }; let domainCount = 0; for (const pattern of Object.values(domains)) { if (pattern.test(text)) { domainCount++; } } return domainCount >= 2; } /** * Detect if problem requires temporal reasoning */ private detectTemporalReasoning(text: string): boolean { const temporalPatterns = [ /\b(before|after|during|while|until|since|when)\b.*\b(then|next|later|finally)\b/i, /\b(first|second|third|then|finally|eventually|subsequently)\b/i, /\b(timeline|schedule|deadline|milestone|phase|stage)\b/i, /\b(past|present|future|historical|upcoming|planned)\b/i, ]; return temporalPatterns.some((p) => p.test(text)); } /** * Detect if problem involves trade-offs */ private detectTradeoffs(text: string): boolean { const tradeoffPatterns = [ /\b(trade-?off|balance|versus|vs\.?|compared to)\b/i, /\b(pros and cons|advantages and disadvantages)\b/i, /\b(on one hand|on the other hand)\b/i, /\b(benefit|drawback|risk|reward)\b/i, /\b(optimize|maximize|minimize)\b.*\b(while|without|maintaining)\b/i, ]; return tradeoffPatterns.some((p) => p.test(text)); } /** * Calculate overall complexity score (0-1) */ private calculateScore(factors: ComplexityFactors, problem: string): number { // Handle empty or minimal content as trivial if (factors.wordCount === 0) { return 0.1; } // Check for trivial patterns first if (this.isTrivialProblem(problem)) { return 0.1; } let score = 0; // Word count contribution (0-0.35) - increased weight if (factors.wordCount < 5) { score += 0.05; } else if (factors.wordCount < 15) { score += 0.15; } else if (factors.wordCount < 30) { score += 0.25; } else if (factors.wordCount < 60) { score += 0.3; } else { score += 0.35; } // Question count contribution (0-0.15) score += Math.min(0.15, (factors.questionCount - 1) * 0.05); // Technical density contribution (0-0.25) - increased weight score += factors.technicalDensity * 0.25; // Nested clause contribution (0-0.1) score += Math.min(0.1, factors.nestedClauseCount * 0.02); // Multi-domain contribution (0.15) - increased weight if (factors.multiDomain) { score += 0.15; } // Temporal reasoning contribution (0.05) if (factors.temporalReasoning) { score += 0.05; } // Trade-offs contribution (0.1) - increased weight if (factors.hasTradeoffs) { score += 0.1; } // Check for complex patterns - boost score significantly if (COMPLEX_PATTERNS.some((p) => p.test(problem))) { score = Math.max(score, 0.7); } return Math.min(1, score); } /** * Check if problem matches trivial patterns */ private isTrivialProblem(problem: string): boolean { const trimmed = problem.trim(); return TRIVIAL_PATTERNS.some((p) => p.test(trimmed)); } /** * Determine complexity level from score */ private determineLevel(score: number, problem: string): ComplexityLevel { // Override for trivial patterns if (this.isTrivialProblem(problem)) { return ComplexityLevel.TRIVIAL; } // Empty or minimal content is trivial if (problem.trim().length === 0) { return ComplexityLevel.TRIVIAL; } if (score < 0.2) { return ComplexityLevel.TRIVIAL; } else if (score < 0.35) { return ComplexityLevel.SIMPLE; } else if (score < 0.65) { return ComplexityLevel.MODERATE; } else { return ComplexityLevel.COMPLEX; } } /** * Calculate recommended analysis depth (1-5) */ private calculateRecommendedDepth(level: ComplexityLevel, factors: ComplexityFactors): number { const baseDepth: Record<ComplexityLevel, number> = { [ComplexityLevel.TRIVIAL]: 1, [ComplexityLevel.SIMPLE]: 2, [ComplexityLevel.MODERATE]: 3, [ComplexityLevel.COMPLEX]: 4, }; let depth = baseDepth[level]; // Adjust for multi-domain problems if (factors.multiDomain && depth < 5) { depth++; } // Adjust for multiple questions if (factors.questionCount > 3 && depth < 5) { depth++; } return Math.min(5, depth); } /** * Calculate recommended number of reasoning steps */ private calculateRecommendedSteps(level: ComplexityLevel, factors: ComplexityFactors): number { const baseSteps: Record<ComplexityLevel, number> = { [ComplexityLevel.TRIVIAL]: 1, [ComplexityLevel.SIMPLE]: 2, [ComplexityLevel.MODERATE]: 4, [ComplexityLevel.COMPLEX]: 6, }; let steps = baseSteps[level]; // Add steps for each additional question steps += Math.max(0, factors.questionCount - 1); // Add steps for nested clauses steps += Math.floor(factors.nestedClauseCount / 3); // Cap at reasonable maximum return Math.min(10, steps); } /** * Determine if problem should be decomposed into sub-problems */ private shouldDecompose(level: ComplexityLevel, factors: ComplexityFactors): boolean { // Never decompose trivial problems if (level === ComplexityLevel.TRIVIAL) { return false; } // Simple problems only decompose if multi-part if (level === ComplexityLevel.SIMPLE) { return factors.questionCount > 2 || factors.multiDomain; } // Moderate and complex problems should decompose return true; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/keyurgolani/ThoughtMcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server