mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-07 16:19:09 +00:00
feat: add Sonnet 5 to model picker (#1651)
* chore: update Sonnet examples to Sonnet 5 Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com> * chore: add Sonnet 5 to model picker Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com> --------- Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
parent
e1d85526b6
commit
289f5e3abf
3 changed files with 68 additions and 9 deletions
|
|
@ -140,7 +140,7 @@ The model is configured in the `get_agent()` function in `agent/server.py`. By d
|
|||
|
||||
```bash
|
||||
# Set the model via environment variable (uses provider:model format)
|
||||
LLM_MODEL_ID="anthropic:claude-sonnet-4-6"
|
||||
LLM_MODEL_ID="anthropic:claude-sonnet-5"
|
||||
```
|
||||
|
||||
If `LLM_MODEL_ID` is not set, the default model (`openai:gpt-5.5`) is used.
|
||||
|
|
@ -153,7 +153,7 @@ Use the `provider:model` format:
|
|||
|
||||
```python
|
||||
# Anthropic
|
||||
model=make_model("anthropic:claude-sonnet-4-6", temperature=0, max_tokens=16_000)
|
||||
model=make_model("anthropic:claude-sonnet-5", temperature=0, max_tokens=16_000)
|
||||
|
||||
# OpenAI (uses Responses API by default)
|
||||
model=make_model("openai:gpt-5.5", max_tokens=128_000, reasoning={"effort": "medium"})
|
||||
|
|
@ -167,7 +167,7 @@ The `make_model()` helper in `agent/utils/model.py` wraps `langchain.chat_models
|
|||
```python
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
|
||||
model = ChatAnthropic(model_name="claude-sonnet-4-6", temperature=0, max_tokens=16_000)
|
||||
model = ChatAnthropic(model_name="claude-sonnet-5", temperature=0, max_tokens=16_000)
|
||||
|
||||
return create_deep_agent(
|
||||
model=model,
|
||||
|
|
@ -185,7 +185,7 @@ async def get_agent(config: RunnableConfig) -> Pregel:
|
|||
|
||||
if source == "slack":
|
||||
# Faster model for Slack Q&A
|
||||
model = make_model("anthropic:claude-sonnet-4-6", temperature=0, max_tokens=16_000)
|
||||
model = make_model("anthropic:claude-sonnet-5", temperature=0, max_tokens=16_000)
|
||||
else:
|
||||
# Full model for code changes from Linear
|
||||
model = make_model("openai:gpt-5.5", max_tokens=128_000, reasoning={"effort": "medium"})
|
||||
|
|
|
|||
|
|
@ -21,6 +21,13 @@ SUPPORTED_MODELS: list[ModelOption] = [
|
|||
"default_effort": "high",
|
||||
"supports_images": True,
|
||||
},
|
||||
{
|
||||
"id": "anthropic:claude-sonnet-5",
|
||||
"label": "Sonnet 5",
|
||||
"efforts": ["low", "medium", "high", "xhigh", "max"],
|
||||
"default_effort": "high",
|
||||
"supports_images": True,
|
||||
},
|
||||
{
|
||||
"id": "openai:gpt-5.5",
|
||||
"label": "GPT-5.5",
|
||||
|
|
@ -83,6 +90,16 @@ def _provider_of(model_id: str) -> str | None:
|
|||
return provider if rest else None
|
||||
|
||||
|
||||
def _claude_family_of(model_id: str) -> str | None:
|
||||
provider, _, name = model_id.partition(":")
|
||||
if provider != "anthropic" or not name.startswith("claude-"):
|
||||
return None
|
||||
parts = name.split("-")
|
||||
if len(parts) < 2:
|
||||
return None
|
||||
return "-".join(parts[:2])
|
||||
|
||||
|
||||
def _fallback_effort_for(model: ModelOption, effort: object) -> str | None:
|
||||
if not isinstance(effort, str):
|
||||
return None
|
||||
|
|
@ -98,19 +115,25 @@ def _fallback_effort_for(model: ModelOption, effort: object) -> str | None:
|
|||
|
||||
|
||||
def provider_fallback_pair(model_id: object, effort: object = None) -> tuple[str, str] | None:
|
||||
"""Newest supported ``(model_id, effort)`` for the same provider as ``model_id``.
|
||||
"""Newest supported ``(model_id, effort)`` for the same provider/family.
|
||||
|
||||
Keeps a stored selection on its original provider when its exact id has
|
||||
dropped out of the supported set (e.g. an Opus minor-version bump), instead
|
||||
of falling through to the cross-provider global default. Preserves ``effort``
|
||||
when the fallback model supports it, otherwise uses that model's default
|
||||
effort. Returns ``None`` when no supported model shares the provider.
|
||||
dropped out of the supported set (e.g. an Opus minor-version bump), preferring
|
||||
the same Claude family when available instead of falling through to the
|
||||
cross-provider global default. Preserves ``effort`` when the fallback model
|
||||
supports it, otherwise uses that model's default effort. Returns ``None`` when
|
||||
no supported model shares the provider.
|
||||
"""
|
||||
if not isinstance(model_id, str):
|
||||
return None
|
||||
provider = _provider_of(model_id)
|
||||
if provider is None:
|
||||
return None
|
||||
family = _claude_family_of(model_id)
|
||||
if family is not None:
|
||||
for m in SUPPORTED_MODELS:
|
||||
if _provider_of(m["id"]) == provider and _claude_family_of(m["id"]) == family:
|
||||
return m["id"], _fallback_effort_for(m, effort) or m["default_effort"]
|
||||
for m in SUPPORTED_MODELS:
|
||||
if _provider_of(m["id"]) == provider:
|
||||
return m["id"], _fallback_effort_for(m, effort) or m["default_effort"]
|
||||
|
|
|
|||
36
tests/test_anthropic_model.py
Normal file
36
tests/test_anthropic_model.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import pytest
|
||||
|
||||
from agent.dashboard.options import SUPPORTED_MODELS, provider_fallback_pair
|
||||
from agent.utils.model import provider_model_kwargs
|
||||
|
||||
SONNET_5_ID = "anthropic:claude-sonnet-5"
|
||||
|
||||
|
||||
def test_sonnet_5_is_supported_with_documented_efforts() -> None:
|
||||
sonnet = next(m for m in SUPPORTED_MODELS if m["id"] == SONNET_5_ID)
|
||||
assert sonnet["label"] == "Sonnet 5"
|
||||
assert sonnet["efforts"] == ["low", "medium", "high", "xhigh", "max"]
|
||||
assert sonnet["default_effort"] == "high"
|
||||
assert sonnet["supports_images"] is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize("effort", ["low", "medium", "high", "xhigh", "max"])
|
||||
def test_sonnet_5_efforts_map_to_anthropic_kwargs(effort: str) -> None:
|
||||
kwargs = provider_model_kwargs(SONNET_5_ID, effort, max_tokens=16_000)
|
||||
assert kwargs["max_tokens"] == 16_000
|
||||
assert kwargs["effort"] == effort
|
||||
assert kwargs["thinking"] == {"type": "adaptive", "display": "summarized"}
|
||||
|
||||
|
||||
def test_sonnet_46_fallback_uses_sonnet_5() -> None:
|
||||
assert provider_fallback_pair("anthropic:claude-sonnet-4-6", "xhigh") == (
|
||||
SONNET_5_ID,
|
||||
"xhigh",
|
||||
)
|
||||
|
||||
|
||||
def test_opus_fallback_stays_on_opus_family() -> None:
|
||||
assert provider_fallback_pair("anthropic:claude-opus-4-7", "xhigh") == (
|
||||
"anthropic:claude-opus-4-8",
|
||||
"xhigh",
|
||||
)
|
||||
Loading…
Add table
Reference in a new issue