Fix DeepSeek cost attribution and pricing

This commit is contained in:
rcourtman 2025-12-12 10:49:56 +00:00
parent 71b6a2ae12
commit 877a4f08e7
4 changed files with 35 additions and 6 deletions

View file

@ -43,10 +43,13 @@ var providerPrices = map[string][]modelPrice{
{Pattern: "claude-sonnet*", InputUSDPerMTok: 3.00, OutputUSDPerMTok: 15.00},
{Pattern: "claude-haiku*", InputUSDPerMTok: 0.25, OutputUSDPerMTok: 1.25},
},
"deepseek": {
// DeepSeek docs include an "input cache hit" discount; this uses cache-miss rates for conservative estimates.
{Pattern: "deepseek-*", InputUSDPerMTok: 0.28, OutputUSDPerMTok: 0.42},
},
"ollama": {
{Pattern: "*", InputUSDPerMTok: 0, OutputUSDPerMTok: 0},
},
// deepseek pricing intentionally omitted until stable public pricing is confirmed.
}
func lookupPrice(provider, model string) (TokenPrice, bool) {

View file

@ -122,8 +122,9 @@ func (s *Store) GetSummary(days int) Summary {
var totalInput, totalOutput int64
for _, e := range events {
provider := e.Provider
provider := strings.ToLower(strings.TrimSpace(e.Provider))
model := normalizeModel(provider, e.RequestModel, e.ResponseModel)
provider, model = inferProviderAndModel(provider, model)
k := pmKey{provider: provider, model: model}
pm := pmTotals[k]
@ -278,6 +279,19 @@ func normalizeModel(provider, requestModel, responseModel string) string {
return ""
}
func inferProviderAndModel(provider, model string) (string, string) {
if provider == "openai" {
parts := strings.SplitN(strings.TrimSpace(model), ":", 2)
if len(parts) == 2 && strings.ToLower(parts[0]) == "deepseek" {
return "deepseek", parts[1]
}
if strings.HasPrefix(strings.ToLower(strings.TrimSpace(model)), "deepseek") {
return "deepseek", model
}
}
return provider, model
}
// ProviderModelSummary is a rollup for a provider/model pair.
type ProviderModelSummary struct {
Provider string `json:"provider"`

View file

@ -130,7 +130,11 @@ func TestEstimateUSDKnownAndUnknownModels(t *testing.T) {
}
usd, ok, _ = EstimateUSD("deepseek", "deepseek-reasoner", 1_000_000, 1_000_000)
if ok || usd != 0 {
t.Fatalf("expected deepseek pricing to be unknown, got ok=%v usd=%.4f", ok, usd)
if !ok {
t.Fatalf("expected deepseek pricing to be known for deepseek-reasoner")
}
expected = 0.70 // 1M input * $0.28 + 1M output * $0.42
if math.Abs(usd-expected) > 0.0001 {
t.Fatalf("expected usd %.4f, got %.4f", expected, usd)
}
}

View file

@ -1002,9 +1002,13 @@ Always execute the commands rather than telling the user how to do it.`
}
if costStore != nil {
providerName, _ := config.ParseModelString(modelString)
if providerName == "" {
providerName = provider.Name()
}
costStore.Record(cost.UsageEvent{
Timestamp: time.Now(),
Provider: provider.Name(),
Provider: providerName,
RequestModel: modelString,
ResponseModel: resp.Model,
UseCase: req.UseCase,
@ -1189,9 +1193,13 @@ Always execute the commands rather than telling the user how to do it.`
}
if costStore != nil {
providerName, _ := config.ParseModelString(modelString)
if providerName == "" {
providerName = provider.Name()
}
costStore.Record(cost.UsageEvent{
Timestamp: time.Now(),
Provider: provider.Name(),
Provider: providerName,
RequestModel: modelString,
ResponseModel: resp.Model,
UseCase: req.UseCase,