Repository navigation
v0.13.0 内建模型价表 + 「价格未知」不再静默记 0
成本计价不再依赖调用方自带价格
此前 llm 有完整的成本追踪能力,但价格不在这一层:CostTracker.Record 要求调用方每次传入单价,llm 自己既不持有「模型→价格」映射,也没有按模型名查价的入口。于是每个下游都得自己维护一张表(通常在应用配置里,模型名精确匹配),漏配就静默记 0——0 成本在账单上与「免费模型」不可区分。
1) 内建价表(新增 pricing.go)
| API | 作用 |
|---|---|
DefaultPriceTable() |
内建价表(OpenAI / Anthropic / DeepSeek / 小米 MiMo,共 20 个模型键) |
NewPricing→NewPriceTable(overrides) |
内建价 + 调用方覆盖(覆盖优先) |
LookupPrice(model) |
查价(返回命中的键与命中方式) |
LookupPriceStrict(model) |
查不到返回 ErrPriceUnknown(硬失败路径) |
单位统一为「美元 / 每 100 万 token」。仓里此前并存两套单位(Price 每 1M,Provider.CostPer1KTokens 与 Record 的 costPer1K 每 1K),差一个数量级;新 API 全部收敛到每 1M,旧入口保留但标 Deprecated。
归一化规则:原名 → 去部署前缀(openai/gpt-4o → gpt-4o)→ 去日期后缀(mimo-v2.5-pro-20250101 → mimo-v2.5-pro)。
不做最长前缀回落:那会把同主干异价 SKU 静默定价错(表里有 gpt-4o 时 gpt-4o-mini 会按 gpt-4o 计)。「静默算错」比「显式未知」更危险。
2) 「价格未知」不再静默记 0
CostRecord 增 PriceStatus / PriceKey / PriceMatched;CostTracker 增 RecordAuto / RecordPriced / RecordUnpriced / Unpriced / UnpricedCount;ModelSummary 增 PricedCalls / UnpricedCalls。
判读口径:
TotalCostUSD == 0 && UnpricedCalls == 0→ 真免费TotalCostUSD == 0 && UnpricedCalls > 0→ 成本口径不完整(不是「这个模型不要钱」)
需要硬失败的出账链路用 LookupPriceStrict(ErrPriceUnknown)。
3) 接入生产路径
Provider 新增可选接口 PricedProvider(ModelPricing() (Price, bool),显式单价优先于价表);Resilient 新增 PriceTable 字段,记账改走 providerPrice(p, table):Provider 显式价 > per-1K 非零 > 价表按模型名 > 未知。
此前这条路径在 Provider 不给价时恒记 0——这正是「成本看板恒为 0 而无人察觉」的成因。
⚠️ 价目表是参考价
内建价表是 2026-10-20 采集的官方 list price 快照:厂商随时调价,本表必然滞后于厂商公告;同一模型在不同渠道(官方/代理/云托管)价格不同,缓存命中、批量、区域定价另算;只收录厂商以美元公布的模型,人民币计价与阶梯计价的(通义/百炼等)不收——换算汇率会漂、阶梯价无法用单一「每 1M 常数」表达,硬折算等于给出一个看起来精确的错误数字。契约价、代理加价、折算价一律用 NewPriceTable(overrides) 或 PricedProvider 覆盖。
验证
GOWORK=off go test -race ./... 全绿;新增 14 个用例(含子用例),断言一律用关系(查表单价 × token 数 == 记录成本),不写死价目表数值——价目表随厂商调价变动,写死数字会随表更新假失败。
关联 issue #9