feat(cache): enable DeepSeek caching on OpenCode
This commit is contained in:
parent
5c45d9c208
commit
6b6435a874
|
|
@ -1860,12 +1860,12 @@ def anthropic_prompt_cache_policy(
|
|||
gateway implements the Anthropic cache_control contract
|
||||
(MiniMax, Zhipu GLM, LiteLLM's Anthropic proxy mode all do).
|
||||
|
||||
Qwen / Alibaba-family models on OpenCode, OpenCode Go, and direct
|
||||
Alibaba (DashScope) also honour Anthropic-style ``cache_control``
|
||||
markers on OpenAI-wire chat completions. Upstream pi-mono #3392 /
|
||||
pi #3393 documented this for opencode-go Qwen. Without markers
|
||||
these providers serve zero cache hits, re-billing the full prompt
|
||||
on every turn.
|
||||
Qwen models on OpenCode and direct Alibaba (DashScope), plus DeepSeek
|
||||
models on OpenCode, also honour Anthropic-style ``cache_control`` markers
|
||||
on OpenAI-wire chat completions. Upstream pi-mono #3392 / pi #3393
|
||||
documented this for opencode-go Qwen; #24617 reports the same gateway
|
||||
contract for DeepSeek. Without markers these providers serve zero cache
|
||||
hits, re-billing the full prompt on every turn.
|
||||
"""
|
||||
eff_provider = (provider if provider is not None else agent.provider) or ""
|
||||
eff_base_url = base_url if base_url is not None else (agent.base_url or "")
|
||||
|
|
@ -1980,16 +1980,22 @@ def anthropic_prompt_cache_policy(
|
|||
if is_minimax_provider or is_minimax_host:
|
||||
return True, True
|
||||
|
||||
# Qwen/Alibaba on OpenCode (Zen/Go) and native DashScope: OpenAI-wire
|
||||
# transport that accepts Anthropic-style cache_control markers and
|
||||
# rewards them with real cache hits. Without this branch
|
||||
# qwen3.6-plus on opencode-go reports 0% cached tokens and burns
|
||||
# through the subscription on every turn.
|
||||
# Qwen on OpenCode (Zen/Go) and native DashScope, plus DeepSeek on
|
||||
# OpenCode only: OpenAI-wire transports that accept Anthropic-style
|
||||
# cache_control markers and reward them with real cache hits. Keep direct
|
||||
# Alibaba specific to Qwen; its catalog does not establish the same
|
||||
# contract for DeepSeek.
|
||||
model_is_qwen = "qwen" in model_lower
|
||||
model_is_deepseek = "deepseek" in model_lower
|
||||
provider_is_opencode = provider_lower in {
|
||||
"opencode", "opencode-zen", "opencode-go",
|
||||
}
|
||||
provider_is_alibaba_family = provider_lower in {
|
||||
"opencode", "opencode-zen", "opencode-go", "alibaba",
|
||||
}
|
||||
if provider_is_alibaba_family and model_is_qwen:
|
||||
if (provider_is_alibaba_family and model_is_qwen) or (
|
||||
provider_is_opencode and model_is_deepseek
|
||||
):
|
||||
# Envelope layout (native_anthropic=False): markers on inner
|
||||
# content parts, not top-level tool messages. Matches
|
||||
# pi-mono's "alibaba" cacheControlFormat.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ from __future__ import annotations
|
|||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from run_agent import AIAgent
|
||||
|
||||
|
||||
|
|
@ -256,6 +258,44 @@ class TestQwenAlibabaFamily:
|
|||
assert agent._anthropic_prompt_cache_policy() == (False, False)
|
||||
|
||||
|
||||
class TestDeepSeekOpenCode:
|
||||
"""DeepSeek uses OpenCode's envelope-layout cache markers (#24617)."""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"provider",
|
||||
["opencode", "opencode-zen", "opencode-go"],
|
||||
)
|
||||
def test_deepseek_on_opencode_caches_with_envelope_layout(self, provider):
|
||||
agent = _make_agent(
|
||||
provider=provider,
|
||||
base_url="https://opencode.ai/v1",
|
||||
api_mode="chat_completions",
|
||||
model="deepseek-v4-pro",
|
||||
)
|
||||
|
||||
assert agent._anthropic_prompt_cache_policy() == (True, False)
|
||||
|
||||
def test_deepseek_on_direct_alibaba_does_not_cache(self):
|
||||
agent = _make_agent(
|
||||
provider="alibaba",
|
||||
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||
api_mode="chat_completions",
|
||||
model="deepseek-v4-pro",
|
||||
)
|
||||
|
||||
assert agent._anthropic_prompt_cache_policy() == (False, False)
|
||||
|
||||
def test_deepseek_on_openrouter_does_not_cache(self):
|
||||
agent = _make_agent(
|
||||
provider="openrouter",
|
||||
base_url="https://openrouter.ai/api/v1",
|
||||
api_mode="chat_completions",
|
||||
model="deepseek/deepseek-chat",
|
||||
)
|
||||
|
||||
assert agent._anthropic_prompt_cache_policy() == (False, False)
|
||||
|
||||
|
||||
class TestNousPortalAnthropicWire:
|
||||
def test_portal_claude_on_the_messages_wire_uses_the_native_layout(self):
|
||||
agent = _make_agent(
|
||||
|
|
@ -315,4 +355,3 @@ class TestExplicitOverrides:
|
|||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Long-lived prefix cache policy (cross-session 1h tier)
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue