GUI智能体可见性约束评测与优化
最近在折腾 GUI 智能体,说白了就是让 AI 看屏幕截图、自己点按钮、填表单那种东西。我手上有个小工具链,拿它跑一些重复的网页操作。跑着跑着就发现一个问题:明明按钮就在截图里,模型却说"找不到元素";有时候它又对着一个不可见的浮层猛点,点了半天没反应。
这就引出一个词:可见性约束。简单讲,就是智能体只能操作它"看得见"的东西,看不见的、被遮挡的、在视口外的,都不该碰。听着像废话,但真做起来,评测和优化都挺费劲。这篇就聊聊我用 AI 帮我做这块的经历。
一、我具体干了什么
我手上有一批历史操作轨迹,每条轨迹是一串截图加动作。我想知道:模型在这些轨迹里,有多少次动作是针对"实际不可见元素"的。人工看太慢,我就让 AI 帮我写评测脚本,顺带让它帮我分析失败样本。
场景很具体:给定一张截图和模型预测的点击坐标,判断这个坐标落点的元素,在截图里到底可不可见——有没有被别的元素挡住、是不是透明度接近 0、是不是在滚动容器外面。
二、怎么用的
工具用的是 Claude,配一个能读图的本地脚本。分三步走。
第一步,让 AI 帮我把"可见性"拆成可判定的规则。我给的提示词是这样的,可以直接复制:
你是前端测试工程师。我要评测 GUI 智能体点击的元素是否可见。 请把"元素可见"拆成若干条可程序化判定的规则,每条规则给出: 1、判定条件(用 DOM 属性或几何信息描述) 2、需要读取哪些字段 3、容易误判的边界情况 不要写代码,只给规则清单。它返回的清单里,有几条我觉得挺实用:元素自身 display 不为 none、visibility 不为 hidden、opacity 大于 0.1;元素的中心点没有被同层级更高 z-index 的元素覆盖;元素矩形与视口矩形有交集。还有一条边界情况提醒得好:父元素被隐藏时,子元素 computed style 可能仍是 visible,得往上遍历祖先。
第二步,让它生成评测脚本的骨架。提示词:
基于上面的规则,用 Python 写一个函数 is_visible(element, viewport), 入参是 Playwright 的 ElementHandle 和视口尺寸。 要求: 1、逐条实现上面的规则,每条加注释标明对应哪条 2、覆盖边界情况:祖先隐藏、被遮挡、在视口外 3、返回 (bool, reason),reason 说明是哪条规则没过生成的代码我改了两处:遮挡检测原来用的是 elementFromPoint,我换成了对元素中心点取样,因为有些页面有透明遮罩,elementFromPoint 会返回遮罩本身。这个改动是我自己踩坑后加的,AI 一开始没考虑到。
第三步,拿失败样本喂给 AI 做归因。我把"模型说找不到、但脚本判定可见"的样本截图贴进去,提示词:
这是一张网页截图,以及智能体预测要点击的目标描述:"提交按钮"。 智能体报告找不到该元素。请分析可能原因,按可能性排序, 每条给出你在图上观察到的依据。不要下结论说模型不行,只分析页面侧原因。三、实测效果
先说好的。规则拆解那一步省了我不少时间,尤其是"祖先隐藏"这条,我自己大概率会漏。脚本骨架大概七成能直接用,改改就能跑。
再说翻车的。第一版脚本跑出来,误判率不低。有两类问题:
一类是懒加载。截图那一刻元素还没渲染出来,脚本读 DOM 时它已经在了,于是判定"可见",但模型看到的截图里确实没有。这说明评测的时机和截图时机必须对齐,不然规则再细也白搭。这个问题 AI 没帮我发现,是我对着日志一行行看出来的。
另一类是 iframe。跨域 iframe 里的元素,脚本读不到 computed style,直接抛异常。我后来在脚本里加了降级:读不到就标记为"未知",不计入分母。这块 AI 给的代码没做异常兜底,得自己补。
归因那一步,AI 的分析有对有错。它指出"按钮被固定底栏遮挡"的那次是对的,我回头一看截图,确实被 cookie 提示条压住了。但它有两次把"元素在折叠区域下方"说成"元素不存在",这就跑偏了。所以归因结果我只当线索,不当结论。
四、适用边界
说说什么时候别用这套。
页面结构极度动态的,比如每秒都在重排的图表页,DOM 快照和截图对不上,可见性判定基本没意义,别硬套。
纯 canvas 渲染的应用也别用。DOM 里就一个 canvas 节点,所有规则都失效,只能靠图像侧判断,那是另一套活儿。
还有,如果你只是偶尔手动点几下,没必要上这套评测。它是给批量轨迹分析用的,单次操作人工看一眼更快。
最后一句我的判断:AI 在这件事里最值钱的是帮你把模糊概念拆成规则清单,代码和归因都得自己把关。规则对不对,还得靠真实失败样本来验。
如果这篇对你有用,请扫码关注。