diff --git a/backend/internal/service/account_stats_pricing.go b/backend/internal/service/account_stats_pricing.go index 8d5bc144fcad..af82bc15d64d 100644 --- a/backend/internal/service/account_stats_pricing.go +++ b/backend/internal/service/account_stats_pricing.go @@ -62,29 +62,17 @@ func resolveAccountStatsCost( } // tryModelFilePricing 使用模型定价文件(LiteLLM/fallback)中的价格计算费用。 +// 与用户计费共用同一条定价管线,避免这里维护第二份"单价 × token 数"实现后, +// 每加一个定价特性都要手工镜像一次。channelPricing 为 nil,保持优先级 3 的 +// 语义:只取模型定价文件,不引入渠道自定义定价。 func tryModelFilePricing(billingService *BillingService, model string, tokens UsageTokens, serviceTier string) *float64 { - pricing, err := billingService.GetModelPricing(model) - if err != nil || pricing == nil { - return nil - } - normalizedTier := normalizeBillingServiceTier(serviceTier) - if normalizedTier == "priority" || normalizedTier == "fast" || normalizedTier == "flex" || - billingService.shouldApplySessionLongContextPricing(tokens, pricing) { - breakdown, err := billingService.CalculateCostWithServiceTier(model, tokens, 1, normalizedTier) - if err != nil || breakdown == nil || breakdown.TotalCost <= 0 { - return nil - } - return &breakdown.TotalCost - } - cost := float64(tokens.InputTokens)*pricing.InputPricePerToken + - float64(tokens.OutputTokens)*pricing.OutputPricePerToken + - float64(tokens.CacheCreationTokens)*pricing.CacheCreationPricePerToken + - float64(tokens.CacheReadTokens)*pricing.CacheReadPricePerToken + - float64(tokens.ImageOutputTokens)*pricing.ImageOutputPricePerToken - if cost <= 0 { + breakdown, err := billingService.CalculateCostWithServiceTier( + model, tokens, 1, normalizeBillingServiceTier(serviceTier), + ) + if err != nil || breakdown == nil || breakdown.TotalCost <= 0 { return nil } - return &cost + return &breakdown.TotalCost } // tryCustomRules 遍历自定义规则,按数组顺序先命中为准。 diff --git a/backend/internal/service/account_stats_pricing_test.go b/backend/internal/service/account_stats_pricing_test.go index 1bd28896fcba..84ca0897eccc 100644 --- a/backend/internal/service/account_stats_pricing_test.go +++ b/backend/internal/service/account_stats_pricing_test.go @@ -594,8 +594,9 @@ func TestTryModelFilePricing_WithImageOutput(t *testing.T) { } result := tryModelFilePricing(bs, "claude-sonnet-4", tokens, "") require.NotNil(t, result) - // 100*0.001 + 50*0.002 + 10*0.01 = 0.1 + 0.1 + 0.1 = 0.3 - require.InDelta(t, 0.3, *result, 1e-12) + // ImageOutputTokens 是 OutputTokens 的子集,先扣除再按图片单价计。 + // 100*0.001 + (50-10)*0.002 + 10*0.01 = 0.1 + 0.08 + 0.1 = 0.28 + require.InDelta(t, 0.28, *result, 1e-12) } func TestTryModelFilePricing_WithCacheTokens(t *testing.T) {