Files
2026-03-26 20:06:14 +08:00

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()