256 lines
6.0 KiB
Python
256 lines
6.0 KiB
Python
|
|
"""
|
||
|
|
Configuration for the Complexity Router.
|
||
|
|
|
||
|
|
Contains default keyword lists, weights, tier boundaries, and configuration classes.
|
||
|
|
All values are configurable via proxy config.yaml.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from enum import Enum
|
||
|
|
from typing import Dict, List, Optional
|
||
|
|
|
||
|
|
from pydantic import BaseModel, ConfigDict, Field
|
||
|
|
|
||
|
|
|
||
|
|
class ComplexityTier(str, Enum):
|
||
|
|
"""Complexity tiers for routing decisions."""
|
||
|
|
|
||
|
|
SIMPLE = "SIMPLE"
|
||
|
|
MEDIUM = "MEDIUM"
|
||
|
|
COMPLEX = "COMPLEX"
|
||
|
|
REASONING = "REASONING"
|
||
|
|
|
||
|
|
|
||
|
|
# ─── Default Keyword Lists ───
|
||
|
|
# Note: Keywords should be full words/phrases to avoid substring false positives.
|
||
|
|
# The matching logic uses word boundary detection for single-word keywords.
|
||
|
|
|
||
|
|
DEFAULT_CODE_KEYWORDS: List[str] = [
|
||
|
|
"function",
|
||
|
|
"class",
|
||
|
|
"def",
|
||
|
|
"const",
|
||
|
|
"let",
|
||
|
|
"var",
|
||
|
|
"import",
|
||
|
|
"export",
|
||
|
|
"return",
|
||
|
|
"async",
|
||
|
|
"await",
|
||
|
|
"try",
|
||
|
|
"catch",
|
||
|
|
"exception",
|
||
|
|
"error",
|
||
|
|
"debug",
|
||
|
|
"api",
|
||
|
|
"endpoint",
|
||
|
|
"request",
|
||
|
|
"response",
|
||
|
|
"database",
|
||
|
|
"sql",
|
||
|
|
"query",
|
||
|
|
"schema",
|
||
|
|
"algorithm",
|
||
|
|
"implement",
|
||
|
|
"refactor",
|
||
|
|
"optimize",
|
||
|
|
"python",
|
||
|
|
"javascript",
|
||
|
|
"typescript",
|
||
|
|
"java",
|
||
|
|
"rust",
|
||
|
|
"golang",
|
||
|
|
"react",
|
||
|
|
"vue",
|
||
|
|
"angular",
|
||
|
|
"node",
|
||
|
|
"docker",
|
||
|
|
"kubernetes",
|
||
|
|
"git",
|
||
|
|
"commit",
|
||
|
|
"merge",
|
||
|
|
"branch",
|
||
|
|
"pull request",
|
||
|
|
]
|
||
|
|
|
||
|
|
DEFAULT_REASONING_KEYWORDS: List[str] = [
|
||
|
|
"step by step",
|
||
|
|
"think through",
|
||
|
|
"let's think",
|
||
|
|
"reason through",
|
||
|
|
"analyze this",
|
||
|
|
"break down",
|
||
|
|
"explain your reasoning",
|
||
|
|
"show your work",
|
||
|
|
"chain of thought",
|
||
|
|
"think carefully",
|
||
|
|
"consider all",
|
||
|
|
"evaluate",
|
||
|
|
"pros and cons",
|
||
|
|
"compare and contrast",
|
||
|
|
"weigh the options",
|
||
|
|
"logical",
|
||
|
|
"deduce",
|
||
|
|
"infer",
|
||
|
|
"conclude",
|
||
|
|
]
|
||
|
|
|
||
|
|
DEFAULT_TECHNICAL_KEYWORDS: List[str] = [
|
||
|
|
"architecture",
|
||
|
|
"distributed",
|
||
|
|
"scalable",
|
||
|
|
"microservice",
|
||
|
|
"machine learning",
|
||
|
|
"neural network",
|
||
|
|
"deep learning",
|
||
|
|
"encryption",
|
||
|
|
"authentication",
|
||
|
|
"authorization",
|
||
|
|
"performance",
|
||
|
|
"latency",
|
||
|
|
"throughput",
|
||
|
|
"benchmark",
|
||
|
|
"concurrency",
|
||
|
|
"parallel",
|
||
|
|
"threading",
|
||
|
|
"memory",
|
||
|
|
"cpu",
|
||
|
|
"gpu",
|
||
|
|
"optimization",
|
||
|
|
"protocol",
|
||
|
|
"tcp",
|
||
|
|
"http",
|
||
|
|
"grpc",
|
||
|
|
"websocket",
|
||
|
|
"container",
|
||
|
|
"orchestration",
|
||
|
|
# Note: "async", "kubernetes", "docker" are in DEFAULT_CODE_KEYWORDS
|
||
|
|
]
|
||
|
|
|
||
|
|
DEFAULT_SIMPLE_KEYWORDS: List[str] = [
|
||
|
|
"what is",
|
||
|
|
"what's",
|
||
|
|
"define",
|
||
|
|
"definition of",
|
||
|
|
"who is",
|
||
|
|
"who was",
|
||
|
|
"when did",
|
||
|
|
"when was",
|
||
|
|
"where is",
|
||
|
|
"where was",
|
||
|
|
"how many",
|
||
|
|
"how much",
|
||
|
|
"yes or no",
|
||
|
|
"true or false",
|
||
|
|
"simple",
|
||
|
|
"brief",
|
||
|
|
"short",
|
||
|
|
"quick",
|
||
|
|
"hello",
|
||
|
|
"hi",
|
||
|
|
"hey",
|
||
|
|
"thanks",
|
||
|
|
"thank you",
|
||
|
|
"goodbye",
|
||
|
|
"bye",
|
||
|
|
"okay",
|
||
|
|
# Note: "ok" removed due to false positives (matches "token", "book", etc.)
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
# ─── Default Dimension Weights ───
|
||
|
|
|
||
|
|
DEFAULT_DIMENSION_WEIGHTS: Dict[str, float] = {
|
||
|
|
"tokenCount": 0.10, # Reduced - length is less important than content
|
||
|
|
"codePresence": 0.30, # High - code requests need capable models
|
||
|
|
"reasoningMarkers": 0.25, # High - explicit reasoning requests
|
||
|
|
"technicalTerms": 0.25, # High - technical content matters
|
||
|
|
"simpleIndicators": 0.05, # Low - don't over-penalize simple patterns
|
||
|
|
"multiStepPatterns": 0.03,
|
||
|
|
"questionComplexity": 0.02,
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
# ─── Default Tier Boundaries ───
|
||
|
|
|
||
|
|
DEFAULT_TIER_BOUNDARIES: Dict[str, float] = {
|
||
|
|
"simple_medium": 0.15, # Lower threshold to catch more MEDIUM cases
|
||
|
|
"medium_complex": 0.35, # Lower threshold to catch technical COMPLEX cases
|
||
|
|
"complex_reasoning": 0.60, # Reasoning tier reserved for explicit reasoning markers
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
# ─── Default Token Thresholds ───
|
||
|
|
|
||
|
|
DEFAULT_TOKEN_THRESHOLDS: Dict[str, int] = {
|
||
|
|
"simple": 15, # Only very short prompts (<15 tokens) are penalized
|
||
|
|
"complex": 400, # Long prompts (>400 tokens) get complexity boost
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
# ─── Default Tier to Model Mapping ───
|
||
|
|
|
||
|
|
DEFAULT_TIER_MODELS: Dict[str, str] = {
|
||
|
|
"SIMPLE": "gpt-4o-mini",
|
||
|
|
"MEDIUM": "gpt-4o",
|
||
|
|
"COMPLEX": "claude-sonnet-4-20250514",
|
||
|
|
"REASONING": "claude-sonnet-4-20250514",
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
class ComplexityRouterConfig(BaseModel):
|
||
|
|
"""Configuration for the ComplexityRouter."""
|
||
|
|
|
||
|
|
# Tier to model mapping
|
||
|
|
tiers: Dict[str, str] = Field(
|
||
|
|
default_factory=lambda: DEFAULT_TIER_MODELS.copy(),
|
||
|
|
description="Mapping of complexity tiers to model names",
|
||
|
|
)
|
||
|
|
|
||
|
|
# Tier boundaries (normalized scores)
|
||
|
|
tier_boundaries: Dict[str, float] = Field(
|
||
|
|
default_factory=lambda: DEFAULT_TIER_BOUNDARIES.copy(),
|
||
|
|
description="Score boundaries between tiers",
|
||
|
|
)
|
||
|
|
|
||
|
|
# Token count thresholds
|
||
|
|
token_thresholds: Dict[str, int] = Field(
|
||
|
|
default_factory=lambda: DEFAULT_TOKEN_THRESHOLDS.copy(),
|
||
|
|
description="Token count thresholds for simple/complex classification",
|
||
|
|
)
|
||
|
|
|
||
|
|
# Dimension weights
|
||
|
|
dimension_weights: Dict[str, float] = Field(
|
||
|
|
default_factory=lambda: DEFAULT_DIMENSION_WEIGHTS.copy(),
|
||
|
|
description="Weights for each scoring dimension",
|
||
|
|
)
|
||
|
|
|
||
|
|
# Keyword lists (overridable)
|
||
|
|
code_keywords: Optional[List[str]] = Field(
|
||
|
|
default=None,
|
||
|
|
description="Keywords indicating code-related content",
|
||
|
|
)
|
||
|
|
reasoning_keywords: Optional[List[str]] = Field(
|
||
|
|
default=None,
|
||
|
|
description="Keywords indicating reasoning-required content",
|
||
|
|
)
|
||
|
|
technical_keywords: Optional[List[str]] = Field(
|
||
|
|
default=None,
|
||
|
|
description="Keywords indicating technical content",
|
||
|
|
)
|
||
|
|
simple_keywords: Optional[List[str]] = Field(
|
||
|
|
default=None,
|
||
|
|
description="Keywords indicating simple/basic queries",
|
||
|
|
)
|
||
|
|
|
||
|
|
# Default model if scoring fails
|
||
|
|
default_model: Optional[str] = Field(
|
||
|
|
default=None,
|
||
|
|
description="Default model to use if tier cannot be determined",
|
||
|
|
)
|
||
|
|
|
||
|
|
model_config = ConfigDict(extra="allow") # Allow additional fields
|
||
|
|
|
||
|
|
|
||
|
|
# Combined default config
|
||
|
|
DEFAULT_COMPLEXITY_CONFIG = ComplexityRouterConfig()
|