This repository has been archived on 2026-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
orchestrator/models.py
Adam Moussa 3638d6ba96 Bump Sonnet model ID to claude-sonnet-4-6
claude-sonnet-4-20250514 reaches EOL 2026-06-15. Bumping ahead of the
deadline while the centralized models.py constant makes it a one-line
change. Smoke-tested via run.py --route-only — no deprecation warning,
router behavior unchanged.
2026-05-15 13:14:18 -04:00

104 lines
2.7 KiB
Python

import os
from langchain_anthropic import ChatAnthropic
from langchain_core.runnables import Runnable
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_openai import ChatOpenAI
# Model IDs — single source of truth. Bump here when families ship new revs.
CLAUDE_SONNET = "claude-sonnet-4-6"
CLAUDE_HAIKU = "claude-haiku-4-5-20251001"
OPENAI_CROSS_REVIEWER = "gpt-4.1"
GEMINI_SCANNER = "gemini-2.5-pro"
DEEPSEEK_FAST_CODER = "deepseek-coder"
DEEPSEEK_BASE_URL = "https://api.deepseek.com/v1"
def _collect_retriable_exceptions() -> tuple[type[BaseException], ...]:
excs: list[type[BaseException]] = []
try:
import anthropic
excs.extend(
[
anthropic.APIConnectionError,
anthropic.RateLimitError,
anthropic.InternalServerError,
]
)
except ImportError:
pass
try:
import openai
excs.extend(
[
openai.APIConnectionError,
openai.RateLimitError,
openai.InternalServerError,
]
)
except ImportError:
pass
try:
from google.api_core import exceptions as google_exceptions
excs.extend(
[
google_exceptions.ResourceExhausted,
google_exceptions.InternalServerError,
google_exceptions.ServiceUnavailable,
google_exceptions.DeadlineExceeded,
google_exceptions.GatewayTimeout,
]
)
except ImportError:
pass
return tuple(excs)
RETRIABLE_EXCEPTIONS = _collect_retriable_exceptions()
def with_retries(runnable: Runnable) -> Runnable:
"""Wrap an LLM runnable with up to 2 retries on transient provider errors."""
if not RETRIABLE_EXCEPTIONS:
return runnable
return runnable.with_retry(
retry_if_exception_type=RETRIABLE_EXCEPTIONS,
stop_after_attempt=3,
wait_exponential_jitter=True,
)
def get_orchestrator():
return ChatAnthropic(model=CLAUDE_SONNET, temperature=0)
def get_implementer():
return ChatAnthropic(model=CLAUDE_SONNET, temperature=0)
def get_reviewer():
return ChatAnthropic(model=CLAUDE_SONNET, temperature=0)
def get_researcher():
return ChatAnthropic(model=CLAUDE_HAIKU, temperature=0)
def get_cross_reviewer():
return ChatOpenAI(model=OPENAI_CROSS_REVIEWER, temperature=0.2)
def get_scanner():
return ChatGoogleGenerativeAI(model=GEMINI_SCANNER, temperature=0)
def get_fast_coder():
return ChatOpenAI(
model=DEEPSEEK_FAST_CODER,
base_url=DEEPSEEK_BASE_URL,
api_key=os.getenv("DEEPSEEK_API_KEY"),
temperature=0,
)