Chain of Draft (CoD) MCP Server
by stat-guy
"""
Complexity estimation module for the Chain of Draft MCP server.
Analyzes problems to determine appropriate word limits.
"""
class ComplexityEstimator:
"""
Estimates the complexity of a problem to determine appropriate word limits
for Chain of Draft reasoning steps.
"""
def __init__(self):
"""Initialize with domain-specific complexity rules."""
# Base complexity rules - default word limits per domain
self.domain_base_limits = {
"math": 6,
"logic": 5,
"common_sense": 4,
"physics": 7,
"chemistry": 6,
"biology": 5,
"code": 8,
"puzzle": 5,
"general": 5
}
# Keywords that might indicate complexity
self.complexity_indicators = {
"math": [
"integral", "derivative", "equation", "proof", "theorem", "calculus",
"matrix", "vector", "linear algebra", "probability", "statistics",
"geometric series", "differential", "polynomial", "factorial"
],
"logic": [
"if and only if", "necessary condition", "sufficient", "contradiction",
"syllogism", "premise", "fallacy", "converse", "counterexample",
"logical equivalence", "negation", "disjunction", "conjunction"
],
"code": [
"recursion", "algorithm", "complexity", "optimization", "function",
"class", "object", "inheritance", "polymorphism", "data structure",
"binary tree", "hash table", "graph", "dynamic programming"
],
"physics": [
"quantum", "relativity", "momentum", "force", "acceleration",
"energy", "thermodynamics", "electric field", "magnetic field",
"potential", "entropy", "wavelength", "frequency"
],
"chemistry": [
"reaction", "molecule", "compound", "element", "equilibrium",
"acid", "base", "oxidation", "reduction", "catalyst", "isomer"
],
"biology": [
"gene", "protein", "enzyme", "cell", "tissue", "organ", "system",
"metabolism", "photosynthesis", "respiration", "homeostasis"
],
"puzzle": [
"constraint", "sequence", "pattern", "rules", "probability",
"combination", "permutation", "optimal", "strategy"
]
}
async def estimate_complexity(self, problem, domain="general"):
"""
Estimate the complexity of a problem based on its characteristics.
Returns a recommended word limit per step.
"""
# Start with base word limit for domain
base_limit = self.domain_base_limits.get(domain.lower(), 5)
# Analyze problem length - longer problems often need more detailed reasoning
length_factor = min(len(problem.split()) / 50, 2) # Cap at doubling
# Check for complexity indicators
indicator_count = 0
indicators = self.complexity_indicators.get(domain.lower(), [])
for indicator in indicators:
if indicator.lower() in problem.lower():
indicator_count += 1
indicator_factor = min(1 + (indicator_count * 0.2), 1.8) # Cap at 80% increase
# Count the number of question marks - might indicate multi-part problems
question_factor = 1 + (problem.count("?") * 0.2)
# Simple complexity analysis based on sentence structure
sentences = [s for s in problem.split(".") if s.strip()]
words_per_sentence = len(problem.split()) / max(len(sentences), 1)
sentence_complexity_factor = min(words_per_sentence / 15, 1.5) # Complex sentences
# Special domain-specific adjustments
domain_factor = 1.0
if domain.lower() == "math" and any(term in problem.lower() for term in ["prove", "proof", "theorem"]):
domain_factor = 1.3 # Proofs need more explanation
elif domain.lower() == "code" and any(term in problem.lower() for term in ["implement", "function", "algorithm"]):
domain_factor = 1.2 # Code implementations need more detail
# Combine factors - take the maximum impact factor
impact_factor = max(length_factor, indicator_factor, question_factor,
sentence_complexity_factor, domain_factor)
# Apply the impact factor to the base limit
adjusted_limit = round(base_limit * impact_factor)
# Cap at reasonable bounds
return max(3, min(adjusted_limit, 10))
def analyze_problem(self, problem, domain="general"):
"""
Provide a detailed analysis of problem complexity factors.
Useful for debugging and understanding complexity estimates.
"""
base_limit = self.domain_base_limits.get(domain.lower(), 5)
# Word count analysis
word_count = len(problem.split())
length_factor = min(word_count / 50, 2)
# Indicator analysis
indicators = self.complexity_indicators.get(domain.lower(), [])
found_indicators = [ind for ind in indicators if ind.lower() in problem.lower()]
indicator_count = len(found_indicators)
indicator_factor = min(1 + (indicator_count * 0.2), 1.8)
# Question mark analysis
question_count = problem.count("?")
question_factor = 1 + (question_count * 0.2)
# Sentence complexity
sentences = [s for s in problem.split(".") if s.strip()]
words_per_sentence = word_count / max(len(sentences), 1)
sentence_complexity_factor = min(words_per_sentence / 15, 1.5)
return {
"domain": domain,
"base_limit": base_limit,
"word_count": word_count,
"length_factor": length_factor,
"indicator_count": indicator_count,
"found_indicators": found_indicators,
"indicator_factor": indicator_factor,
"question_count": question_count,
"question_factor": question_factor,
"sentence_count": len(sentences),
"words_per_sentence": words_per_sentence,
"sentence_complexity_factor": sentence_complexity_factor,
"estimated_complexity": max(3, min(round(base_limit * max(length_factor, indicator_factor, question_factor, sentence_complexity_factor)), 10))
}