Repository navigation
kimi: 将被拒绝的采样参数改写为可接受的值 - #1197
Conversation
VS Code Copilot's chat hardcodes temperature 0.1 and top_p 1, which Kimi Code's per-model whitelist refuses with 400 "invalid temperature: only 1 is allowed for this model" before any token is read. Rewrite them to the accepted values (1, 0.95) in the body before forwarding, and add them when absent; a request already carrying them, or going to another provider, is left as it was. Tested with the four cases: refused, absent, accepted, another provider.
yetone
left a comment
There was a problem hiding this comment.
感谢 PR!在 head b2bba1dd 上合到当前 main 后跑过:go vet ./...、go build、GOOS=linux go build -tags nogui、GOOS=windows go build 都过;go test -tags nogui ./internal/gateway/... 通过。但有几个问题需要先改:
- 范围太宽,会把原本正常的请求改坏。
kimiSamplingParams复用了isKimi,它也命中 Moonshot 按量付费(api.moonshot.ai/api.moonshot.cn)和所有moonshot*/kimi*预设,用户自己设的 temperature 会被一律改成 1,包括moonshot-v1-*这类接受范围值的模型。另外 K2.5/K2.6 关闭 thinking 时只接受temperature: 0.6,而 magpie 在 Anthropic 路径上会对非 Claude 模型关掉 thinking(thinkingOffUnlessAsked),这时强行写 1 会把原本 200 的请求变成 400。 - 已有值时是对整个 body 做字节替换(
bytes.Replace(..., 1)):带空格的"temperature": 0.1匹配不到,被拒的值照发;body 里更早出现的嵌套键会被误改,例如tool_use.input里的{"temperature":0.1}被改成 1,而顶层的 0.1 没动。 - 缺失时的插入不安全:
{}变成{"top_p":0.95,"temperature":1,}(非法 JSON);开头有空白的 body 也会被写坏。 - 描述里「不带采样参数的请求保持原样」和代码(会插入两个字段)不一致;
if !changed { return body }; return body是死代码。 - 测试换回旧代码后大多仍然通过:它遍历 map(顺序随机),每个 Kimi 请求都存到
got["api.kimi.com"],只检查最后一个。去掉forwardOnce里的调用后跑 8 次有 7 次通过。请每个用例单独断言,并覆盖 Anthropic 端点和 Moonshot 主机。
建议改法:只对 Kimi Code 的 K 系列模型,用现有的 withoutFields 删除 temperature/top_p,让服务端按当前模式取默认值,不要写死数值;测试请用实际被拒的请求体,并加一条断言:Moonshot 的 moonshot-v1 保留用户自己的 temperature。我这边暂时没法实测 400 → 200,如果方便,请贴一下修改后真实请求的结果。
VS Code Copilot chat sends temperature:0.1 and top_p:1, which Kimi Code rejects with 400 "invalid temperature: only 1 is allowed for this model". Instead of rewriting to fixed accepted values, remove the fields for Kimi Code K models only, so the server fills in the value each model and mode wants. Scope is narrowed to the Kimi Code membership endpoints (kimi-code presets and api.kimi.com/ai/coding) and K models (kimi-*, kN), so Moonshot pay-as-you-go (api.moonshot.ai/cn) and moonshot-v1-* keep the user temperature. Tests cover the refused Copilot request, absent fields, already-accepted values, Anthropic endpoint, Moonshot pay-as-you-go keeping user temperature, and another provider left untouched.
|
yetone
left a comment
There was a problem hiding this comment.
感谢更新。我在新 head bebe81c74948d10a0e581bf1ca735deb96a4e8c8 上重新审了,合到当前 main e90f30d9(无冲突)后跑过:
go vet -tags nogui ./internal/gateway/在 darwin、GOOS=linux、GOOS=windows下都通过;go build -tags nogui .通过。go test -tags nogui ./internal/gateway/(临时 HOME,固定缓存)整包通过。- 故意改坏,看
TestKimiCodeSampling能不能抓到:- 去掉
forwardOnce里的调用:挂 3 个子测试(refused / accepted / anthropic endpoint),挂的原因说得清楚。 - 只删
temperature、不删top_p:挂。 kimiKModel一律返回 false:挂。- **把
isKimiCode换回原来的isKimi(Moonshot 按量付费也算进去):测试仍然通过。**也就是说,「范围只限 Kimi Code」这一点没有测试守着。现在 Moonshot 的用例用的是moonshot-v1-8k,它是被kimiKModel挡掉的,跟isKimiCode没关系。
- 去掉
上次的五个问题都改了:用 withoutFields 删字段,不再写死数值;不再做字节替换和插入;每个用例单独断言;Anthropic 端点和 Moonshot 主机都覆盖到了。这部分没问题。
但有一处要改,而且是我上次的建议给错了,抱歉:Kimi 开放平台(Moonshot 按量付费)上的 K2.5 之后的模型同样只接受固定值。 Kimi 的模型参数文档写的是 kimi-k3、kimi-k2.7-code、kimi-k2.6 的 temperature 固定为 1.0(K2.5/K2.6 关闭 thinking 时是 0.6),top_p 固定为 0.95,「passing any other value returns an error」。Cherry Studio 的 #19601 报的也是同一个 400(invalid temperature: only 1 is allowed for this model),他们的做法是对 kimi-k(2.[5-9]|[3-9]) 省略这两个字段。所以现在这个版本里,用 Moonshot 按量 key 跑 kimi-k2.6 / kimi-k3 的 Copilot 用户还是会 400,这就是 code standards 里说的「修复要覆盖所有同类」。
建议这样改:
- 主机条件用
isKimi(Kimi Code 和 Moonshot 两个平台都算),模型条件收窄到会锁定参数的模型:Kimi Code 端点上的所有模型(kimi-for-coding*、k3*),以及kimi-k2.5及之后、kimi-k3及之后。moonshot-v1-*、kimi-k2-0905-preview、kimi-k2-thinking、kimi-latest这类接受范围值的模型保留用户自己的值。现在的kimiKModel匹配所有kimi*开头的模型,放到 Moonshot 上就太宽了。 - 测试加上:Moonshot 主机 +
kimi-k2.6时删掉这两个字段;Moonshot 主机 +kimi-k2-0905-preview(或moonshot-v1-8k)时保留temperature: 0.1。这样把isKimi/isKimiCode换来换去,测试都能抓到。 - PR 描述还是第一版的内容(写的是「改写为 1 / 0.95」「缺失时插入」),请更新成现在的行为。
真实请求:owner 的 Kimi Code 账号现在返回 403 access_terminated_error(订阅已失效),OpenCode Go 的订阅也不可用,所以我这边没法实测 400 → 200。你说已经用 VS Code Copilot 实测通过,方便的话请贴一下改之后发给 Kimi 的真实请求体和响应状态(key 打码),最好再加一条 kimi-k2.6 关闭 thinking 时的结果(服务端默认值应该是 0.6)。
没跑的:真实 Kimi 请求(原因见上)、全量 go test ./...(只改了 gateway 包)。
…els that lock them A review of the last commit found the rewrite missed Moonshot's pay-as-you-go API: kimi-k2.5 and later there lock temperature and top_p the same as Kimi Code's models (400 "invalid temperature: only 1 is allowed for this model", CherryHQ/cherry-studio#19601), so a Copilot user on a Moonshot key with kimi-k2.6 was still refused. The host check is isKimi again — both platforms — and the model check narrows to the ones that lock the fields: kimi-for-coding* and k3* on Kimi Code, kimi-k2.5 and later on either. moonshot-v1-*, kimi-k2-0905-preview, kimi-k2-thinking and kimi-latest take a range and keep the user's values. TestKimiLockedSampling adds Moonshot host cases both ways (kimi-k2.6 loses the fields, kimi-k2-0905-preview keeps 0.1), so swapping the host check between the platforms fails a test, and each case asserts its own upstream body.
|
在 forwardOnce 中对发往 Kimi 两个平台(Kimi Code 会员端点 + Moonshot 开放平台)且模型锁定采样参数的请求,用 withoutFields 删除 temperature/top_p,由服务端按当前模型和模式填默认值:
|
|
hi @yetone , 已经按照要求修复,帮忙看看还有其他问题吗? |
|
感谢更新。在新 head
故意改坏,看
还差两处,改完就可以合:
真实请求:owner 的 Kimi Code key 现在仍然返回 403 |
…xed names TestKimiLockedSampling now covers the cases a mutation could slip past: Kimi Code's k3 (the bare-k branch), kimi-k2.5 (the minor >= 5 boundary), kimi-k2-thinking keeping its temperature (k2 without a version dot is not locked), and a relay's vendor-prefixed moonshotai/kimi-k2.6 (the vendor strip). Each of the three surviving mutants from review — minor >= 6, no bare-k branch, no vendor strip — now fails its subtest.
三个幸存变异体现在都能抓到:minor >= 6 挂(kimi-k2.5)、去掉裸 k 前缀分支挂(k3)、不去 vendor/ 前缀挂(moonshotai/kimi-k2.6),逐条实际改坏验证过。
已跑:gofmt -l internal/gateway/ 无输出;go vet -tags nogui ./internal/gateway/;go build -tags nogui .;go test -tags nogui -count=1 ./internal/gateway/ ./internal/provider/ 整包通过。没跑的同你列的:真实 Kimi 请求(key 403)、全量 go test honlu.。 |
|
hi @yetone 这块代码可以合了吗? |
|
可以合了,感谢耐心改了这么多轮。在 head
故意改坏,看
最后两条没有测试守着,但 Moonshot 现在的列表里没有 kimi-k2.0–k2.4 或 kimi-k1.x 这样的模型,不影响合并。 没跑的:真实 Kimi 400 → 200 对照(owner 的 Kimi Code key 仍然 403 接下来 squash 合并,会在下一个版本里发布。 |
问题
VS Code Copilot Chat 的请求硬编码 temperature: 0.1, top_p: 1。Kimi 两个平台(Moonshot 开放平台 + Kimi Code 会员端点)对部分模型在服务端锁定采样参数,请求里带任何值都会被 400 拒绝:invalid temperature: only 1 is allowed for this model(K2.5/K2.6 关闭 thinking 时只接受 0.6),整个请求在读取任何 token 前失败。
修改
kimi_schema.go 新增 kimiLockedSampling:在 forwardOnce 转发前,对锁定模型用 withoutFields 从请求体删除 temperature 和 top_p(不是改写值,缺失时也不插入)。缺省时服务端按模型和模式自己填入正确值。
主机条件 isKimi(与既有 kimiToolEnumTypes 一致):api.moonshot.ai / api.moonshot.cn / api.kimi.com / api.kimi.ai,或 moonshot* / kimi* preset 前缀。Moonshot 按量付费的 kimi-k2.5+ 同样锁参数(Cherry Studio #19601 佐证),所以不按 Kimi Code 收窄。
模型条件 kimiLockedSamplingModel(先剥 vendor/ 前缀):
锁定:kimi-for-coding*、Kimi Code 的 k3*、kimi-k2.5 及以后(kimi-k2.6、kimi-k3…)
保留用户值:moonshot-v1-*、kimi-k2-0905-preview、kimi-k2-thinking、kimi-latest,以及任何非 Kimi 主机
System One 的分类请求(temperature: 0)也走 /v1/chat/completions → forwardOnce,同锁模型同样覆盖。
测试
TestKimiLockedSampling(12 个子用例,每个独立断言):被拒的(0.1/1)和合法的(1/0.95)值都删;原本不带则不新增;Anthropic 端点同样生效;Kimi Code 的 k3、Moonshot 的 kimi-k2.5(边界)、kimi-k2.6、vendor 前缀名 moonshotai/kimi-k2.6 都删;moonshot-v1-8k、kimi-k2-0905-preview、kimi-k2-thinking 保留用户值;非 Kimi provider 原样透传。
变异测试均确认 FAIL:去掉 forwardOnce 调用挂 4 个;主机条件只认 Kimi Code 挂(kimi-k2.6);模型一律 true 挂(moonshot-v1-8k、kimi-k2-0905-preview);只删 temperature 挂;kimi-for-coding 不算锁定挂;minor >= 6 挂(kimi-k2.5);去掉裸 k 分支挂(k3);不去 vendor/ 前缀挂(moonshotai/kimi-k2.6)。
已跑
gofmt -l internal/gateway/ 无输出;go vet -tags nogui ./internal/gateway/;go build -tags nogui .
go test -tags nogui -count=1 ./internal/gateway/ ./internal/provider/ 整包通过
真实请求:本地编译 PR 二进制替换网关,VS Code Copilot 经 kimi-code-cn 发 4 条 /chat/completions(model: k3),转发 body 无 temperature/top_p,无 400
未跑
真实 Kimi 400 → 200 对照(owner 的 Kimi Code key 目前 403 access_terminated_error),以 k3 实测代替
全量 go test honlu.(改动只在 gateway 包,已跑 gateway + provider 两包)