48 lines
2.3 KiB
Go
48 lines
2.3 KiB
Go
package main
|
|
|
|
// pricing.go centralises model pricing as a per-model table (the LiteLLM pattern)
|
|
// instead of three hardcoded Grok fields. The spend ledger prices each call by the
|
|
// model it actually used, so when a second model (Gemini) starts answering some
|
|
// routes, its cost books correctly against the same global ceiling.
|
|
|
|
// ModelPrice is the per-1M-token USD price for one model, applied to the API's
|
|
// returned usage so the wallet ceiling tracks real cost even as prices change.
|
|
type ModelPrice struct {
|
|
InputPerM float64 // non-cached prompt tokens
|
|
CachedPerM float64 // prompt tokens served from the provider cache (cheaper)
|
|
OutputPerM float64 // completion tokens
|
|
}
|
|
|
|
// CostBreakdown is the per-component USD cost of answering one request. A plain
|
|
// grok_direct call has only Token; a cascade adds Router (the cheap classifier),
|
|
// Grounding (Gemini Google-search) and/or WebTool (Grok web search) on top. Settle
|
|
// books each column separately so the ledger and request_log can attribute spend,
|
|
// and so a half-finished cascade can book only what it actually spent (§8.1).
|
|
type CostBreakdown struct {
|
|
Token float64
|
|
Grounding float64 // Gemini grounded-prompt TOKEN cost
|
|
WebTool float64
|
|
Router float64
|
|
// GroundingFee is the per-grounded-prompt FEE (the $35/1k overage on a paid Gemini
|
|
// tier, GEMINI_GROUNDING_PER_PROMPT_USD) — kept separate from Grounding (the token
|
|
// cost) for clean analytics. Booked the moment the grounded prompt is admitted, even
|
|
// on the error return (§7 SG1). Settle folds it into the grounding_usd spend column,
|
|
// so the $10 ceiling finally sees it without a spend-table migration.
|
|
GroundingFee float64
|
|
}
|
|
|
|
// Total is the grand total across all components (the number the wallet ceiling and
|
|
// request_log.total_usd care about). Computed, never stored, so it can't drift.
|
|
func (c CostBreakdown) Total() float64 {
|
|
return c.Token + c.Grounding + c.WebTool + c.Router + c.GroundingFee
|
|
}
|
|
|
|
// priceFor returns the configured price for a model. An unknown model falls back to
|
|
// the default (final-voice) model's price rather than $0 — a $0 price would silently
|
|
// blind the global ceiling to that call, the one failure mode we never want.
|
|
func (c *Config) priceFor(model string) ModelPrice {
|
|
if p, ok := c.Prices[model]; ok {
|
|
return p
|
|
}
|
|
return c.Prices[c.XAIModel]
|
|
}
|