Jev Ultrafast 端到端实测:三种静默假成功,与一个 HTML 属性的分界线

上篇结尾我留了一句遗憾:没有 TypeSafe 的 API key,端到端跑不通,只能做离线审计。现在 key 有了,我在沙盒里装起 Chromium 136,让 browser-harness 接上 CDP 调试端口,把这个 Agent 真跑了起来。

六个场景跑完,结论比上篇更尖锐:模型是好的,眼睛是瞎的

而且瞎得很有讲究——有一个场景,我只往 HTML 里加了一个属性,任务就从「静默失败」变成「顺利完成」。

模型这一侧,我几乎挑不出毛病

先把 TypeSafe 的 API 单独拉出来测。观测点在中国大陆(沙盒出口是广州联通),到服务端的网络单程约 120 毫秒。

延迟。同一个请求连打 30 次,连接复用前提下:最小 334 毫秒、中位 382 毫秒、p90 422 毫秒、最大 999 毫秒。拆开网络路径看——DNS 22 到 43 毫秒,TCP 握手 237 到 375 毫秒,TLS 完成 496 到 738 毫秒,首字节 825 到 1215 毫秒。官方说的「端到端 70 到 500 毫秒」是在美国西岸笔记本上测的,从国内发出去,光网络往返就吃掉两百多毫秒。扣掉这部分,服务端处理大约在一百七十毫秒上下,和官方录制里那个「中位决策延迟 178 毫秒」对得上。

加问题不增延迟,这条是真的。官方文档原话是「Adding questions barely changes the response time」。我直接测:1 个问题 373 毫秒,5 个 393 毫秒,20 个 426 毫秒,60 个 426 毫秒。输入 token 从 305 涨到 1299,翻了 4.3 倍,延迟只涨 14%。这是它并行采样架构的真正红利,也是 jev-ultrafast 敢在一次请求里同时问四个问题(操作、点击目标、填文本目标、下拉目标)的底气。

255 这个数字是硬边界。官方博客提到 Jev 的选项基数上限是 255。我逐个试:250 个选项正常返回,255 个正常返回,256 个直接 HTTP 400,错误信息是「Too many choices. Must have at most 255 choices.」而 jev-ultrafast 的快照最多保留 250 个动作候选——这个数字不是随手取的,它是在 255 上留了安全余量。

校准稳定得反常。同一个判断连问 15 次,15 次全选同一个选项,被选项概率落在 0.78 到 0.83 之间,标准差 0.014,置信度 0.67 到 0.74。这个抖动幅度比大多数 LLM 的温度采样小得多。

真实页面上的决策质量也对。我把上篇从浏览器里抓下来的 Google Flights 真实元素表(21 个元素)连同完整任务喂进去,连跑 10 次:10 次全部选「Change ticket type. Round trip」——任务要求单程票,而页面默认往返,改票种确实是正确的第一步。置信度稳定在 0.70 到 0.77。

顺便修正上篇一个数字。当时我用「字节数 ÷ 4」粗估 token,现在有真值了:Google Flights 首页的真实请求体是 3,422 输入 token(我粗估 2,469,低估 39%),GitHub issue 列表是 6,729(粗估 4,316,低估 56%)。官方录制里那个「17 次请求 90,558 输入 token」,统计口径是可信的。

端到端:六个场景,三类失败

关键前提:Google Flights 在中国大陆访问不了,所以我复现不了那 7.1 秒。我换了能跑的目标,并自己写了两个本地页面做对照。

需要说明一件事:jev-ultrafast 的 TYPE_TEXT 要另外配一个 OpenAI 兼容的文本模型(官方示例用 OpenRouter 的 mercury)。我没有第二个 key,所以自己起了一个本地桩服务顶替,按字段语义返回站名。下面凡是涉及打字的场景,文本是本地桩给的,不是真模型写的——这一点先讲清楚。

场景 结果 步数 DONE 置信度 成本
百度首页,点「新闻」进新闻首页 假成功 3/3 4 / 3 / 4 0.21 / 0.27 / 0.25 $0.0009–0.0011
百度新闻页,打开一条新闻 正确 blocked 3 $0.0010
本地页 A:规范 button、同标签跳转,三步下单 真成功 4/4 3 0.97 / 0.98 $0.00019
本地页 B:联想行用裸 div + onclick 假成功 3/3 2 0.85 / 0.86 $0.00022
本地页 C:B 的同一个页面,联想行加一个属性 真成功 3/3 3 0.92 / 0.93 $0.00030
12306 购票页,填两个站名 抛异常中断 1

三类失败,逐个说。

第一类:点得动,但点在了看不见的新标签页上。百度首页顶部那个「新闻」是个 target="_blank" 链接。Agent 点它——点击执行成功了,浏览器里也确实多了一个 news.baidu.com 的标签页——但它自己那个标签页纹丝不动,于是它开始 WAIT,等了三次之后,以 0.21 到 0.27 的置信度宣布任务完成。最终 URL 还是 https://www.baidu.com/。三次复跑,三次同样结果。

顺带一个副作用:每跑一次就在浏览器里留下一个没人回收的僵尸标签页。我三次复跑之后,浏览器里静静躺着五个 news.baidu.com

