202 lines
9.2 KiB
Python
202 lines
9.2 KiB
Python
import os
|
|
from typing import Literal
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from openai.types.shared.reasoning import Reasoning
|
|
|
|
from agents import Agent
|
|
from agents.model_settings import ModelSettings
|
|
from agents.models import (
|
|
get_default_model,
|
|
get_default_model_settings,
|
|
gpt_5_reasoning_settings_required,
|
|
is_gpt_5_default,
|
|
)
|
|
|
|
|
|
def _gpt_5_default_settings(
|
|
reasoning_effort: Literal["none", "low", "medium"] | None,
|
|
) -> ModelSettings:
|
|
if reasoning_effort is None:
|
|
return ModelSettings(verbosity="low")
|
|
return ModelSettings(reasoning=Reasoning(effort=reasoning_effort), verbosity="low")
|
|
|
|
|
|
def test_default_model_is_gpt_5_4_mini():
|
|
assert get_default_model() == "gpt-5.4-mini"
|
|
assert is_gpt_5_default() is True
|
|
assert gpt_5_reasoning_settings_required(get_default_model()) is True
|
|
assert get_default_model_settings() == _gpt_5_default_settings("none")
|
|
|
|
|
|
@patch.dict(os.environ, {"OPENAI_DEFAULT_MODEL": "gpt-5.4"})
|
|
def test_is_gpt_5_default_with_real_model_name():
|
|
assert get_default_model() == "gpt-5.4"
|
|
assert is_gpt_5_default() is True
|
|
|
|
|
|
@patch.dict(os.environ, {"OPENAI_DEFAULT_MODEL": "gpt-4.1"})
|
|
def test_is_gpt_5_default_returns_false_for_non_gpt_5_default_model():
|
|
assert get_default_model() == "gpt-4.1"
|
|
assert is_gpt_5_default() is False
|
|
|
|
|
|
def test_gpt_5_reasoning_settings_required_detects_gpt_5_models_while_ignoring_chat_latest():
|
|
assert gpt_5_reasoning_settings_required("gpt-5") is True
|
|
assert gpt_5_reasoning_settings_required("gpt-5.1") is True
|
|
assert gpt_5_reasoning_settings_required("gpt-5.2") is True
|
|
assert gpt_5_reasoning_settings_required("gpt-5.2-codex") is True
|
|
assert gpt_5_reasoning_settings_required("gpt-5.2-pro") is True
|
|
assert gpt_5_reasoning_settings_required("gpt-5.4-pro") is True
|
|
assert gpt_5_reasoning_settings_required("gpt-5.5") is True
|
|
assert gpt_5_reasoning_settings_required("gpt-5-mini") is True
|
|
assert gpt_5_reasoning_settings_required("gpt-5-nano") is True
|
|
assert gpt_5_reasoning_settings_required("gpt-5-chat-latest") is False
|
|
assert gpt_5_reasoning_settings_required("gpt-5.1-chat-latest") is False
|
|
assert gpt_5_reasoning_settings_required("gpt-5.2-chat-latest") is False
|
|
assert gpt_5_reasoning_settings_required("gpt-5.3-chat-latest") is False
|
|
|
|
|
|
def test_gpt_5_reasoning_settings_required_returns_false_for_non_gpt_5_models():
|
|
assert gpt_5_reasoning_settings_required("gpt-4.1") is False
|
|
|
|
|
|
def test_get_default_model_settings_returns_none_reasoning_defaults_for_gpt_5_1_models():
|
|
assert get_default_model_settings("gpt-5.1") == _gpt_5_default_settings("none")
|
|
assert get_default_model_settings("gpt-5.1-2025-11-13") == _gpt_5_default_settings("none")
|
|
|
|
|
|
def test_get_default_model_settings_returns_none_reasoning_defaults_for_gpt_5_2_models():
|
|
assert get_default_model_settings("gpt-5.2") == _gpt_5_default_settings("none")
|
|
assert get_default_model_settings("gpt-5.2-2025-12-11") == _gpt_5_default_settings("none")
|
|
|
|
|
|
def test_get_default_model_settings_returns_none_reasoning_defaults_for_gpt_5_3_codex_models():
|
|
assert get_default_model_settings("gpt-5.3-codex") == _gpt_5_default_settings("none")
|
|
|
|
|
|
def test_get_default_model_settings_returns_none_reasoning_defaults_for_gpt_5_4_models():
|
|
assert get_default_model_settings("gpt-5.4") == _gpt_5_default_settings("none")
|
|
|
|
|
|
def test_get_default_model_settings_returns_none_reasoning_defaults_for_gpt_5_4_snapshot_families():
|
|
assert get_default_model_settings("gpt-5.4-2026-03-05") == _gpt_5_default_settings("none")
|
|
assert get_default_model_settings("gpt-5.4-mini-2026-03-17") == _gpt_5_default_settings("none")
|
|
assert get_default_model_settings("gpt-5.4-nano-2026-03-17") == _gpt_5_default_settings("none")
|
|
|
|
|
|
def test_get_default_model_settings_returns_none_reasoning_defaults_for_gpt_5_4_mini_and_nano():
|
|
assert get_default_model_settings("gpt-5.4-mini") == _gpt_5_default_settings("none")
|
|
assert get_default_model_settings("gpt-5.4-nano") == _gpt_5_default_settings("none")
|
|
|
|
|
|
def test_get_default_model_settings_returns_none_reasoning_defaults_for_gpt_5_5_models():
|
|
assert get_default_model_settings("gpt-5.5") == _gpt_5_default_settings("none")
|
|
assert get_default_model_settings("gpt-5.5-2026-04-23") == _gpt_5_default_settings("none")
|
|
|
|
|
|
@pytest.mark.parametrize("model", ["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"])
|
|
def test_get_default_model_settings_returns_none_reasoning_defaults_for_gpt_5_6_models(
|
|
model: str,
|
|
):
|
|
assert get_default_model_settings(model) == _gpt_5_default_settings("none")
|
|
|
|
|
|
@pytest.mark.parametrize("model", ["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"])
|
|
def test_agent_uses_gpt_5_6_model_settings_from_default_model_env(
|
|
model: str, monkeypatch: pytest.MonkeyPatch
|
|
):
|
|
monkeypatch.setenv("OPENAI_DEFAULT_MODEL", model.upper())
|
|
|
|
agent = Agent(name="test")
|
|
|
|
assert get_default_model() == model
|
|
assert agent.model is None
|
|
assert agent.model_settings == _gpt_5_default_settings("none")
|
|
|
|
|
|
def test_get_default_model_settings_returns_low_reasoning_defaults_for_base_gpt_5():
|
|
assert get_default_model_settings("gpt-5") == _gpt_5_default_settings("low")
|
|
assert get_default_model_settings("gpt-5-2025-08-07") == _gpt_5_default_settings("low")
|
|
|
|
|
|
def test_get_default_model_settings_returns_low_reasoning_defaults_for_gpt_5_2_codex():
|
|
assert get_default_model_settings("gpt-5.2-codex") == _gpt_5_default_settings("low")
|
|
|
|
|
|
def test_get_default_model_settings_returns_medium_reasoning_defaults_for_gpt_5_pro_models():
|
|
assert get_default_model_settings("gpt-5.2-pro") == _gpt_5_default_settings("medium")
|
|
assert get_default_model_settings("gpt-5.2-pro-2025-12-11") == _gpt_5_default_settings("medium")
|
|
assert get_default_model_settings("gpt-5.4-pro") == _gpt_5_default_settings("medium")
|
|
assert get_default_model_settings("gpt-5.4-pro-2026-03-05") == _gpt_5_default_settings("medium")
|
|
|
|
|
|
def test_get_default_model_settings_omits_reasoning_for_unconfirmed_gpt_5_variants():
|
|
assert get_default_model_settings("gpt-5-mini") == _gpt_5_default_settings(None)
|
|
assert get_default_model_settings("gpt-5-mini-2025-08-07") == _gpt_5_default_settings(None)
|
|
assert get_default_model_settings("gpt-5-nano") == _gpt_5_default_settings(None)
|
|
assert get_default_model_settings("gpt-5-nano-2025-08-07") == _gpt_5_default_settings(None)
|
|
assert get_default_model_settings("gpt-5.1-codex") == _gpt_5_default_settings(None)
|
|
|
|
|
|
def test_get_default_model_settings_returns_empty_settings_for_gpt_5_chat_latest_aliases():
|
|
assert get_default_model_settings("gpt-5-chat-latest") == ModelSettings()
|
|
assert get_default_model_settings("gpt-5.1-chat-latest") == ModelSettings()
|
|
assert get_default_model_settings("gpt-5.2-chat-latest") == ModelSettings()
|
|
assert get_default_model_settings("gpt-5.3-chat-latest") == ModelSettings()
|
|
|
|
|
|
def test_get_default_model_settings_returns_empty_settings_for_non_gpt_5_models():
|
|
assert get_default_model_settings("gpt-4.1") == ModelSettings()
|
|
|
|
|
|
@patch.dict(os.environ, {"OPENAI_DEFAULT_MODEL": "gpt-5"})
|
|
def test_agent_uses_gpt_5_default_model_settings():
|
|
"""Agent should inherit GPT-5 default model settings."""
|
|
agent = Agent(name="test")
|
|
assert agent.model is None
|
|
assert agent.model_settings.reasoning.effort == "low" # type: ignore[union-attr]
|
|
assert agent.model_settings.verbosity == "low"
|
|
|
|
|
|
def test_agent_uses_model_specific_settings_for_explicit_gpt_5_models():
|
|
"""Agent should not apply the fallback model's GPT-5 settings to explicit GPT-5 models."""
|
|
agent = Agent(name="test", model="gpt-5")
|
|
assert agent.model == "gpt-5"
|
|
assert agent.model_settings == get_default_model_settings("gpt-5")
|
|
assert agent.model_settings.reasoning.effort == "low" # type: ignore[union-attr]
|
|
|
|
|
|
def test_agent_uses_empty_settings_for_explicit_non_gpt_5_models():
|
|
"""Agent should not apply GPT-5 defaults to explicit non-GPT-5 models."""
|
|
agent = Agent(name="test", model="gpt-4.1")
|
|
assert agent.model == "gpt-4.1"
|
|
assert agent.model_settings == ModelSettings()
|
|
|
|
|
|
def test_agent_clone_recomputes_implicit_settings_when_model_changes():
|
|
"""Agent.clone should keep implicit model settings aligned with the cloned model."""
|
|
agent = Agent(name="test", model="gpt-5")
|
|
cloned = agent.clone(model="gpt-5.4-mini")
|
|
assert cloned.model == "gpt-5.4-mini"
|
|
assert cloned.model_settings == get_default_model_settings("gpt-5.4-mini")
|
|
assert cloned.model_settings.reasoning.effort == "none" # type: ignore[union-attr]
|
|
|
|
|
|
def test_agent_clone_preserves_explicit_settings_when_model_changes():
|
|
"""Agent.clone should not recompute model settings that were explicitly customized."""
|
|
model_settings = ModelSettings(temperature=0.3)
|
|
agent = Agent(name="test", model="gpt-5", model_settings=model_settings)
|
|
cloned = agent.clone(model="gpt-5.4-mini")
|
|
assert cloned.model == "gpt-5.4-mini"
|
|
assert cloned.model_settings == model_settings
|
|
|
|
|
|
@patch.dict(os.environ, {"OPENAI_DEFAULT_MODEL": "gpt-5"})
|
|
def test_agent_resets_model_settings_for_non_gpt_5_models():
|
|
"""Agent should reset default GPT-5 settings when using a non-GPT-5 model."""
|
|
agent = Agent(name="test", model="gpt-4.1")
|
|
assert agent.model == "gpt-4.1"
|
|
assert agent.model_settings == ModelSettings()
|