mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-12 04:07:25 +00:00
fix(billing): 源层零价不再覆盖模型价(issue #1)+ default_mode 生效 + 文档/判据补齐
GitCode issue #1:任何按 `mode: token` 且 URL 非通配符的规则定价的源,计费恒为 0,
且 `unpriced_reqs` 也不增长 —— 完全静默。
## 真因
- `compile.go` 给这类规则写源条目 `{prompt:0, completion:0, per_request:0}`,
本意只是"标记该源已定价"(同源未列入价目表的模型不算 unpriced);
- `billing.lua` 的 priceFor() 源层在模型层之后、且 `sp.prompt ~= nil` 即覆盖;
- 两者叠加 ⇒ 模型价被清成 0,而 `out.priced` 仍为 true ⇒ 连未定价计数都不涨。
## 修法
1. `compile.go`:token 规则的源条目只写 `{per_request: 0}`(只是标记,不参与 token
计价)。`free` / `subscription` 保留全零(那里 0 本身就是语义)。
2. `billing.lua`:
- `priceFor()` 的 `out` 补 `local`(此前是 VM 级全局变量,跨请求残留);
- 实现 `profiles[].default` 的 `free|unpriced` 语义:`free` = 刻意免费(不进
unpriced),`unpriced`(默认)= 未定价债务。此前 compile.go 写 `default_mode`
但**无人读**,两种取值运行时完全等价。
3. `core.go`:应用 profile 时把 `unmatched_sources` 打进日志(WARNING 列出没有
规则命中的源)。该字段此前只写不读,是第二个静默少报点。
4. `docs/plugins.md`:token 价优先级改为与实际实现一致的
`keys > sources > models > default`,并写明"标记已定价只能用 per_request:0"。
## 判据(都先红后绿)
- `internal/billing`:token 规则的源条目**不含** prompt/completion;free/subscription
仍保留显式 0。
- `internal/lua`:同源同模型下旧形状 cost=0(缺陷本身)、新形状 cost=0.75 且
unpriced_reqs=0;未列入价目表的模型仍算"已定价";default_mode 三态。
- `internal/gateway`:`billing_rules_api_test` 的单位断言原本读
`cc["models"]`(恒 false,整块被跳过——从未执行过),改为 `prices["models"]`,
并新增"源条目不得带 token 价"断言。
## 顺带修掉一个"永不执行"的判据
`discover_mutate_test.go` 的变异锚点写成 6 个空格,而 `discover.go` 已是 2 个空格
⇒ 该变异每次都 `anchor not found`,变异 campaign 长期红着。修正锚点后,
"嵌套 metadata 不再读取"这条变异真的被执行并被测试 KILL。
This commit is contained in:
@ -1065,6 +1065,23 @@ func (c *Core) applyBillingDSL() {
|
||||
return
|
||||
}
|
||||
log.Printf("[billing] profile %q applied (%d rules, %d sources)", profile.ID, len(profile.Rules), len(c.cfg.Sources))
|
||||
// unmatched_sources used to be written by the compiler and read by nobody,
|
||||
// so a profile that silently left half the gateway unpriced looked applied
|
||||
// and healthy. Logging it is the cheap reader: an operator who sees source
|
||||
// names here knows exactly which rules to add (GitCode issue #1 follow-up).
|
||||
if unmatched, ok := prices["unmatched_sources"].([]string); ok && len(unmatched) > 0 {
|
||||
log.Printf("[billing] WARNING %d source(s) match no rule and fall through to the "+
|
||||
"profile default: %v (add rules, or set `default: free` if that is intended)",
|
||||
len(unmatched), unmatched)
|
||||
} else if raw, ok := prices["unmatched_sources"].([]interface{}); ok && len(raw) > 0 {
|
||||
names := make([]string, 0, len(raw))
|
||||
for _, v := range raw {
|
||||
names = append(names, fmt.Sprint(v))
|
||||
}
|
||||
log.Printf("[billing] WARNING %d source(s) match no rule and fall through to the "+
|
||||
"profile default: %v (add rules, or set `default: free` if that is intended)",
|
||||
len(names), names)
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateScopeQuotas checks every scope entry's caps before they are stored.
|
||||
|
||||
Reference in New Issue
Block a user