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
|
```bash
|
||||||
# Set the model via environment variable (uses provider:model format)
|
# 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.
|
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
|
```python
|
||||||
# Anthropic
|
# 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)
|
# OpenAI (uses Responses API by default)
|
||||||
model=make_model("openai:gpt-5.5", max_tokens=128_000, reasoning={"effort": "medium"})
|
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
|
```python
|
||||||
from langchain_anthropic import ChatAnthropic
|
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(
|
return create_deep_agent(
|
||||||
model=model,
|
model=model,
|
||||||
|
|
@ -185,7 +185,7 @@ async def get_agent(config: RunnableConfig) -> Pregel:
|
||||||
|
|
||||||
if source == "slack":
|
if source == "slack":
|
||||||
# Faster model for Slack Q&A
|
# 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:
|
else:
|
||||||
# Full model for code changes from Linear
|
# Full model for code changes from Linear
|
||||||
model = make_model("openai:gpt-5.5", max_tokens=128_000, reasoning={"effort": "medium"})
|
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",
|
"default_effort": "high",
|
||||||
"supports_images": True,
|
"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",
|
"id": "openai:gpt-5.5",
|
||||||
"label": "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
|
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:
|
def _fallback_effort_for(model: ModelOption, effort: object) -> str | None:
|
||||||
if not isinstance(effort, str):
|
if not isinstance(effort, str):
|
||||||
return None
|
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:
|
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
|
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
|
dropped out of the supported set (e.g. an Opus minor-version bump), preferring
|
||||||
of falling through to the cross-provider global default. Preserves ``effort``
|
the same Claude family when available instead of falling through to the
|
||||||
when the fallback model supports it, otherwise uses that model's default
|
cross-provider global default. Preserves ``effort`` when the fallback model
|
||||||
effort. Returns ``None`` when no supported model shares the provider.
|
supports it, otherwise uses that model's default effort. Returns ``None`` when
|
||||||
|
no supported model shares the provider.
|
||||||
"""
|
"""
|
||||||
if not isinstance(model_id, str):
|
if not isinstance(model_id, str):
|
||||||
return None
|
return None
|
||||||
provider = _provider_of(model_id)
|
provider = _provider_of(model_id)
|
||||||
if provider is None:
|
if provider is None:
|
||||||
return 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:
|
for m in SUPPORTED_MODELS:
|
||||||
if _provider_of(m["id"]) == provider:
|
if _provider_of(m["id"]) == provider:
|
||||||
return m["id"], _fallback_effort_for(m, effort) or m["default_effort"]
|
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