上个月我把一个内部工具从闭源 API 换到本地部署的开源模型,跑了两周,又换回去一半。
不是因为效果差。恰恰相反,它在结构化任务上的表现比我预期好。换回去的原因很朴素:我算错了账。省下的调用费,最后以机器、运维和调试时间的形式还了回去,而且还多付了一点。
DeepSeek V4 这类模型真正改变的东西,是“开源模型能不能干活”这个问题,答案从“勉强”变成了“可以”。但它没有改变另一个问题:干活和干得好之间,还有一段距离。
长上下文不等于理解
百万级上下文是这一代模型最容易被误读的参数。
我做过一次很典型的测试:把一个项目的全部文档一次性投进去,问一个横跨三份文档的接口约定。它答得很快,格式也漂亮,但引用的是一份已经废弃的版本。三份文档里有两份写着同一个字段的新旧两种含义,它选了错的那份,并且语气没有任何犹豫。
窗口变大解决的是“不用切分”,不解决“注意力怎么分配”。这两件事经常被混为一谈。把材料全部塞进去,只是省掉了检索和拼装的工作,理解的质量仍然取决于模型能不能在长序列里维持住约束。
后来我改了一个习惯:不管窗口多大,都要求它指出答案来自哪一段。这个要求本身不提高理解力,但它让错误暴露得更早。它引用错版本的时候,我一眼就能看见,而不是等下游系统报错。
长上下文真正的价值,我觉得是减少状态断裂。多轮任务里最怕的不是某一步答错,是中间某次切分把关键约束切掉了,后面的推理全建在残缺的前提上。一次投进去能缓解这个问题,但缓解不等于解决,因为上下文里如果同时存在新旧两版信息,模型仍然要自己选一个。
长上下文的成本也常被低估。上下文越长,首 token 的等待越久,单次请求占的显存越多,并发一上来就开始排队。我最后把默认窗口压到二十万左右,超了就走摘要或检索。不是模型不行,是账单不允许。
我评测长上下文的方式也变了。不再问“能不能归纳这篇长文”,而是给三份互相矛盾的文档,问它能不能指出冲突在哪。归纳能力早就不缺,缺的是在噪声里保持判断。
所以我现在用长上下文的方式比较保守:把它当成减少切片的工具,而不是减少整理的借口。该做的摘要、该标的引用点、该拆的子任务,一样都不省。窗口是容量,不是能力。
稀疏激活省的是算力,不是显存
MoE 的账很容易算错。
公开说法是总参数规模很大,单次前向只激活其中一部分,活跃参数在 32B 量级。这个设计确实把推理计算量压下来了,单位 token 的成本比同规模稠密模型低得多。但它压的不是显存:权重还是要完整放进去,KV cache 还会随上下文长度增长。
我第一次按“32B 能跑”去估机器,结论是单机足够。实际把上下文开到几十万 token,直接 OOM。后来才想明白,长上下文场景里最占地方的往往不是模型本体,是缓存。
能选的路线只有三条,每条都有代价:
- 接受更短的上下文,把任务拆小,代价是工程复杂度上升
- 加卡,代价是钱,而且并行度上去以后通信和容错都变难
- 量化,代价是长上下文下的稳定性会掉一点,掉多少得自己测
多卡还有一些隐形成本。张量并行能分摊权重和缓存,专家并行能缓解稀疏激活带来的负载不均,但两者都会引入通信开销;卡越多,单次请求的尾延迟越难看。小团队最容易忽略这一点:吞吐上去了,体验反而变差。
还有一个现实约束是硬件。消费级卡能跑量化版本,但吞吐很难看;租卡按小时计费,空闲时间也在烧钱。自托管的经济性只在利用率足够高的时候成立,这一点和买服务器做网站是一样的。
还有一层成本不在机器上:版本。自托管意味着模型升级、依赖升级、驱动升级都要自己跟,升级之后还要重跑一遍回归。API 把这些活接过去了,自托管又原样还回来。
另一个坑是长度和并发的权衡。长上下文请求一多,吞吐掉得比预期快,排队时间会掩盖掉单次推理的便宜。这个账只能用真实流量测,不能看单条基准。
我最后选了拆任务,因为我的场景本来就可以拆。这不是普适答案,只是在我这里,拆任务比加机器便宜。
还有一个反直觉的结论:并发低的时候,自托管不一定省钱。一张卡空转的成本是固定的,而 API 是按用量计费。调用量本来就小的时候,省下来的钱可能还不够付电费和运维时间。这笔账要按峰值和利用率算,不能按平均值算。
Agent 场景里,失败点不在“答错”
多步任务是我最关心的部分,也是这批开源模型进步最明显的地方。它能连续跑十几步不跑偏,跨文件定位问题的能力比上一代好很多。
但失败模式非常固定,而且不像“答错”那么容易被发现:
它会跳步。明明应该先分析再给补丁,它直接给补丁,看起来还挺合理。
它会把不存在的文件当成真实依赖。上下文里提过一次的路径,它后面就默认存在。
它会在长流程里悄悄改掉早期的设定。第三步定好的变量含义,到第十五步变成了另一个意思,而且它自己不觉得矛盾。
这三类问题,加提示词只能缓解,不能解决。真正有用的是外部结构。我后来在自己的流水线里加了三样东西:步数上限,每一步的结构化状态,以及失败之后重跑测试而不是重跑整个任务。加完这三样,成功率上去了,延迟和成本也上去了。这是一个明确的交换,不是免费的提升。
如果要给这几类失败排优先级,我会先修状态,再修工具,最后修提示词。状态错了,后面全错;工具错了,错误会写进真实系统;提示词错了,最多是表达不好。
评估多步任务的方式也要改。只看最终产物对不对,会漏掉很多信息。我现在会把一次执行拆成检索、分析、执行、校验四段,分别看它有没有漏掉中间产物、有没有在依赖关系上编造、有没有在最后一步把没验证的结果说成已验证。
工具调用一多,还有一个副作用:上下文膨胀得比想象中快。一次搜索返回几千字,一次日志查询返回几百行,十几次之后窗口就满了。我现在要求工具返回结构化摘要,原始内容落盘,模型只拿需要的字段。这个改动听起来不聪明,但它把很多长任务从“跑一半失忆”变成了“跑完还能复盘”。
代价是,这套判断方式很费时间。每换一个任务,都要重新设计状态字段和验证器,复用性比想象中差。我现在接受这件事:通用 Agent 离我还很远,先把一个任务做稳,比做十个半成品有用。
有意思的是,单步正确率更高的模型,在多步任务里不一定更可靠。长链路考验的是状态保持和错误恢复,而这两件事更多由外层结构决定。这也是我后来越来越不看重“跑分高一点”的原因。
我还在用闭源的地方
创意写作、语气控制、开放式策略判断,这三类我仍然用闭源。
不是我懒。V4 的输出偏结构化,逻辑优先,写长文的时候有一种挥之不去的“解释感”:每一段都在说明它在论证什么,读起来累。让它模仿某种语气,前两句还行,第三句就开始漂。
我在写作上试过让它改稿,结果是把句子改得更整齐,也更容易空。它会把具体的东西抽象成概念,把犹豫改成判断。这两件事对一篇要发表的东西是致命的。
这不算缺陷,是训练目标的差异。推理和代码是可以被验证的,语感不行。一个模型在可验证的任务上变强,和在不可验证的任务上变强,本来就不是同一件事。
开源真正的优势,其实不是便宜,是可控。权重在自己手里,意味着可以裁剪、可以私有化、可以把敏感数据留在内网、可以在模型外面加审计。这些对做产品的人是实打实的价值,只是它们不会出现在跑分榜上。
如果只算钱,自托管在多数小团队里并不划算。API 按用量计费,自建按峰值付费,调用量小的时候,省下的钱还不够付电费和运维时间。真正让它值得的是另外两件事:数据不出内网,以及行为可以审计。前者是合规要求,后者是排障需要。我做的工具涉及内部文档,把内容发到外部接口这件事本身就要走一轮审批,这个成本不在账单上,但它在。
开源模型的迭代速度也是我留下它的原因。权重公开之后,社区会在几周内给出量化版本、推理优化和针对特定任务的微调。闭源模型的能力提升是厂商决定的,开源的是可以参与的。这个差别短期看不出来,长期会累积。
调优那条路我也试过一点。系统提示能解决大部分输出格式问题,检索能解决事实性问题,LoRA 我只在很小的场景里用过。多数时候,前两步就够了;上微调往往不是模型不够好,是需求本身没想清楚。而且微调之后的模型要重新做评估,这部分工作量经常被低估。
我也不觉得开源和闭源是对立阵营。它们更像两种交付方式,一种把控制权给使用者,一种把维护责任留给厂商。选哪个,取决于团队里有没有人愿意接这份责任。
我现在的默认配置是混合:能自动验证的任务交给开源,需要语感和模糊判断的交给闭源。这个分法很土,但它是我试了两周之后唯一能说清楚的结论。
以后可能会变。等开源模型在长上下文下的稳定性再好一点,或者我的任务再窄一点,这条线还会往左移。但现在,我不打算为了“全部自托管”这个目标,去承担那些本来可以避免的调试时间。
评论