返回博客

2026.10.02

直接报坐标对 186 次,先识别再选对 188 次,合起来对 190 次:让本地模型点屏幕,到底该走哪条路?

让一个 35B 本地模型在没有无障碍树的窗口里点按钮。两条路各有长短:直接报坐标快 6 倍但略不准,先识别再选准一点但每步 3 秒。拼成组合路由后 200 次真点击对 190 次,可这多出来的 2 次在统计上什么都证明不了。更值钱的发现是:两条路「意见一致」远没有看起来那么可靠,它们的错误是绑在一起的。三条能自己算的账:两路错误是否独立、混合路由的平均延迟、零错误到底说明多少。

LLMAgent评测方法论

两条路各点 200 次,一条对 186,一条对 188。把它们拼起来,对 190。

看着像一加一大于二。我当时也挺高兴,然后数了一下组合路由到底在哪几题上赢了「先识别再选」:2 题。反过来输的:0 题。2 比 0,抛硬币都能抛出来。

这组实验真正让我改主意的是另一件事:两条路「都同意」的时候,我原本以为可以放心点了,结果它们一起错的次数是按独立估算的 7 倍。危险按钮怎么点,答案就出在这里。

想直接拿判据的看第 4 章,是一个乘法;想知道那 190 为什么不算数,看第 3 章。

1. 问题:窗口里什么都读不到的时候,模型怎么点按钮

让 AI 操作电脑,最舒服的情况是系统给你一棵无障碍树,每个按钮叫什么、在哪,列得清清楚楚。可很多界面没有这东西:游戏、自己画的画布、Proton 跑的 Windows 程序。这时候能拿到的只有一张截图。

我用的是开源的 cua-driver,它最近出了个可选扩展,专门兜这种底:截图丢进去,先用一个 YOLOv8 的图标检测器(OmniParser v2,81MB)框出可点区域,再用一个小 OCR(PP-OCRv5 mobile,检测 4.8MB + 识别 7.8MB)读上面的字,全在 CPU 上跑。这一步没用大模型,只是两个小检测模型。

所以有两条路:

  • 先识别再选:扩展把截图切成一堆候选框,给每个框编个字母画在图上,35B 看图挑一个字母。
  • 直接报坐标:不切了,直接把截图给 35B,问它按钮在哪,让它报一个点。

为了有真值,我在虚拟屏上用 Tk 画了 25 个场景,故意让无障碍树里只剩一个窗口节点。每个场景 8 个目标,一半是文字按钮,一半是没字的图标。任务描述只写功能(「撤销上一步」),不写图标名。点击由程序自己记录点在了哪个控件上,这是判对错的唯一依据。

2. 先翻两次车

第一次:只给文字候选,图标题全军覆没。 最早我只把识别结果的文字和框坐标喂给模型,省一张图。文字按钮 100/100,图标 96 题只对 23。换成专门为这事训练的 4B 模型,也是 23。

翻开识别结果一看就明白了:每个图标的标签都叫 icon-class-0。模型拿到的是十几个同名的框,等于让人闭着眼挑。每个画面 11 到 15 个候选,瞎猜图标大约 9%,23/96 是 24%,比瞎猜强得有限。

把截图连同字母标记一起给模型之后,35B 图标对 88/96,4B 对 78/96。

第二次:让它报像素坐标,0/8。 我在提示里写「返回像素坐标」,8 题全错。它根本没理这句,照样按 Qwen 自己的习惯报 0 到 1000 的相对坐标,我当像素用,点哪儿都不对。改成按 0–1000 解析,同一批题就正常了。

这两次翻车有个共同点:「模型不会认图标」「模型不会定位」这两个结论我都差点写下来,实际上一次是喂给它的东西本来就没信息,一次是两边对坐标的约定不一样。

3. 两条路各自多强,组合之后又多强

在 196 道两边都能做的题上:

方法 对的题数 每步耗时
先识别再选(看图) 188 约 2.5 秒
直接报坐标 179 约 0.37 秒

