(cls, v, info)
| 308 | |
| 309 | @field_validator("model") |
| 310 | def validate_model_token_count(cls, v, info): # Renamed to avoid conflict |
| 311 | # Use the same logic as MessagesRequest validator |
| 312 | # NOTE: Pydantic validators might not share state easily if not class methods |
| 313 | # Re-implementing the logic here for clarity, could be refactored |
| 314 | original_model = v |
| 315 | new_model = v # Default to original value |
| 316 | |
| 317 | logger.debug( |
| 318 | f"📋 TOKEN COUNT VALIDATION: Original='{original_model}', Preferred='{PREFERRED_PROVIDER}', BIG='{BIG_MODEL}', SMALL='{SMALL_MODEL}'" |
| 319 | ) |
| 320 | |
| 321 | # Remove provider prefixes for easier matching |
| 322 | clean_v = v |
| 323 | if clean_v.startswith("anthropic/"): |
| 324 | clean_v = clean_v[10:] |
| 325 | elif clean_v.startswith("openai/"): |
| 326 | clean_v = clean_v[7:] |
| 327 | elif clean_v.startswith("gemini/"): |
| 328 | clean_v = clean_v[7:] |
| 329 | |
| 330 | # --- Mapping Logic --- START --- |
| 331 | mapped = False |
| 332 | # Map Haiku to SMALL_MODEL based on provider preference |
| 333 | if "haiku" in clean_v.lower(): |
| 334 | if PREFERRED_PROVIDER == "google" and SMALL_MODEL in GEMINI_MODELS: |
| 335 | new_model = f"gemini/{SMALL_MODEL}" |
| 336 | mapped = True |
| 337 | else: |
| 338 | new_model = f"openai/{SMALL_MODEL}" |
| 339 | mapped = True |
| 340 | |
| 341 | # Map Sonnet to BIG_MODEL based on provider preference |
| 342 | elif "sonnet" in clean_v.lower(): |
| 343 | if PREFERRED_PROVIDER == "google" and BIG_MODEL in GEMINI_MODELS: |
| 344 | new_model = f"gemini/{BIG_MODEL}" |
| 345 | mapped = True |
| 346 | else: |
| 347 | new_model = f"openai/{BIG_MODEL}" |
| 348 | mapped = True |
| 349 | |
| 350 | # Add prefixes to non-mapped models if they match known lists |
| 351 | elif not mapped: |
| 352 | if clean_v in GEMINI_MODELS and not v.startswith("gemini/"): |
| 353 | new_model = f"gemini/{clean_v}" |
| 354 | mapped = True # Technically mapped to add prefix |
| 355 | elif clean_v in OPENAI_MODELS and not v.startswith("openai/"): |
| 356 | new_model = f"openai/{clean_v}" |
| 357 | mapped = True # Technically mapped to add prefix |
| 358 | # --- Mapping Logic --- END --- |
| 359 | |
| 360 | if mapped: |
| 361 | logger.debug(f"📌 TOKEN COUNT MAPPING: '{original_model}' ➡️ '{new_model}'") |
| 362 | else: |
| 363 | if not v.startswith(("openai/", "gemini/", "anthropic/")): |
| 364 | logger.warning( |
| 365 | f"⚠️ No prefix or mapping rule for token count model: '{original_model}'. Using as is." |
| 366 | ) |
| 367 | new_model = v # Ensure we return the original if no rule applied |
nothing calls this directly
no outgoing calls
no test coverage detected