除了上一篇让 DeepSeek 超过 Opus 4.7 网页链接 ,Ahmad Awais还分享了使用 Kimi K2.6 的经验: ---------------------------------我们是怎么让 Kimi K2.6 几乎打平 Opus 4.7 的?
“开源模型不擅长写代码”不是模型问题,而是 coding agent 的 harness 问题!
如果你用 Claude Code 去跑开源模型,那你大概率跑不出来。他们并不想让开放模型赢。
我这一周很奇怪。同一个模型,DeepSeek V4 Pro,在我们的内部评测里 6/10 次打败 Opus;Kimi K2.6 也差不多,打到了 5/10。
提示词一样,checkpoint 一样,temperature 一样。唯一变化的是 gateway 选择了哪个上游。
我认为很多“开源模型不擅长写代码”,其实是“开源模型在冷缓存上跑”。当你说某个模型赢了评测时,你真正说的是:
模型 + provider + 缓存状态 赢了评测。
harness 决定的是后两者。
背景:我一直在做 CommandCodeAI 的开源模型路径,跑 Kimi K2.6、DeepSeek V4 Pro、GLM、Qwen,通过一组推理 provider 做 fanout。我们在构建 Command Code agent 的每月 1 美元 Go plan。
最后,Kimi K2.6 在更难、工具调用更重的评测切片上,已经能做到 5/10 接近 Opus 4.7;DeepSeek V4 Pro 做到 6/10。主要靠四个小的管道改动。它们都没有改模型。
我学到的一些东西,感觉具有普遍性:
1/ 最大的单点收益,来自一个 HTTP header
闭源模型把 prompt caching 做成了产品。开源模型没有这种产品化缓存。它们有的是 prefix cache:推理服务器把最近 N 次前向计算保留在 GPU 的 KV memory 里。如果一个请求和最近请求共享同样前缀,就能跳过重新 prefill。
这是计算时间层面的缓存,不是产品层面的套餐能力。而且只要你的请求落到另一个节点上,它就没了。
一个 coding agent 本质上就是在利用 prefix cache:
好的 system prompt:大约 10k token,基本不变;工具列表:不变;对话:只追加,不重写。
除了第一轮以外,后面每一轮都应该几乎完全命中缓存。理论上应该如此。
但我们发现:同一个对话的连续轮次被负载均衡到了不同的 GPU pod。每个 pod 都必须重新 prefill 约 10k token 的前缀。TTFT,也就是首 token 延迟,是 6 到 8 秒。
模型并不慢,是负载均衡器把我们的缓存偷走了。
修复就是一行。但因为我们同时和多个 provider 以及负载均衡打交道,它表现为一种 soft pin:同一个值尽量落到同一个 pod。CLI 里本来就有稳定的 session id,我们把它转发过去。
缓存命中后的轮次里,TTFT 从 6 到 8 秒降到了 1 秒以内。
这对评测也很重要:当前缀缓存是热的,模型可以把全部预算用在新 token 上。小型开源模型如果冷 prefill,会吃掉很多延迟;而在 Opus 上,这个成本是不可见的,因为 Anthropic 的基础设施里已经内建了产品级缓存。
闭源模型静默地吃掉这个成本。开源模型大声地吃掉这个成本,然后我们怪模型。
这就像开了一个小时的会,你对对话进展一直有连贯理解。如果你每次发言前都必须重新看一遍会议纪要,你当然会慢,也会忘事。模型也是一样。
在 Command Code,我们正在为开源模型,也包括闭源模型,构建最好的 coding agent harness。这是一个很棒的修复:用户省钱,速度更快,模型看起来也免费变强了。
2/ 规范化模型 ID 是关键抽象
我们会把同一个模型,比如 kimi-k2-6,按优先级路由到最多三个 provider:
providerOne,p1,最低 p50;providerTwo,p2;providerThree,p3。
每个 provider 都想要不同的模型 slug:
moonshotai/Kimi-K2-Instructmoonshot/kimi-k2-6每个 provider 又想要不同的请求形状:
p2 要 providerOptions.gatewayp3 要 headersp1 要自己的 auth header
诱惑是:一路把每个 provider 的请求形状都 fork 到 agent loop 里。不要这么做。
我们让一个规范化 ID,也就是 kimi-k2-6,贯穿整个请求、计费、遥测、评测和 fallback。slug 翻译只发生在一个边界:
getProviderModelId(provider, canonicalId)
它在 buildOSSLanguageModel 里调用,也就是在我们真正把字节交给 SDK 的那一刻调用。
这在 fallback 时尤其重要。
当 p1 在 stream 中途 503,然后我们切到 p2 时,我们重新应用:
applyEntryOptions(params, entry, canonicalId)
gateway options 会针对新的 provider entry 重新构建,message array 保持不变,canonical id 也不变。
在我们的 usage logs 里,所有 Kimi 调用都是 kimi-k2-6,无论实际由哪个 GPU 提供服务。这样评测不会撒谎:你知道你测试的到底是哪个模型。
如果你曾经 debug 过“这一轮到底是去了 p2 还是 p3”,你就知道这为什么重要。
这里的缓存工程体验,属于非常先进的工程。我作为工程师,构建这个东西真的很开心。
3/ capability flags 需要按 provider 协商
我们会向 gateway 请求:
zeroDataRetention: truedisallowPromptTraining: true
这些是请求级别的,不是逐上游的。gateway 对每个 flag 都是全有或全无。如果我们白名单里的任何 provider 不支持某个 flag,gateway 就会报:
NoNonTrainingProvidersError
然后请求直接死掉。
最初的代码路径是:两个 flag 都硬编码开启。结果一半模型都坏了。比如 Novita 支持 no-training 但不支持 ZDR,Fireworks 支持 ZDR 但不支持 no-training。注意这些每个月都会变,要看当前 capability table,别信这里列的例子。
修复方式是:根据白名单里的上游是否缺少某个能力,独立地丢掉对应 flag。
这发生在 buildGatewayOptions,同一个文件里。
这样请求会带着“这个 provider 集合实际共同支持的保证”继续执行。你不能要求一个路由集合提供它不存在的属性。
这和上周的工具输入修复是同一种形状:
当你撞墙时,应该问的是:
这个上游集合实际能共同遵守的最小契约是什么?
而不是:
我该怎么强行把我偏好的契约塞进去?
我对这个还没那么满意,仍在处理各种边角问题,也想让用户更容易在 ZDR 和成本管理之间做选择。
4/ 最好笑的 bug,是一个 thinking mode 回归
DeepSeek V4 Pro 通过 p2 进行多轮对话时,每次 continuation 都开始 400:
the reasoning_content in the thinking mode must be passed back to the api.
发生了什么?
gateway 侧的 converter 把 R1 的 reasoning-stripping 逻辑应用到了 V4 上。R1 会返回 reasoning_content,你必须把它回传。V4 不返回,你也不该回传。converter 把它剥掉之后,上游因为缺少它而拒绝,于是每个多轮对话都在第二轮死掉。
修复在 getReasoningProviderOptions 里。
DeepSeek V4 Pro 现在端到端都作为非 thinking 模型运行。converter 没有东西可删,多轮就能工作。
我们失去了 reasoning。这会让一些困难的一次性谜题掉几分。但 coding agent 不是一次性谜题,它是 40 轮循环。第二轮不 400,比第一轮有 chain-of-thought 更重要。
后来我们又弄清楚了,如何在运行时修复工具调用的同时,教开源模型理解它们的 toolCalls 哪里错了。昨天我写过一个详细 thread,感兴趣可以去看。
拉远看
四件事,没有一件是关于模型本身的:
在对话和 provider 之间保持 prefix cache 热着。这是 harness 的工作,不是模型或 provider 的工作。使用一个抽象:请求层用 canonical id,SDK 边界再做 slug translation,这样 fallback 对计费和评测不可见。使用一个过滤器:根据每个上游的能力集合,独立丢弃 capability flags,避免 gateway 因属性不匹配而拒绝请求。对单个 provider 前缀的上游 SDK bug 做一个 workaround:禁用 thinking,避免多轮对话坏掉。与此同时,用确定性方式教模型修正 tool calls,而不是只给它错误,导致静默失败。
模型没有变聪明。是 harness 不再在每一轮之间把模型已经做过的工作丢掉。
闭源模型的 harness 可以在这四件事上偷懒,因为 Anthropic 和 OpenAI 会在服务端吃掉成本:它们的缓存是内建的,模型 ID 是无歧义的,capability flags 是一致的,工具契约也已经在预训练里见过。
开源模型的 harness 不能在任何一个环节偷懒。只要懒了一个环节,模型就会在本来能赢的 eval 或 vibe check 里“输掉”。
DeepSeek V4 Pro 现在在我们的内部评测里 6/10 次打败 Opus 4.7。Kimi K2.6 达到 5/10。模型权重没有任何变化。
在我看来,如果你的开源模型“写代码很差”,大多数情况下是你在用错误的 coding agent harness。那个 harness 要么根本不在乎你的模型,只想泛化到几百个模型;要么只关心那些已经有产品级缓存的闭源模型。
这些修复你都可以试,已经上线了。
AI创造营How I AI
