mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-07 21:08:34 +03:00
fix(anthropic): support Opus 5 effort controls (#5236)
This commit is contained in:
@@ -4,6 +4,8 @@ from __future__ import annotations
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from nanobot.providers.anthropic_provider import AnthropicProvider
|
||||
|
||||
|
||||
@@ -65,17 +67,24 @@ def test_none_does_not_enable_thinking() -> None:
|
||||
assert kw["temperature"] == 0.7
|
||||
|
||||
|
||||
def test_empty_effort_does_not_enable_thinking() -> None:
|
||||
kw = _build(_make_provider(), "")
|
||||
assert "thinking" not in kw
|
||||
assert kw["temperature"] == 0.7
|
||||
|
||||
|
||||
def test_opus_4_7_omits_temperature_adaptive() -> None:
|
||||
kw = _build(_make_provider("claude-opus-4-7"), "adaptive")
|
||||
assert "temperature" not in kw
|
||||
assert kw["thinking"] == {"type": "adaptive"}
|
||||
|
||||
|
||||
def test_opus_4_7_omits_temperature_enabled() -> None:
|
||||
"""Enabled thinking (high) must also omit temperature for opus-4-7."""
|
||||
def test_opus_4_7_high_uses_adaptive_effort() -> None:
|
||||
kw = _build(_make_provider("claude-opus-4-7"), "high", max_tokens=4096)
|
||||
assert "temperature" not in kw
|
||||
assert kw["thinking"]["type"] == "enabled"
|
||||
assert kw["thinking"] == {"type": "adaptive"}
|
||||
assert kw["output_config"] == {"effort": "high"}
|
||||
assert kw["max_tokens"] == 4096
|
||||
|
||||
|
||||
def test_opus_4_7_omits_temperature_none() -> None:
|
||||
@@ -90,9 +99,11 @@ def test_opus_4_8_omits_temperature_adaptive() -> None:
|
||||
assert "temperature" not in kw
|
||||
|
||||
|
||||
def test_opus_4_8_omits_temperature_enabled() -> None:
|
||||
def test_opus_4_8_high_uses_adaptive_effort() -> None:
|
||||
kw = _build(_make_provider("claude-opus-4-8"), "high", max_tokens=4096)
|
||||
assert "temperature" not in kw
|
||||
assert kw["thinking"] == {"type": "adaptive"}
|
||||
assert kw["output_config"] == {"effort": "high"}
|
||||
|
||||
|
||||
def test_opus_4_8_omits_temperature_none() -> None:
|
||||
@@ -105,9 +116,11 @@ def test_fable_omits_temperature_adaptive() -> None:
|
||||
assert "temperature" not in kw
|
||||
|
||||
|
||||
def test_fable_omits_temperature_enabled() -> None:
|
||||
def test_fable_high_uses_adaptive_effort() -> None:
|
||||
kw = _build(_make_provider("claude-fable-5"), "high", max_tokens=4096)
|
||||
assert "temperature" not in kw
|
||||
assert kw["thinking"] == {"type": "adaptive"}
|
||||
assert kw["output_config"] == {"effort": "high"}
|
||||
|
||||
|
||||
def test_fable_omits_temperature_none() -> None:
|
||||
@@ -121,16 +134,67 @@ def test_sonnet_5_omits_temperature_adaptive() -> None:
|
||||
assert kw["thinking"] == {"type": "adaptive"}
|
||||
|
||||
|
||||
def test_sonnet_5_omits_temperature_enabled() -> None:
|
||||
def test_sonnet_5_high_uses_adaptive_effort() -> None:
|
||||
kw = _build(_make_provider("claude-sonnet-5"), "high", max_tokens=4096)
|
||||
assert "temperature" not in kw
|
||||
assert kw["thinking"]["type"] == "enabled"
|
||||
assert kw["thinking"] == {"type": "adaptive"}
|
||||
assert kw["output_config"] == {"effort": "high"}
|
||||
|
||||
|
||||
def test_sonnet_5_omits_temperature_none() -> None:
|
||||
kw = _build(_make_provider("anthropic/claude-sonnet-5"), None)
|
||||
kw = _build(_make_provider("anthropic/claude-sonnet-5"), "none")
|
||||
assert "temperature" not in kw
|
||||
assert kw["thinking"] == {"type": "disabled"}
|
||||
assert "output_config" not in kw
|
||||
|
||||
|
||||
def test_mythos_preview_omits_temperature_but_keeps_manual_budget() -> None:
|
||||
kw = _build(_make_provider("claude-mythos-preview"), "high", max_tokens=4096)
|
||||
assert "temperature" not in kw
|
||||
assert kw["thinking"] == {"type": "enabled", "budget_tokens": 8192}
|
||||
assert "output_config" not in kw
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reasoning_effort", [None, "none", "adaptive", "low", "medium", "high", "xhigh", "max"]
|
||||
)
|
||||
def test_opus_5_omits_temperature(reasoning_effort: str | None) -> None:
|
||||
kw = _build(_make_provider("claude-opus-5"), reasoning_effort)
|
||||
assert "temperature" not in kw
|
||||
|
||||
|
||||
def test_opus_5_none_disables_default_thinking() -> None:
|
||||
kw = _build(_make_provider("claude-opus-5"), "none")
|
||||
assert kw["thinking"] == {"type": "disabled"}
|
||||
assert "output_config" not in kw
|
||||
|
||||
|
||||
def test_opus_5_unset_preserves_provider_default() -> None:
|
||||
kw = _build(_make_provider("claude-opus-5"), None)
|
||||
assert "thinking" not in kw
|
||||
assert "output_config" not in kw
|
||||
|
||||
|
||||
@pytest.mark.parametrize("reasoning_effort", ["low", "medium", "high", "xhigh", "max"])
|
||||
def test_opus_5_uses_adaptive_thinking_with_effort(reasoning_effort: str) -> None:
|
||||
kw = _build(_make_provider("claude-opus-5"), reasoning_effort, max_tokens=4096)
|
||||
assert kw["thinking"] == {"type": "adaptive"}
|
||||
assert kw["output_config"] == {"effort": reasoning_effort}
|
||||
assert kw["max_tokens"] == 4096
|
||||
|
||||
|
||||
def test_dated_opus_5_model_uses_family_capabilities() -> None:
|
||||
kw = _build(_make_provider("claude-opus-5-20260724"), "medium")
|
||||
assert "temperature" not in kw
|
||||
assert kw["thinking"] == {"type": "adaptive"}
|
||||
assert kw["output_config"] == {"effort": "medium"}
|
||||
|
||||
|
||||
def test_dated_opus_4_model_does_not_treat_date_as_minor_version() -> None:
|
||||
kw = _build(_make_provider("claude-opus-4-20250514"), "high")
|
||||
assert kw["temperature"] == 1.0
|
||||
assert kw["thinking"] == {"type": "enabled", "budget_tokens": 8192}
|
||||
assert "output_config" not in kw
|
||||
|
||||
|
||||
def test_ordinary_model_sends_temperature() -> None:
|
||||
|
||||
Reference in New Issue
Block a user