From 8d7d95a20d05c043128610a3752041fed96038c8 Mon Sep 17 00:00:00 2001 From: m4 Date: Thu, 20 Aug 2026 08:27:23 +0800 Subject: [PATCH] feat: classify provider prompt-cache strategy (explicit/implicit/none) --- EvoScientist/llm/models.py | 23 ++++++++++++++++++++--- tests/test_llm.py | 12 ++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/EvoScientist/llm/models.py b/EvoScientist/llm/models.py index 520db30..0ad38a8 100644 --- a/EvoScientist/llm/models.py +++ b/EvoScientist/llm/models.py @@ -333,11 +333,28 @@ def _drop_unsupported_chat_model_kwargs(kwargs: dict[str, Any]) -> None: model_kwargs.pop(key, None) +_IMPLICIT_CACHE_PROVIDERS = frozenset({"zhipu", "zhipu-code", "siliconflow", "nvidia"}) + + +def _cache_strategy(provider: str, model_id: str) -> str: + """Return the provider's prompt-cache mechanism. + + ``explicit`` — needs Anthropic-style ``cache_control`` markers (OpenRouter + Claude routes only, matching the pre-existing condition). + ``implicit`` — provider prefixes-cache automatically; no markers, but the + prompt prefix must stay byte-stable for hits (see memory injection order). + ``none`` — no cache model to declare. + """ + if provider == "openrouter" and model_id.startswith(("anthropic/", "~anthropic/")): + return "explicit" + if provider in _IMPLICIT_CACHE_PROVIDERS: + return "implicit" + return "none" + + def _supports_openrouter_anthropic_prompt_cache(provider: str, model_id: str) -> bool: """Return whether EvoScientist should declare OpenRouter Claude caching.""" - return provider == "openrouter" and model_id.startswith( - ("anthropic/", "~anthropic/") - ) + return _cache_strategy(provider, model_id) == "explicit" def _has_cache_control_override(kwargs: dict[str, Any]) -> bool: diff --git a/tests/test_llm.py b/tests/test_llm.py index 59d200c..aabdcbd 100644 --- a/tests/test_llm.py +++ b/tests/test_llm.py @@ -965,6 +965,18 @@ class TestThirdPartyRouting: assert "thinking" not in call_kwargs +def test_cache_strategy_classifies_providers(): + from EvoScientist.llm.models import _cache_strategy + + assert _cache_strategy("openrouter", "anthropic/claude-sonnet-4-6") == "explicit" + assert _cache_strategy("openrouter", "x-ai/grok-4.3") == "none" + assert _cache_strategy("anthropic", "claude-sonnet-4-6") == "none" + assert _cache_strategy("zhipu", "glm-5.2") == "implicit" + assert _cache_strategy("zhipu-code", "glm-5.2") == "implicit" + assert _cache_strategy("siliconflow", "glm-5.2") == "implicit" + assert _cache_strategy("ollama", "llama3.1:8b") == "none" + + # ============================================================================= # Test MiniMax provider # =============================================================================