Skip to content

v0.13.0 内建模型价表 + 「价格未知」不再静默记 0

Choose a tag to compare

@zy84338719 zy84338719 released this 19 Oct 23:11
· 56 commits to main since this release
257a5d2

成本计价不再依赖调用方自带价格

此前 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