From 5a593a511e448af9dd4304a9956b81d7f1e2aa7a Mon Sep 17 00:00:00 2001 From: alfadb Date: Sat, 9 May 2026 21:13:22 +0800 Subject: [PATCH] test(billing): tighten DeepSeek V4 fallback assertions; clarify branch comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address copilot-pull-request-reviewer feedback on #2157: - billing_service_test.go: extend TestGetFallbackPricing_FamilyMatching with optional expectedOutput / expectedCacheRead fields and assert full Input/Output/CacheRead pricing for all 4 DeepSeek cases (v4-pro, v4-flash, deepseek-chat→flash, deepseek-reasoner→flash), preventing silent regression to 0 output/cache cost. - billing_service.go: rewrite the DeepSeek block comment to explicitly describe its scope (V4 Pro/Flash + chat/reasoner aliases, no unknown-deepseek fallback) and tighten the OpenAI comment to make it unambiguous that it only describes the OpenAI/Codex branch immediately below it. --- backend/internal/service/billing_service.go | 6 +-- .../internal/service/billing_service_test.go | 51 ++++++++++++++++--- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/backend/internal/service/billing_service.go b/backend/internal/service/billing_service.go index bdeef9185b..bbe9e97272 100644 --- a/backend/internal/service/billing_service.go +++ b/backend/internal/service/billing_service.go @@ -362,19 +362,19 @@ func (s *BillingService) getFallbackPricing(model string) *ModelPricing { return s.fallbackPrices["gemini-3.1-pro"] } - // DeepSeek V4 系列 + // DeepSeek V4 系列:仅匹配已知 V4 Pro/Flash 与官方兼容别名 + // (deepseek-chat / deepseek-reasoner → V4 Flash),未知 deepseek-* 型号不回退,避免误计价。 if strings.Contains(modelLower, "deepseek-v4-flash") { return s.fallbackPrices["deepseek-v4-flash"] } if strings.Contains(modelLower, "deepseek-v4-pro") { return s.fallbackPrices["deepseek-v4-pro"] } - // deepseek-chat / deepseek-reasoner → V4 Flash(官方兼容别名) if strings.Contains(modelLower, "deepseek-chat") || strings.Contains(modelLower, "deepseek-reasoner") { return s.fallbackPrices["deepseek-v4-flash"] } - // OpenAI 仅匹配已知 GPT-5/Codex 族,避免未知 OpenAI 型号误计价。 + // OpenAI(GPT-5 / Codex 族):仅匹配已知型号,避免未知 OpenAI 型号误计价。 if normalized := normalizeKnownOpenAICodexModel(modelLower); normalized != "" { switch normalized { case "gpt-5.5": diff --git a/backend/internal/service/billing_service_test.go b/backend/internal/service/billing_service_test.go index d75bbfde35..3857715b07 100644 --- a/backend/internal/service/billing_service_test.go +++ b/backend/internal/service/billing_service_test.go @@ -332,11 +332,14 @@ func TestCalculateCost_LongContextAppliesMultiplierToCacheCreation5mAnd1h(t *tes func TestGetFallbackPricing_FamilyMatching(t *testing.T) { svc := newTestBillingService() + // expectedOutput / expectedCacheRead 为 0 时跳过该字段断言(保持与原有用例兼容)。 tests := []struct { - name string - model string - expectedInput float64 - expectNilPricing bool + name string + model string + expectedInput float64 + expectedOutput float64 + expectedCacheRead float64 + expectNilPricing bool }{ {name: "empty model", model: " ", expectNilPricing: true}, {name: "claude opus 4.6", model: "claude-opus-4.6-20260201", expectedInput: 5e-6}, @@ -352,10 +355,34 @@ func TestGetFallbackPricing_FamilyMatching(t *testing.T) { {name: "openai legacy gpt5.1 codex falls back to gpt5.3 codex", model: "gpt-5.1-codex", expectedInput: 1.5e-6}, {name: "openai legacy codex mini latest falls back to gpt5.3 codex", model: "codex-mini-latest", expectedInput: 1.5e-6}, {name: "openai unknown no fallback", model: "gpt-unknown-model", expectNilPricing: true}, - {name: "deepseek v4 pro", model: "deepseek-v4-pro", expectedInput: 4.35e-7}, - {name: "deepseek v4 flash", model: "deepseek-v4-flash", expectedInput: 1.4e-7}, - {name: "deepseek chat alias → flash", model: "deepseek-chat", expectedInput: 1.4e-7}, - {name: "deepseek reasoner alias → flash", model: "deepseek-reasoner", expectedInput: 1.4e-7}, + { + name: "deepseek v4 pro", + model: "deepseek-v4-pro", + expectedInput: 4.35e-7, + expectedOutput: 8.7e-7, + expectedCacheRead: 3.625e-9, + }, + { + name: "deepseek v4 flash", + model: "deepseek-v4-flash", + expectedInput: 1.4e-7, + expectedOutput: 2.8e-7, + expectedCacheRead: 2.8e-9, + }, + { + name: "deepseek chat alias → flash", + model: "deepseek-chat", + expectedInput: 1.4e-7, + expectedOutput: 2.8e-7, + expectedCacheRead: 2.8e-9, + }, + { + name: "deepseek reasoner alias → flash", + model: "deepseek-reasoner", + expectedInput: 1.4e-7, + expectedOutput: 2.8e-7, + expectedCacheRead: 2.8e-9, + }, {name: "non supported family", model: "qwen-max", expectNilPricing: true}, } @@ -368,6 +395,14 @@ func TestGetFallbackPricing_FamilyMatching(t *testing.T) { } require.NotNil(t, pricing) require.InDelta(t, tt.expectedInput, pricing.InputPricePerToken, 1e-12) + if tt.expectedOutput != 0 { + require.InDelta(t, tt.expectedOutput, pricing.OutputPricePerToken, 1e-12, + "OutputPricePerToken mismatch for %s", tt.model) + } + if tt.expectedCacheRead != 0 { + require.InDelta(t, tt.expectedCacheRead, pricing.CacheReadPricePerToken, 1e-14, + "CacheReadPricePerToken mismatch for %s", tt.model) + } }) } }