推理时间减半,代理任务只提速两成——真正的杠杆不在推理速度
我的职业生涯中有相当一部分时间都在优化网站和应用的运行速度,把其中一些原则用到代理式工作流上是件很有意思的事。下面分享几个关键经验——还有很多想法想找时间写下来,但为了简洁,下面算是我处理这类问题的一个大致思维模型。
推理速度
最明显的起点是推理速度。它有两个关键组成部分,做过后端API优化的人应该很熟悉。
第一个是TTFT(time to first token,首个token的生成时间)。它类似于Web服务器中的TTFB(time to first byte,首字节时间),也就是发出请求后,第一个token要多久才能回来。TTFT包含prefill(输入token处理)所需的时间,所以它也会随代理发给推理提供商的token数量增加而升高——这意味着你会看到这个数字出现明显波动,就像在需要做更多数据库调用才能准备响应的端点上,TTFB会更高一样。TTFT越低越好。
提示缓存(prompt caching)在这里绝对至关重要。缓存的token服务起来快得多,也便宜得多。现在大多数代理框架(agent harness)都已经处理得很好——我已经很久没见到这方面的问题了。当然值得保持关注,但在实际经验中,它的重要性比我预想的要低。
第二个是tok/s(tokens per second,每秒生成的token数),它衡量响应开始后token返回的速度。这更接近应用服务器的带宽,数值越高越好。
这两个指标哪个更重要,取决于你期望从LLM提供商那里收到什么类型的响应。如果代理工作流的各轮之间要来回发送大量短响应,TTFT的重要性通常会超过tok/s。反过来,如果需要LLM输出较长内容(比如代码或文档),TTFT的重要性就低于tok/s。
用示意数字来解释一下:TTFT是网络、排队和prefill的总和——也就是任何数据返回前的那段等待时间。tok/s则是开始流式输出后的速度。
搞清楚自己需要哪个指标更快,对比较模型和推理提供商很重要。小模型通常比大模型快,但即使同一模型,不同提供商之间的速度也有巨大差异。OpenRouter确实提供了推理提供商的公开数据,但要记住那是聚合数据,可能只能大致反映你的真实使用情况。注意,即使在同一个模型下,不同提供商的量化(quantisation,压缩)等级也可能不同:一个提供商跑FP8,另一个跑INT4,后者会更快但质量会有损失,比较时必须确保口径一致。
常见的主要问题是,提供商的速度也会随时段和负载大幅变化。TTFT大幅跳升(提示长度差不多的情况下)可能表示提供商侧在排队,也可能只是你的请求被分到了更慢的硬件,或是有更多用户在争夺prefill计算资源。同样,tok/s变慢可能说明底层硬件变慢或提供商批处理的并发度变高。总而言之,很多推理提供商都有严重的“吵闹邻居”(noisy neighbour)问题——同一台共享硬件上其他用户资源占用高时,你的速度就会被拖慢。在VM上通常可以通过vmstat的steal列观察到这种情况,但推理提供商那边的负载则非常不透明。
当然,很多提供商也提供不同服务等级。比如OpenAI在标准档和“快速”档之外还有"flex“档,用速度换成本。但不要忽视思考预算(thinking budgets)的影响。把”快速“档模型的思考预算设成maximum或xhigh,它会比”慢“档模型设成low或medium慢得多。我在看这些数据时经常栽在思考预算上,但它带来的差异是压倒性的。人们很容易被量化的tok/s和TTFT数字吸引,而实际上,如果任务允许,调低思考预算带来的提速效果可以完全碾压这两个指标。
不仅限于推理速度
虽然更快的推理速度永远不坏,但要注意,它往往不是加速代理的最大杠杆,而且提速的代价可能很高(为更快档位付费),或者更换推理提供商很麻烦(如果有已承诺的消费或合同要求)。粗略地估算,在预置、工具和挂起/恢复都不变的情况下,把推理时间减半,整个任务也只能提速约20%。
所以,值得更仔细地去查看工具调用。这更像经典性能优化工作,但我注意到一些平时不该慢的地方会变慢。一个经典例子是代理在大量文件上运行xargs -I{},这会引起几十万次新进程调用,在沙箱环境里尤其慢得可怕。
经典软件性能工程的规则对代理工具调用照样适用,但你需要看工具调用轨迹(tool call traces),了解代理到底做了什么。代理经常会把一串bash命令连起来完成一个目标,要看出哪一环拖慢了速度并不容易。strace很有用,但不适合一直开着,因为它本身也有性能开销。
工具输出的大小也很关键。虽然大多数代理框架在阻止cat式命令撑爆上下文窗口上相当严格,但如前所述,未缓存的输入token会直接影响TTFT。如果你能让代理直接访问SQL风格的数据源,那是很大的优势——它可以精确取回需要的数据,而不用靠一个范围很大的awk命令抓回几千个token的无关内容。
另外,许多代理每条命令都会新开一个shell,所以。bashrc里一些平时无所谓的配置可能变成真问题。注意shell启动时要加载什么——特别是如果里面放了nvm或类似的工具。你还没反应过来,启动shell的时间就已经远超执行命令本身的时间了。
构建代理想要的工具
在”把这个命令变快“这个显而易见的层面之上,我认为下一步是认真想清楚:代理需要什么工具,以及它正在”绕开“什么。比如,如果你反复让代理对markdown文件跑xargs,那也许把数据放进一个支持全文搜索的数据库里,会比让它一遍遍扫描文件好得多。
这正是我的软件优化思维模型里比较不同的地方。通常你会看一个请求、观察它在做什么、把每一段变快,然后重复循环。而面对代理工作流,你往往只需要观察代理的行为,就能推断出什么对它更有利。所以,只看工具调用轨迹反而容易误导。
我发现开放权重(open weights)模型在这方面有巨大优势,因为你能直接读到它们的思维轨迹。CoT(Chain-of-Thought,思维链)轨迹一直是实验室做安全和对齐的重要材料,但事实证明,对设计给代理用的工具,它们同样是绝佳的灵感来源。
我的做法是:拿到一批慢调用的清单,然后去看这些调用之前的思考块。你通常会看到类似”嗯,可以做x,但没有y“这种一眼就懂的念头,然后直接把代理想要的东西给它,再观察效果。
另一个值得留意的是:把带sleep的for循环当成一个危险信号。这说明代理其实是在等某件事的通知,但只能靠轮询。代理轮询的对象往往本身很快,但它在for循环里通常会设10秒或20秒的最小等待时间。这个问题有时靠提示词(prompting)就能解决,但更多时候,它意味着(通常是外部的)服务应该提供一种异步方式来回传任务完成事件。
最后,并行化对缩短工具执行时间很有帮助。加一句简单的”尝试在$TASK里并行化工具调用“常常就有奇效,但模型越弱,代理越容易犯错并抵消效率收益。所以,直接给代理提供能并行完成这些步骤的工具(CLI或MCP)会是更稳妥的选择。
硬件提醒
在我的职业生涯里,因为主要跟云计算平台打交道,我经常发现最省事的快速修复就是直接换更快的硬件。这里说的”更快的硬件“不是指换更大的AWS实例,而是要深入看代理运行的底层硬件:具体用的CPU核心类型(Zen 4c/5c这种小核心可能比完整大核慢不少)、时钟频率、文件IO速度。
这跟代理的任务类型关系很大,但如果代理需要写大量自定义代码或做大量数据分析,底层硬件快不快影响非常大。例如,代理的任务如果是IO密集型,你会发现很多延迟来自网络磁盘。换成更快的本地NVMe磁盘,IO性能可能要好几个数量级。
这个问题在沙箱环境里往往更严重。写时复制(copy on write)和各种快照技术会给文件IO带来很大开销,底层IO一慢,所有事情都跟着变慢。
挂起与恢复
我经常看到挂起和恢复(suspend and resume)环节出现真实的速度问题。不是所有代理工作流都会用到,但如果你允许代理在人工审批(human in the loop)时暂停,那优化挂起和恢复的细节就必须留意。
MicroVM(微虚拟机)在纸面上通常能极快地恢复,但实际运行时,页面往往在首次访问时才被流式载入。所以你不能只看MicroVM自报的恢复速度,还要实测恢复之后新的推理请求要多久才能真正开始。
这里的关键是小心处理内存管理。你当然不希望VM内存不够而触发swap或OOM,但同样值得在挂起前调查内存到底被什么占用了。如果有无头浏览器会话(headless browser session)在跑,基本确定应该在挂起前把它杀掉,代理可能启动的任何服务器进程也一样。
一如既往,最重要的是测量和跟踪RAM使用情况;如果挂起/恢复的循环很频繁,还需要按时间维度拆开来看。
最后查一下网络。我的经验里,沙箱环境中IPv6配置损坏非常常见,结果每次请求都在DNS的AAAA查询上撞到网络超时,给每个请求都增加了一点点额外开销。这类基础卫生问题在代理会话过程中会不断累积。
关键要点
在任何代理优化项目里,我会优先检查这些事:
- 推理速度很微妙,要先弄清楚你最依赖推理的哪个环节。
- 检查思考预算!这是最大也最明显的”低垂果实"(low hanging fruit,指最容易摘取的成果)。
- 读轨迹;如果你用的是开放权重模型,读CoT思维轨迹。里面通常有大量关于代理真实意图的宝贵线索。
- 给代理它真正想要的工具,而不是你认为它需要的工具。
- 别忽视基础项。更快的硬件仍然重要,沙箱和MicroVM会带来一大堆潜在性能陷阱,并行化有用,经典软件性能优化跟以前一样适用。
这个领域还在快速演进,紧跟前沿一直是我让系统保持高性能的北极星。如果你也在做代理提速的事,我很想知道你的经验,特别是有没有发现我漏掉了什么明显的因素。