让 Agent 当自己的预言家:自推测如何把工具调用延迟藏起来
让 Agent 当自己的预言家:自推测如何把工具调用延迟藏起来
场景:你在等搜索结果的时候,GPU 在发呆
假设你写了一个 LLM 搜索代理,让它回答"2026 年 Nature 上最反直觉的物理学发现是什么"。它思考了几秒,决定调用搜索工具 web_search("Nature 2026 physics counterintuitive")。然后——等。搜索 API 返回要 300 毫秒到 2 秒不等,模型在这段时间里什么也做不了,就干等着。
这不是个例。UCSB 和 LinkedIn 的团队在 2026 年 7 月的论文 *Speculate While You Reason* 里算过一笔账:LLM agent 的推理时间里,相当大一部分花在等工具返回上——搜索、数据库查询、代码执行、调子 LLM,每一个都是远程调用。token 生成是毫秒级,工具调用是百毫秒到秒级,差了一个数量级。
这让我想起一个老问题:CPU 流水线里,分支指令要等条件计算完才能确定下一步去哪。上世纪 90 年代的解法是分支预测——不等条件算完,先猜一个方向,把那条路的指令提前取出来执行。猜对了,白赚一段时间;猜错了,扔掉重来。现代 CPU 的分支预测准确率超过 95%,这个机制撑起了整个流水线效率。
论文的核心洞察就一句话:把分支预测搬进 LLM 工具调用。在 agent 还在推理的时候,提前猜它下一步会调哪个工具、传什么参数,把这个调用先发出去。猜对了,结果已经准备好了,agent 拿来就用;猜错了,丢弃,等真正的调用返回。
但这里有个关键问题:谁来猜?
外部预言家的问题:speculator-agent gap
最直觉的方案是配一个小模型当"预言家"。主 agent 是 4B,配一个 0.6B 的小模型,看到当前轨迹前缀,预测下一步工具调用。这就像 CPU 里用简单预测器配合复杂预测器。
论文先测了这个方案。结果很尴尬:
| Speculator | MuSiQue Hit@1 | τ-bench Hit@1 |
|---|---|---|
| Qwen3-0.6B(外部) | 4.3% | 16.8% |
| Qwen3-1.7B(外部) | 14.7% | 25.4% |
| Qwen3-4B self(自己猜自己) | 25.3% | 37.2% |
year 和 month 两个字段,它对某些查询有偏好。这些是部署时才形成的习惯,外部小模型根本不知道。更糟的是开销。外部 speculator 要单独加载模型权重,要维护自己的 KV cache,每次切换还要在 GPU 上换参数。论文测下来,外部 1.7B speculator 让推理时间从 8.3 秒涨到 33.1 秒,内存从 8.7GB 涨到 12.8GB。为了藏延迟,先引入了更多延迟——这是典型的工程反讽。
关键设计:一个模型,两种模式
论文的方案简洁得有点反直觉:让 agent 自己当自己的 speculator。
具体怎么做?同一个 4B 模型,同一个参数集,加一个"speculation suffix"——一段固定提示词,告诉模型"现在进入预测模式,不要自己推理,直接输出下一步会调什么工具"。模型看到的前缀还是原来那条轨迹,只是末尾多了这段后缀。KV cache 完全复用,没有额外模型,没有额外内存。
这个设计最漂亮的地方在于:speculator 看到的上下文和 agent 看到的完全一样。没有 speculator-agent gap,因为 speculator 就是 agent。它知道自己的偏好,知道自己的参数习惯,知道自己在什么情况下会调什么工具。
但问题来了:一个模型既要会解题,又要会预测自己下一步调什么,这两个目标会不会打架?RL 训练里,优化一个目标往往会让另一个目标变差。
Joint Agent-Speculator RL:轮流坐庄
论文的核心技术贡献是联合 agent-speculator 强化学习。思路是:数据共享,更新分离。
每一轮训练: 1. 采样一批 query,让 agent 模式跑出 G=8 条轨迹。 2. 这些轨迹既是 agent 的训练数据(用最终答案对不对算 reward),也是 speculator 的训练数据——每一步工具调用前的前缀,加上 speculation suffix,就是 speculator 的输入;agent 实际调的工具,就是 speculator 的目标。 3. 交替更新:这一步训 agent,下一步训 speculator,轮流来。
这里有个精妙的细节:speculator 的训练目标是on-policy的——它预测的不是某个固定的"标准答案",而是当前这个 agent 在当前这一版策略下会怎么调工具。agent 每变一次,speculator 的目标也跟着变。这避免了 speculator 去拟合一个过时的"agent 行为快照"。
reward 设计也很有讲究。工具调用是结构化的 a = (name, args),论文分两部分打分:
- 工具名对不对:
R_name = 1[name_hat = name] - 参数对不对:在工具名对的前提下,对每个参数 key 算 token-F1,取宏平均
- 最终:
R_sp = R_name × R_args
三个稳定化技巧:别让两个目标打架
联合训练最大的风险是模式干扰——agent 更新和 speculator 更新互相破坏。论文试了三个技巧,每个都关键:
SFT warmup:RL 之前先用少量成功轨迹和 speculation 例子做 SFT,让模型学会"看到 speculation suffix 就输出结构化工具调用"的格式。没有这一步,RL 早期会浪费在学格式上,speculation reward 不稳定。
Optimizer reset:切换模式时重置优化器状态。Adam 的动量和自适应学习率是从历史梯度估出来的,如果 agent 模式积累的动量被带到 speculator 模式,会把 speculator 更新推到错误方向。重置让每个模式从零开始积累动量。
Alternating schedule:不要 1:1 交替(一步 agent 一步 speculator),要给 speculator 更长的连续更新块。论文测了 1:1、2:2、4:4、4:8 四种 schedule:
| Schedule | Avg Hit@1 | Avg Success |
|---|---|---|
| 1:1 | 31.8 | 10.3 |
| 2:2 | 41.8 | 22.9 |
| 4:4 | 50.3 | 24.4 |
| 4:8 | 55.2 | 26.1 |
关键数据:从 44.1 到 61.2
主实验在两类任务上跑:agentic SearchQA(多跳问答+搜索工具)和 τ-bench(航空/零售场景的对话式工具调用)。
| Model | 阶段 | Avg Hit@1 | Avg Task Success |
|---|---|---|---|
| Qwen3-4B | Base self | 29.1 | - |
| SFT warmup | 44.1 | - | |
| Joint RL | 61.2 | 26.6 → 27.7 | |
| Qwen3.5-4B | Base self | 33.2 | - |
| SFT warmup | 48.9 | - | |
| Joint RL | 66.3 | 49.2 → 50.6 |
1. SFT warmup 本身就把 speculator 能力从 29% 拉到 44%——模型一旦学会"看到 speculation suffix 就输出结构化调用",它本来就有的 agent 知识就能直接用上。这印证了 speculator-agent gap 的存在:4B 自己当 speculator,能力一直都在,只是没人告诉它"现在你是 speculator"。
2. Joint RL 再拉 17 个点,从 44.1 到 61.2。这部分提升来自 on-policy 训练——让 speculator 跟上 agent 当前版本的偏好。
3. Task success 几乎不变(26.6→27.7,49.2→50.6)。这是最关键的结果:speculation 能力的提升没有以任务能力为代价。一个模型同时当 agent 和 speculator,两个职责可以共存。
4. 跨域泛化:在 SearchQA 上训练的 speculator,放到 τ-bench 上测,Hit@1 仍然有提升。speculation 能力有一定的跨任务迁移性——模型学到的不只是"这个任务里我习惯调什么",而是"我作为一个 agent,在看到某种前缀时会怎么调工具"的元能力。
工程洞察:什么能搬,什么不能搬
论文很诚实地划了边界:这套方法只适用于 read-only 工具。搜索、检索、数据库查询、只读 API——这些调错了直接扔掉就行,没有副作用。但如果是下单、改数据库、发邮件、触发不可逆工作流,speculative execution 就危险了,需要 dry-run 模式、事务回滚、人工确认等额外保护。
这个限制其实和 CPU 分支预测完全一致。CPU 分支预测只对"纯计算"指令做推测执行,不会对"写内存"或"触发 IO"做推测——因为那些操作有副作用,猜错了不能撤。推测执行的安全边界是"操作是否可逆",这个原则从 CPU 到 LLM agent 通用。
另一个工程细节:KV cache 复用是这套方案能省资源的关键。外部 speculator 要维护两套 KV cache(agent 的和 speculator 的),内存翻倍。self-speculation 复用 agent 的 prefix KV cache,只在 speculation suffix 那一小段额外算几个 token 的 cache,开销几乎可以忽略。这和"参数共享但模式分离"的设计哲学一致——分工不一定要分家。
个人思考:概念谱系的新成员
这篇论文让我重新审视之前一直在追踪的一个概念谱系——"换层面解决问题"。从章鱼 RNA 编辑到黏菌外化记忆,从 SOPHIA 分工到 EvoThink 原子推理,再到 Möbius RoPE 拓扑干预,每个案例都是"不直接优化原问题,而是换一个层面"。
这篇论文是谱系的第 12 个成员:不把工具调用延迟当作"必须承受的成本",而是换到预测层面,让延迟被藏起来。更精确地说,它不是"让工具更快",而是"让等待变得无关紧要"——通过提前执行,把串行的"推理→调用→等结果→继续推理"变成并行的"推理的同时,预执行下一步"。
但这里还有个更深的洞察。我之前一直说"分工比统一更有效"——章鱼 DNA 预训练+RNA 推理时计算、Euclid-MCP 让 LLM 当诗人+Prolog 当会计、Rebucca 小模型初筛+大模型复核。这篇论文表面上是"反分工"——把 speculator 和 agent 合并成一个模型。但仔细看,它其实是分工的更精细形式:参数共享,但模式分离;数据共享,但更新分离。分工不一定要分家——职责可以分,但载体可以合。这比"完全分工"和"完全统一"都更精细。
最后,on-policy 这个设计选择让我想到一个更普遍的原则:预测模型的目标应该来自被预测对象的当前行为,而不是某个固定的历史快照。这和推荐系统里的"在线学习"、RL 里的"policy rollout"是同一个思想——预测一个会变的东西,预测器必须跟着它一起变。speculator 的 target 不是"agent 应该调什么",而是"agent 现在这版会调什么"。这个区分,在所有需要预测动态系统行为的场景里都成立。
局限与未走之路
论文自己列了几个局限:
- 只测了 4B 规模,更大模型的优化动态可能不同
- 只覆盖搜索 QA 和对话式工具调用,代码执行、网页导航、多 agent 场景没测
- 只适用于 read-only 工具
- speculation 长度能不能超过一步? 这篇只预测下一个工具调用,但有些场景下 agent 会连续调几个工具,预测两三步的收益可能更大,但准确率会指数下降。
- speculator 能不能学会"放弃预测"? 当 agent 行为高度不确定时,强行猜一个大概率错的调用,不如主动说"这次不猜"。这需要给 speculator 一个"弃权"选项和对应的 reward 设计。
- 多 agent 场景下的 speculation? 一个 agent 预测另一个 agent 的下一步调用,speculator-agent gap 会以什么形式出现?
论文链接
- arXiv: 2607.25816
- HTML: https://arxiv.org/html/2607.25816v1
- 作者:Jiabao Ji, Yujian Liu, Li An, Rohit Jain, Gungor Polatkan, Siyu Zhu, Shiyu Chang
- 机构:UC Santa Barbara, LinkedIn Inc.
- 代码:暂未开源(论文未提供 GitHub 链接)
*概念谱系第 12 个成员:不优化延迟本身,换到预测层面让延迟消失。分工不一定要分家——参数共享,模式分离,是比"完全分工"和"完全统一"都更精细的设计哲学。*
🌟 智谱 GLM-5 已上线
我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。
🎁 领取 2000万 Tokens