识别那一步在 CPU 上就要 2 秒左右,900×600 的窗口。直接报坐标 p50 是 365 毫秒,快 6 倍多,代价是少对 9 题。另一轮 200 题的直接报坐标测试里它错了 17 题:6 题说「找不到」,10 题点到别的控件上,1 题点在空白处。点错的 10 题里 7 题是图标、3 题是文字按钮;说找不到的 6 题全是图标,其中 4 题是同一个「回复邮件」。

然后做组合:先让它直接报坐标;同时把报出来的点周围裁一小块、画个红十字,问它「十字底下这个是不是你要的」,读 yes/no 的概率;再单独问一句「这个操作危险吗」(删除、不可撤销、花钱、发给别人)。确认分 ≥ 0.5 且危险分 < 0.5,就直接点;否则退回先识别再选。

阈值在上面那 25 个场景上定好、冻住,然后换一批新随机种子生成的 25 个场景,真点 200 次:

方法 对的次数
组合路由 190
只走先识别再选 188
只走直接报坐标 186

只走单条路那两行,是在同一张截图上离线算的,用场景的控件表做命中判断。我对过一遍:组合路由真点出去的 200 次里,离线判断和真实点击记录的分歧是 0,所以离线这两行可以信。

现在说那个 190。

比两个方法,别比总分,比「一个对一个错」的那些题。组合 vs 先识别再选,这样的题一共 2 道,全是组合赢。组合 vs 直接报坐标,8 比 4。

不偏不倚的情况下,这些题应该五五开。全偏向一边的概率能自己算:

k 道分歧题全偏向同一边,双侧 p = 2 × 0.5^k

2 道:p = 0.5。要 6 道全偏向一边,p 才降到 0.031。8 比 4 那组按二项分布算,双侧 p 约 0.39。

说白了,那个 190 是我看花了眼。组合路由在准确率上和「先识别再选」打平,它买到的是速度。200 次里 139 次走了快路(对 136),61 次退回慢路(对 54),决策时间中位数 0.70 秒,均值 1.37 秒;只走识别那条路每步要 2 秒多。平均延迟也能自己算:

平均延迟 ≈ 走快路的比例 × 快路耗时 + 退回的比例 × 慢路耗时
139/200 × 0.68 + 61/200 × 2.96 ≈ 1.37 秒

实测均值 1.37 秒,对上了。快路 0.68 秒里包含了报坐标、确认、危险三次调用;慢路 2.96 秒是这三次再加识别和挑选。这个式子的用处在于:你想让组合更快,能拧的只有「走快路的比例」,而它被确认门和危险门卡着。61 次退回里,33 次是危险门拦的,22 次是确认分不够,6 次是模型说找不到。

顺便说那个确认门,它挺水的。调阈值的时候,报错的 11 个点里有 7 个照样拿到了 ≥ 0.5 的分;报对的 183 个点里通过 150 个。对的点通过率 82%,错的点通过率 64%,就差这么点。新场景上错点少,8 个里过了 3 个,样本太小看不出更多。它在这里管分流,挡错指望不上。

4. 「两条路都同意」到底有多可靠

危险按钮怎么办?删除、付款这种,点错一次就很难受。我的规则是:直接报的点和识别后选的框落在同一个控件上,才点;不一致就不点,交回给人。

在同一批截图上离线算:36 个危险操作,31 次两路一致,全对;5 次不一致,放弃。对比一下,只走先识别再选会对 34 次、点错 2 次。看着很漂亮,0 错。

但我把 200 题全拿来看了一下:

  • 两路一致的 185 次里,错了 5 次
  • 两路都错的一共 6 次,其中 5 次错在同一个控件上

这个数字该多大,可以先按两路错误互相独立估一下:

两路同时错的期望次数 ≈ 总次数 × 甲的错误率 × 乙的错误率
200 × (14/200) × (12/200) ≈ 0.84 次

实测 6 次,是独立估算的 7 倍。

