mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-17 22:14:14 +00:00
feat(providers): explicit prompt cache for DashScope/Qwen (#1127)
* feat(providers): explicit prompt cache for DashScope/Qwen Extend OpenAI-compat path with Anthropic-style cache_control:ephemeral inline blocks for Alibaba DashScope endpoints (provider_type=bailian or URL contains "dashscope"). Verified live: qwen3.6-plus / qwen3.5-plus / qwen3-coder-plus all return 99.7% cache hit rate on 6K-token prefix, yielding ~89% token cost reduction on cached prefix (90% Alibaba discount). - isDashScope(): 3-source detection (URL + providerType + name) handles reverse-proxied endpoints; covers both "dashscope" and "bailian" - buildRequestBody wraps system content with SplitSystemPromptForCache (exported from anthropic_request.go) using <!-- GOCLAW_CACHE_BOUNDARY --> - Tool prefix cache: cache_control on last tool definition, with 4-marker budget guard - Parse cache_creation_input_tokens from prompt_tokens_details into Usage.CacheCreationTokens; propagates via existing span metadata writers - Runtime escape hatch: GOCLAW_DISABLE_DASHSCOPE_CACHE=true - Live integration smoke test (build tag integration, env-gated) * chore(providers): polish per PR #1127 review - Use strings.Repeat instead of custom repeat() helper in smoke test - Clarify BuildRequestBodyForTest is test-only, not public API * feat(providers): enable thinking for Qwen 3.7/3.6, observe cache in smoke test Qwen3.7-plus and qwen3.6-plus support deep thinking but were missing from dashscopeThinkingModels, so enable_thinking/thinking_budget was silently skipped. Add both to the whitelist and test. Add qwen3.7-plus to the cache smoke test as cache-optional: Alibaba's context-cache doc does not yet list 3.7/3.6 for explicit cache, and the cache wrap is a safe no-op when unsupported, so a no-cache result is logged rather than failed to avoid a flaky live assertion. Claude-Session: https://claude.ai/code/session_01X3jkrc7N3ar8ZGzUJWyNS5 * fix(providers): preserve DashScope detection for proxy routes
This commit is contained in:
1 parent
c70324f032
commit
0e994f959c
18 files changed
+689
-22
No files matched your search
@@ -8,7 +8,7 @@ import (
|
||||
// the cache boundary marker is split into 2 blocks: stable (cached) + dynamic.
|
||||
func TestAnthropicSystemBlocksSplit(t *testing.T) {
|
||||
prompt := "stable content\n" + CacheBoundaryMarker + "\ndynamic content"
|
||||
blocks := splitSystemPromptForCache(prompt)
|
||||
blocks := SplitSystemPromptForCache(prompt)
|
||||
if len(blocks) != 2 {
|
||||
t.Fatalf("expected 2 blocks, got %d", len(blocks))
|
||||
}
|
||||
@@ -30,7 +30,7 @@ func TestAnthropicSystemBlocksSplit(t *testing.T) {
|
||||
// marker → single block with cache_control.
|
||||
func TestAnthropicSingleBlockFallback(t *testing.T) {
|
||||
prompt := "no boundary here"
|
||||
blocks := splitSystemPromptForCache(prompt)
|
||||
blocks := SplitSystemPromptForCache(prompt)
|
||||
if len(blocks) != 1 {
|
||||
t.Fatalf("expected 1 block, got %d", len(blocks))
|
||||
}
|
||||
@@ -46,7 +46,7 @@ func TestAnthropicSingleBlockFallback(t *testing.T) {
|
||||
// after the boundary produces only 1 block (no empty block appended).
|
||||
func TestAnthropicEmptyDynamic(t *testing.T) {
|
||||
prompt := "stable only\n" + CacheBoundaryMarker + "\n"
|
||||
blocks := splitSystemPromptForCache(prompt)
|
||||
blocks := SplitSystemPromptForCache(prompt)
|
||||
if len(blocks) != 1 {
|
||||
t.Fatalf("expected 1 block for empty dynamic, got %d", len(blocks))
|
||||
}
|
||||
@@ -59,7 +59,7 @@ func TestAnthropicEmptyDynamic(t *testing.T) {
|
||||
// (empty stable section) still produces valid blocks without empty text.
|
||||
func TestAnthropicEmptyStable(t *testing.T) {
|
||||
prompt := CacheBoundaryMarker + "\ndynamic only"
|
||||
blocks := splitSystemPromptForCache(prompt)
|
||||
blocks := SplitSystemPromptForCache(prompt)
|
||||
// Stable is empty string after TrimSpace — should still produce a block
|
||||
// (Anthropic API handles empty text blocks gracefully).
|
||||
if len(blocks) < 1 {
|
||||
|
||||
Reference in new issue
Block a user