流式的收益是分场景的,而且分得比大多数人以为的更开。模型直接开口说话,流式几乎是白捡的体验;模型先调工具再开口,流式基本没用——用户盯着的那段空白,等的不是模型,是工具。这周翻到几篇东西,恰好把这条线划得更清楚了一点。
直接说话的场景,流式是白捡的
聊天、补全、翻译、总结。这类任务里模型是唯一的瓶颈,第一个 token 出来得快,后面匀速吐。用户看到的不是"结果",是"正在发生"。同样等一会儿,光标一个一个跳和屏幕卡死不动,感受完全不一样。这个不用测,你自己拿两个产品对着用就能感觉到。
所以这类场景,流式该做,而且要做好:首 token 延迟、吐字节奏、markdown 别在中间抖。这些都是能直接换来留存的。
调工具再说话,流式等于没做
问题在这。链路一旦变成"模型 → 工具 → 模型",流式的第一个 token 就被工具挡住了。工具跑多久,用户就干等多久。
KaliBench 这类评测在测什么?测模型能不能对 Kali 里的真实工具生成可执行命令。它关心命令对不对,不关心命令跑完之前界面长什么样。Argo-Bench 更明显,企业级数据分析,几十张表、统计检验、再基于结果行动——工具阶段天然就慢。
这时候你把 streaming 打开,会发生什么?模型确实在流,但流出来的是工具调用的参数 JSON,人看不懂,前端也基本不渲染。用户看到的还是空白。
为了流式而流式,等于造一段假空白
我见过一种做法:为了让界面"看起来在动",模型先吐一句"好的,我来帮你查一下",然后卡住,等工具跑完再继续。这不是流式,是拖延。用户第一次会信,第二次就烦了——他知道那句话是假的,后面的空白才是真的。
还有一种:把工具执行日志原样打进对话。一堆 JSON 和 stderr,看着很"透明",其实是把内部复杂度甩给用户。
两种是同一个毛病:把"有输出"当成目标,而不是把"用户在等什么"当成目标。
该推的是进度事件,不是 token
我的做法是,工具阶段推结构化事件,不推文本。大致三类:tool_start(要调什么、参数是什么)、tool_progress(跑到哪一步、已完成几项)、tool_result(拿到什么、下一步干嘛)。前端不渲染成对话气泡,渲染成步骤条或者时间线。
比假装流式诚实的地方在于:它不承诺"马上有答案",它承诺"我知道现在在干嘛"。用户对后者的容忍度高得多。
Mimir 讲长周期灌溉控制,说得很直白:动作会改未来状态,错误会累积,而且不能重来。这种场景里"首 token 快"是个伪指标,用户要的是知道现在到哪了、还剩多少。Dots 那种 always-on agent 更是如此——它一直跑着,你不可能盯着屏幕,你需要它主动报进度,而不是等你打开窗口才看到结果。
顺便说一句,现在主流 API 的流式协议里其实早就有工具调用相关的事件类型,问题是大部分前端把它们吞了,只取文本 delta。要改的东西不多。
延迟优化和感知优化,别混
Magnitude 这类在做推理引擎层面的优化,那是真降延迟,把工具调用和推理调度压紧。流式做的是感知层。两个都要,但顺序别搞反:先看你的耗时到底花在哪。埋个点,把首 token 时间拆成"模型首 token"和"工具总耗时"两段。如果工具占大头,你在流式上再怎么雕花,用户该等还是等。
按我现在看,流式在"模型是唯一瓶颈"的场景里价值被高估不了——它本来就该有。但在 agent 场景里把它当成体验解法,方向就错了。也许过一阵工具调用快到另一个水平,这话会被打脸,那我也认。