自回归解码站在关键路径上:GUI 智能体的 650ms 截止时间问题
同一个冻结模型,只把动作生成挪出关键路径,650ms 截止窗口下成功率 0.50→0.79。瓶颈不在推理能力,在自回归解码的 411ms。
屏幕上弹出一个框,问你要按 A、B 还是 C。650 毫秒后它自己消失。
一个能看懂截图、能操作键盘的多模态智能体,面对这个任务失败了一半。不是因为它看不懂——它读对了那个框,也选对了要按的键。它输在说出答案要花时间。等它把 {"action": "press", "key": "B"} 这段文字逐 token 生成完,框已经没了。
答案对,动作晚。这类失败在成绩单上和”不会做”长得一模一样。
一篇今天挂出来的论文把这件事量化了,并且给出了一个不需要重新训练模型的解法:把生成搬到事件发生之前。同一个冻结模型,成功率从 0.50 到 0.79。
先说结论
- 瓶颈不是模型不够聪明,是自回归解码站在了决策的关键路径上。同一个冻结模型,什么都不改,只把”生成动作文字”这一步挪到事件发生之前,650 ms 窗口下成功率从 0.50 到 0.79(配对 McNemar,)。
- 两个直觉上的解法都拿到 0/42。盲发预测动作(open-loop)0 分;先预测再重新规划(predict-and-replan)也是 0 分——因为它在执行时还在解码。
- 做法:空闲时预先编译一棵”条件动作树”。每个分支带一个可观测的守卫条件、一个已授权的动作、一个自己的截止时间。事件来了只做一次极短的分类:匹配哪个分支,立刻执行,不生成任何新文字。
- 树要多大有公式:按模型自己的解码延迟来定。三种可能结果就配 3 个分支()——42 对全胜,19/0 discordant,。分支数少于结果数时不是变便宜了(关键路径成本差不到 15%),而是规划器生成的树 JSON 直接不合法。
- 作者的预注册探针推翻了他们自己的假设。他们押注瓶颈在观察器延迟,结果证据指向分支路由准确率。
- 不是万灵药:换到外部基准 DynaCU-Bench 上,和普通反应式智能体打成平手(6/39 对 7/39,)。赢的四个任务全是”选项能提前列举”的,输的五个全是”必须临场取值”的。
先把失败拆开
论文给成功下了一个定义,这个定义是整篇文章的支点:
平常的基准只管前一半。把后一半写进去,一类平常看不见的失败就浮出来了:动作正确但迟到。
时间线摊开看,普通反应式智能体(论文里的 R0)在事件发生后要走完这些:
事件发生
│
├─ 截图 ~33 ms(30 FPS 下最多一帧)
├─ 图像送进模型
├─ 逐 token 生成动作 JSON ← 这里是大头,411 ms / 48 tokens
├─ 解析
└─ 执行按键
合计 ~437 ms 往返
窗口 650 ms → 勉强够
窗口 600 ms → 一半的时候不够
关键在于中间那一段:生成 48 个 token 要 411 毫秒(R0 实测 p50)。这个数不取决于任务多难,只取决于要吐多少字。它是一笔固定开销,而且落在最不能承受开销的位置上。
两个朴素猜测,各撞一次墙
猜测一:提前把动作发出去。既然生成慢,那就在事件发生前就预测好要按什么,到时候直接发。
0/42。原因很直白:事件还没发生,要按哪个键的信息还不存在——那个键由一个隐藏的随机种子决定,屏幕上事先没有任何线索。盲猜三分之一的键,还得撞上时间窗,实测得零。
猜测二:提前预测,事件来了再重新规划一下确认。这个听起来稳妥多了:先有个预案,真到了再看一眼实际情况,纠正预案。
也是 0/42。“再看一眼纠正”这个动作本身就是一次解码。关键路径上的 411 毫秒一点没省。只要执行阶段还要生成文字,前面做多少准备都不改变结论。
两次撞墙的位置正好圈出了真正的约束:不是”要不要提前想”,而是事件之后还剩多少必须在线生成的 token。这个数必须压到接近零,同时又不能盲发。
机制:把生成搬到事件之前,只留一次分类
AAPT(Adaptive Anticipatory Policy Trees,自适应预期策略树)把工作切成两段,用屏幕空闲的时候做重活。
慢路径(空闲时,不计时):同一个冻结模型看着当前屏幕,输出一棵符合固定 JSON schema 的策略树。每个节点带四样东西:
guard:一个可观测的条件(比如”框里显示的字母是 B”)- 一个已预授权的原子动作(按 B)
deadline_ms:这个分支自己的截止时间- 规划器写下的该结果的先验概率
快路径(事件时,计时):
30 FPS 抓帧
│
├─ 像素差分「变化门」:屏幕没变的帧直接丢掉
│ (另有强制探针帧周期性放行,防止静止画面永久
│ 堵住观察器)
│
├─ 变化帧 + 当前可用的守卫条件 → 观察器
│ 低温、固定 schema、只输出
│ {branch_id, confidence, reason}
│ 实测 273 ms / 30 tokens(对比 R0 的 411 ms / 48)
│
├─ 三道抑制检查:
│ · branch_id 当前是否可用
│ · 规划器给这个分支的先验是否过阈值 τ_m
│ · 决策年龄是否已超过该分支 deadline
│
└─ 动作在预授权白名单内 → 执行
不匹配 / 有歧义 / 超时 / 校验失败 → 回落到重新规划
事件之后唯一的在线生成,是那个只输出一个 JSON 对象的观察器调用。它不产生自由形式的动作,只做一次”这是哪个分支”的分类。这就是 411 ms 变 273 ms 的来源——但真正的收益不在这 138 毫秒,而在于动作文本早就写好了,选中即可执行。
一个容易忽略的设计:超过截止时间的路由结果被抑制,而不是执行。宁可错过也不乱按。这换来了论文里那个很漂亮的数字——incorrect-action 全程为 0。它没有把”迟到”变成”按错”。
为什么这样设计:树该多大不是调出来的
预先编译听起来就该”越大越好”——多准备几个分支,覆盖面更广。论文这里给了一个反直觉的结论。
树的规模按 定: 是分支数(宽度), 是深度。在 600 ms 主窗口上扫这个网格,结果是一个膝点而不是一条上升曲线:
- (三个分支、深度 1,正好覆盖三种可能结果):42 对全部成功,对反应式基线 19/0 discordant,
- (更深):没有任何额外收益。即使允许更深,规划器实际构造出来的还是那个四节点的深度 1 策略
- (分支比结果少):最差
为什么差,是这段里最有信息量的部分。它不是因为便宜——欠配置的格子关键路径成本差异不到 15%,省不下什么。它差是因为规划器生成的树 JSON 合法率掉到 0.85 的闸门以下。让模型在一棵装不下所有结果的树里安排三种可能,它开始产出不合法的结构。
于是尺寸规则很干脆:分支数对齐结果集大小。作者用一个五结果的复现验证了这条规则会随结果数平移,并且报告了一个更值得警惕的现象——budget 设错时会产生错误动作,不只是错过。
深度不给收益这件事也有解释。深度只在”要连续做多步”时有用,而这个基准里每次事件对应一个原子动作。预先编译的收益来自宽度(覆盖所有可能),不来自深度(预演长序列)。
作者押错了,而且把这件事写出来了
论文最值得学的一段和 GUI 没关系。
成功需要四个条件同时成立:
作者预注册了一个假设:瓶颈在最后一项,观察器延迟。然后他们跑了一个 oracle 探针——把路由换成 ground truth,其余一切冻结不动,看成绩变不变。
在 UI-Venus-1.5-30B-A3B 上,这个模型很快、生成的 JSON 也合法,但路由准确率只有 0.39。它原本的配对结果是打平()。换上真实路由之后,打平翻成了22/42 对 12/42 的胜势()——与作者自己写下的预测相反。
他们把这个反例留在了论文里,还给结论加了限定:那次探针跑出来的树覆盖率比原来高(recall 0.59 对 0.22),所以许可的说法是条件性的——当树覆盖率高过反应式基线时,路由质量单独就能把”平”变成”赢”。
这种”预注册 → 被自己的数据推翻 → 报告推翻并收窄结论”的做法,在工程类论文里少见。它的实用价值是:如果你只在自己相信的那个瓶颈上做消融,你会找到支持它的证据。oracle 探针(把某个环节换成完美版本,看上限)是少数几种能让你发现押错了的手段。
边界:它在哪里赢不了
这篇论文的诚实之处在于它自己报了一次平局。
搬到外部基准 DynaCU-Bench 的 39 个确定性、有截止时间的任务上,预注册的三数表决跑出来是打平:反应式 7/39,AAPT 6/39,discordant 5/4,。
但赢的和输的按任务结构干净地分开了:
- AAPT 独赢的 4 个:全是”仪表盘截止时间”类——回应可以在编译期列举。预先武装好的动作在门控帧之后 140–215 ms 就发出去了,而反应式的约 437 ms 往返错过了窗口。
- 反应式独赢的 5 个:全部需要多步排序、临场才揭晓的数值,或者编译期拿不到的位置定位。
结论因此是互补而不是替代:预计算只在结果和动作都能提前列举时才转移它的延迟优势。
另外几条要记住的条件:
它需要空闲期。慢路径要在屏幕安静的时候跑(planner 实测 p50 1.81 s)。屏幕持续变化、没有喘息的场景里,这棵树没时间编译。
基准是自己造的。作者说明了为什么:OSWorld、WebArena、Mind2Web、AndroidWorld 都不提供毫秒级控制,隔离不出对截止时间敏感的动作选择。他们造了 key_prompt,可调 250–2000 ms 窗口、服务端确定性判分、事件前信息严格受控。这个理由站得住,但自造基准终究是自造基准。
Oracle 上限那一栏没过多重比较校正。O1(完美观察器)在两个窗口都高于 T2,但 Holm–Bonferroni 之后不显著,所以论文把它写成”估计的 headroom”而非确认的效应。
六个模型里只有两个通过全部三道能力闸门。其余四个各卡在不同的一道上。这套方法对模型有前提要求:亚秒级观察器、能生成合法树、路由准得动——不是任何模型接上就能用。
拿得走的三件事
回到开头那个 650 毫秒的框。真正的教训不是”用策略树”,而是三个更一般的判断:
一,把截止时间写进成功的定义。只要评分只看动作对不对,“对但迟到”这类失败就永远不出现在报表上,你也永远不会去修它。这一步不花钱,只是改判分函数。
二,先量在线生成的 token 数,再谈优化。411 ms / 48 tokens 这个数不取决于任务难度,只取决于要吐多少字。任何有时限的回路,第一件事是数清事件之后必须在线生成多少 token——这个数是延迟的下界,压不下去就别谈别的。压它的办法是把自由生成换成固定 schema 的分类(这里是 48 → 30 tokens),或者干脆搬到事件之前。
三,先问结果能不能提前列举。这是判断该用预计算还是老老实实反应的唯一分界线,DynaCU-Bench 上那 4 比 5 的分裂就是它。能列举 → 空闲时编译好,事件时只选。不能列举 → 预计算不但不帮忙,还会因为 budget 设错而产生错误动作。