换上百度新闻页,链接同样是新标签打开,但这次 Agent 选择了连续重试点击——而连续三次「没变化的非等待动作」会触发它自己的停滞检测,于是正确报了 blocked。同一个根因,两种结局,取决于模型当时挑的是 WAIT 还是 CLICK。这个随机性本身就是问题。

第二类:看不见的选项,它就当不存在。本地页 B 是我照 12306 的控件结构做的:出发站输入框旁边有一排联想行,用裸 divonclick 实现,没有任何 ARIA 语义。Agent 的表现是——打字填「北京南」(成功)、点「显示建议」(成功)、然后直接 DONE,置信度 0.85。页面下方的「出发站:未选择」它压根没碰。

因为那三行联想行不在元素表里。它的眼睛是一张最多 250 项的清单,清单上没有的东西,它不知道自己没看见。

这正是仓库 issue #23 里那位用户拿 12306 真实页面跑出来的现象——60 个动作全部往同一个框里打字、77 秒、两个车站最后都填成「北京」。我用一个 20 行的本地页面,把那个机制精确复现了。

第三类:缺依赖时直接崩,不是降级。12306 真实页面能正常加载,快照抓到 54 个元素。但 Agent 第一步就去填顶部搜索框——那个输入框没有可访问名称,快照给它的 label 退化成 "textbox",只有 placeholder 简拼/全拼/汉字 留在 value 里。文本助手拿到 {"label": "textbox"} 这种上下文,当然判断不出该填什么,返回了 null,而 model.py 对 null 的处理是直接抛 ValueError 终止整个运行。这是一次都没走完就结束的第六个场景。

一个 HTML 属性的分界线

上面 B 和 C 两个本地页面,除了联想行是否带 role="option",其余 HTML 完全一样

  • B(裸 div):2 步,假成功,DONE 置信度 0.85–0.86,成本 $0.00022
  • C(加了 role):3 步,真成功,DONE 置信度 0.92–0.93,成本 $0.00030

多出来的那一步就是「点击北京南」。加一个属性,多花 $0.00008,结果从「它以为完成了」变成「真的完成了」。

这不是 jev-ultrafast 独有的毛病,任何靠元素表工作的浏览器 Agent 都会被这个问题绊住。区别在于它失败的方式:不是报错,不是卡住,而是干净利落地告诉你 done。

置信度不能当成功闸门

看到百度那三次 0.21 到 0.27 的 DONE 置信度,我一度觉得找到了通用解法:拿置信度当闸门,低于 0.8 就拒绝接受 DONE。本地成功案例都在 0.92 以上,看起来分得很干净。

然后本地页 B 打脸了:假成功,置信度 0.85。真成功的 C 是 0.92。0.85 和 0.92 之间画不出一条可靠的线,样本量也不支持我这么画。

背后的道理其实很朴素:Jev 的概率是诚实的,但它只能对「看得见的东西」打包票。看不见的选项不在它的视野里,它不知道自己没看见什么,于是给出的高置信度在语义上完全成立——在它能看到的那张表上,任务确实做完了。

所以真正能兜底的还是那老三样:独立的结果校验、任务级的断言、以及别把「模型说完成」当成完成。仓库自己也写了「DONE requires visible evidence」,还写了「A DONE choice still requires independent outcome verification」——问题是示例代码 examples/run.py 里没有任何校验,直接打印最终状态就退出了。

值得用吗

分三层说。

Jev 这个模型本身,值。$0.042 每百万输入 token、输出免费、同一判断连问 15 次结果逐位一致、255 个选项也能精确挑一个、加 60 个问题只慢 14%。我在这次全部测试里花的钱加起来不到一毛钱人民币,其中单个任务最便宜的只花了 $0.00019。要是有「分类、路由、打分、护栏」这类形状的任务,这是目前成本最低的选择之一。

jev-ultrafast 这个运行时,现在的状态是「能演示、不能托付」。它在规范控件加同标签导航的页面上确实快——三步任务 2.6 秒、$0.00019、动作序列和 token 数每次都逐位一致。但它对网页的可见性依赖得太死:target="_blank"、裸 div 造的控件、没有可访问名称的输入框,任意一个都会让它要么假装成功,要么直接崩。

如果真要接,先做三件事。一是给它一套你自己的结果校验,别信它报的 done;二是拿你真实要跑的站点先压一遍,特别是所有会开新标签的链接;三是确认那个 250 项上限够不够用——真实复杂页面的元素表随时会顶到天花板。

一句话总结:这 7 秒的演示是真的,$0.0039 的账单也是真的,但它省下的是「决策时间」,不是「网页理解」。真正卡住浏览器的从来不是模型不够快,是它只看得到被预先定义好的那一类控件。

想接着看,可以读这三篇:上篇《Jev Ultrafast 深度评测》 讲的是它的架构和 90,558 token 那笔账怎么算;Pi Agent 实测 讲的是同一件事的另一个方向——把工具数压到四个;unlazy 深度评测 解决的正是「Agent 说做完了怎么验」。

发表评论