Python 64.6%
TypeScript 33.7%
CSS 0.8%
1"""Model routing per task. Professor overrides (DB) take precedence over env config."""23from __future__ import annotations45from dataclasses import dataclass, field6from typing import Any78from app.core.config import Settings, get_settings91011@dataclass12class RoutePlan:13 models: list[str]14 temperature: float15 reasoning: dict[str, Any] | None = None16 response_format: dict[str, Any] | None = None17 extra: dict[str, Any] = field(default_factory=dict)181920class ModelRouter:21 def __init__(self, settings: Settings | None = None) -> None:22 self.s = settings or get_settings()23 self.overrides: dict[str, str] = {} # e.g. {"primary": "anthropic/claude-opus-4.6"}24 self.budget_exceeded = False2526 def primary(self) -> str:27 return self.overrides.get("primary") or self.s.MODEL_TUTOR_PRIMARY2829 def plan(self, task: str, deep: bool = False) -> RoutePlan:30 s = self.s31 if self.budget_exceeded and task in {"tutor", "reasoning", "vision", "quiz"}:32 return RoutePlan([s.MODEL_FAST], 0.3)33 if (task == "tutor" and deep) or task == "reasoning":34 return RoutePlan([s.MODEL_REASONING, self.primary()], 0.2, {"effort": "high"})35 if task == "tutor":36 return RoutePlan([self.primary(), s.MODEL_TUTOR_FALLBACK], 0.3)37 if task == "fast":38 return RoutePlan([s.MODEL_FAST], 0.0)39 if task == "vision":40 return RoutePlan([s.MODEL_VISION, s.MODEL_TUTOR_FALLBACK], 0.2)41 if task == "quiz":42 return RoutePlan([self.primary(), s.MODEL_TUTOR_FALLBACK], 0.4,43 response_format={"type": "json_object"})44 return RoutePlan([self.primary(), s.MODEL_TUTOR_FALLBACK], 0.3)454647router = ModelRouter()48