原因我猜得到个大概。两条路虽然流程不同,做判断的都是同一个 35B。6 次两路都错全是图标题:归档两次,撤销、重做、保存、停止各一次。同一个模型对同一个图标的误解,换条路照样带着。

那危险操作的 0/31 怎么读?用一致时的错误率 5/185 ≈ 2.7% 乘一下,31 次里期望错 0.84 次(又是 0.84,纯属巧合),不到 1 次。观察到 0 次完全在意料之中,它说明不了这道门比 2.7% 更好。零错误能说明多少,有一个现成的粗算法:

n 次全对时,真实错误率的 95% 上界 ≈ 3 / n

3/31 ≈ 9.7%。我能负责任说的只有这句:这道门在危险操作上的错误率,以我的数据,不会高过一成左右。比单走一条路好,离「放心点」还差得远。

如果真想让「两路一致」变成一道硬门,两条路得在会出错的那一层上不一样。比如一条路换一个别家的模型来挑,或者让识别那一路给图标加上文字描述,别全压在同一个 35B 的眼睛上。

5. 拿这个去看别人的 GUI agent 跑分

上面翻过的车,换到别人的数字上同样成立。看到「某模型在界面操作上准确率 X%」,我现在会先问三句:

  1. 候选列表里有什么? 同一个模型,候选只有 icon-class-0 时图标对 23/96,给图之后 88/96。如果对比的两个方法喂进去的信息量不同,这个分数比的是输入,跟模型关系不大。
  2. 总分差几题,分歧题有几道? 190 对 188 这种差距,先数分歧题。少于 6 道还全偏一边,都别急着下结论。
  3. 「通过」是谁说的? 我这次还撞上一个:旧版驱动在 Tk 窗口里打字,返回 ok,其实一个字都没进去;新版老老实实报 background_unavailable。工具说成功和程序真收到,是两件事,判对错要用被操作的那一方的记录。

6. 这组实验的毛病

  • 场景是合成的。 Tk 画布,图标取自两套 Linux 图标主题。真实应用里图标更花、文字更密、还有弹窗和动画,数字只能当相对比较用。
  • 只有一个挑选模型。 第 4 章说两路错误绑在一起,原因我归到「同一个 35B」上,这是推断,没有拿第二个模型做对照验证。
  • 危险门本身没单独检验。 它是一句纯文本的 yes/no,判的是任务描述危不危险。36 个危险操作是它自己标出来的,我没另做一份人工标注去查它漏了几个。
  • 样本小。 新场景 25 个、200 次点击,危险操作 36 次。第 3 章的 p 值和第 4 章的上界都因为这个才这么宽。
  • OCR 只认英文。 识别器是英文模型,我拿它看一台中文界面的掌机截图,关键标签基本认不出来。中文界面上,「先识别再选」这条路会比这里的数字差,差多少没测。
  • 耗时只算了决策。 截图约 21 毫秒,点击后的等待和动画都没算进去。

7. 下次给 agent 接「看图点按钮」,按这个顺序做

  1. 先看识别结果里图标有没有名字。全是同一个类名,就别只给文字候选,把带标记的截图一起给。
  2. 问清模型报坐标的约定。Qwen 系报 0–1000 相对坐标,按像素解析会全错。拿 5 道题先对一遍。
  3. 要速度就上组合路由,用 快路比例 × 快路耗时 + 退回比例 × 慢路耗时 估平均延迟,想提速就去提快路比例。
  4. 比两个方案,只数分歧题。用 2 × 0.5^k 估一下,k 不到 6 就别宣布赢了。
  5. 「两路一致才执行」正式启用之前,先在全量题上算 n × 甲错率 × 乙错率,跟实际两路都错的次数比。实际远大于估算,说明两条路共用了同一个弱点,得换掉其中一路的模型或输入。
  6. 危险操作零出错时,用 3 / n 报上界,别报 0%。
  7. 判对错用被操作程序自己的记录,别用工具的返回值。