Fix DeepSeek cost attribution and pricing
This commit is contained in:
parent
71b6a2ae12
commit
877a4f08e7
4 changed files with 35 additions and 6 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue