hermes-jev-skills 深度评测:823 Star 的 Jev 决策引擎,1020 个测试全绿、6 个基准我复现 5 个,README 主图却仍取自真实环境

hermes-jev-skills 深度评测:823 Star 的 Jev 决策引擎,1020 个测试全绿、6 个基准我复现 5 个,README 主图却仍取自真实环境

做开源项目评测这些年,我发现一个规律:README 里最响的那个数字,往往是最没人回头核的那个。

所以这回我换了个做法。hermes-jev-skills 这个仓库,我不看它说自己多好,我把它自带的基准脚本全部重新跑了一遍——真金白银买了 Jev 的 API,6 个能复现的实验里 5 个逐格对上了。它是 9 月 18 日建仓、8 天 823 Star 的小项目,MIT,作者一个人维护。

但也是它自己承认了一件事,我先摆在这:README 里那张主图,今天仍然取自一台真实机器。 这一点它自己在 commit message 和脚本注释里写得很清楚,只是图一直没换。

它想做的事:让一个便宜模型替 agent 做小决定

你的 agent 每轮都在烧前沿模型的 token 做那些根本不是「思考」的事:这一轮该哪个模型答、377 个 skill 里该加载哪个、检索回来的哪几段值得读、转录要压缩时哪些轮次该留下、下一步该点哪个按钮。

这些是决定,不是文章。hermes-jev-skills 的做法是把它们交给 Jev——TypeSafe 的决策模型,它从不写文本,你给它一个状态和几道类型化问题,它回你一个带校准置信度的答案。十项技能分别是:模型路由、搜索、记忆过滤、handoff 压缩、轮次取舍、skill 选择、消息分诊、邮箱分拣、computer use、browser use。

这十项都以 SKILL.md 形式发布,所以不止能在 Hermes 上跑——Claude Code、Codex,或任何读 skill 文件的宿主都行。

架构上最值得记的一点:它把请求数当成一等成本。路由的三个问题和 skill 选择的 stage 1 问题被合并进同一次请求——Jev 按请求计费而不是按问题计费。这一点后面有实测数字。

实测一:6 个基准实验,5 个逐格复现

先说方法,因为这是这篇的核心。仓库里每个 scorecard 都附了能「reproduce every number here」的脚本,我就照着跑。做法是:在沙箱里 clone、装一个只有 PyYAML 的 venv,然后用真实的 Jev API key 跑它自带的标定脚本。不是读文档,是重算。

先说不动用网络就能验的:

项 结果
主测试套件 tests/ 1020 个测试通过(skipped=1),28.6 秒,全离线
dashboard 测试 71 个测试通过,2.25 秒
jevkit 第三方依赖 零(AST 扫描:纯标准库)

那 1020 个测试用的是内置 fake transport——这一点它自己在测试文件里点明了:如果 fake 发出的分布形状是 API 根本产生不了的,那套件就会变成「绿着测校验器的拒绝路径」。这句话说明作者知道「测试全绿」本身可以骗人。

然后是花钱的那部分。下面每个数字都是我这次实跑的输出,和仓库 scorecard 对照:

实验 我测到的 仓库 scorecard 判定
calibrate_choose.py 31 cases · 0 wrong actions 同 逐格命中
calibrate_choose_match.py --runs 3 floor 0.65:right 23 / stalled 1 / wrong 0 right 22-23 / stalled 1 / wrong 0 逐格命中
calibrate_choose_stakes.py --runs 3 18 个 gate family 全为 69/1-1/21/0 同表 全表命中
calibrate_choose_permutations.py solo Brier 0.032 对照值 0.032 命中
calibrate_skill_stage2.py --runs 2 单轮折算:stage1 only right 10 / spurious 4;stage1+2 right 14 / spurious 0 同口径 命中
calibrate_skillpick_permutations.py 结构一致(10/0/4/0) 11/0/3/0 一行不同 部分

几条值得单独讲的。

那个 trap case 每次都出现在同一位置。31 个用例里有一个是 Cancel this dialog without losing my work,而错误答案是 Save。原文写它的置信度在五轮里是 0.45-0.60,每一轮都落在 0.65 地板之下,所以从没被放过。我这次测到 0.40 和 0.44——机制完全一致。这种「错答案稳定地出现在地板以下」不是运气,是校准。

分离性数字也对上了。「这个屏幕上没有正确答案」这一类,我用第二个问题测出的上界是 0.45(原文 0.43-0.45);而正常可答类的下界是 0.78(原文 0.75-0.80)。

permutation averaging 那条结论被复现了,而且是以它失败的方式。有一种做法是把选项顺序打乱多次、把概率向量平均。我实跑的结果是:在 0.65 地板上,averaging 把那个本该被拒的 trap case 变成了 1 个 wrong action——而单次调用是 0 个。仓库据此没有采纳这个做法。它甚至补了一句更狠的:那个错答案在三次重复里有两次是全体一致答错的,所以「一致性检查」这种安全阀根本拦不住。

唯一没逐格对上的是第 6 个,因为口径不同:那个脚本优先读机器上的 fleet catalog(原文是 459 个 skill 的目录),沙箱里没有,于是回落到仓库自带的 10 个 skill。结构对上了,数字不能逐格比。我把这条明确标出来,不混进「5 个命中」。

实测二:数字能验,但有一处它自己承认的缺口

既然数字这么硬,那篇宣传的缺口在哪?

缺口不在基准,在主图。README 介绍 dashboard 那张截图,caption 写着「profiles, paths and decisions here are a demo home」。但图本身来自一台真实机器。

这是我这次用 git 历史而不是看图确认的:

证据 内容
图的引入 commit 0a15c12(2026-09-19 23:32),此后从未被替换
自陈的那次 commit c5875aa(2026-09-20),标题是 Make the README screenshot reproducible from invented data
该 commit 改了什么 只新增 scripts/demo_home.py、改 caption、改 CHANGELOG——没有动那张图

c5875aa 的 commit message 原话是:「The image was taken from a real machine under a caption calling it demo data, which is how a working fleet’s model strategy got published.」它同期新增的 demo_home.py 注释里写着「that is how the current image ended up showing a real working pool set」。

也就是说:作者发现了这个问题、写了工具来生成假数据、在文档里解释了这件事——然后忘了换图。caption 里那句「the pools are a real working set」直到今天还在。

顺带说,demo_home.py 本身有个小 bug 我顺手复现了:它把 --help 当成输出目录路径(main() 直接取 argv[0],不解析参数),所以 python3 scripts/demo_home.py --help 会在当前目录建出一个名叫 --help/ 的目录树。这不是安全问题,但是这类「脚本没走参数解析」的痕迹。

还有个细节:README 那张表,一半数字买得到一半买不到

这是我觉得最值得记的一条,因为它解释了这个仓库的诚实边界在哪。

README 顶部有一张十项能力的表,每项配一个「Measured」数字。我按「外部人能怎么验」把它们分了三类:

类别 能力 情况
能重跑出数字 choose(两问门、stakes/margin、permutation)、skill 选择 stage 2 evals/choose-match/、evals/skill-pick/、evals/permutation-averaging/ 有 scorecard,我这轮全跑了并对照
有脚本、但要你自己的数据 记忆过滤(evals/context-filter/regret.py)、computer use 的质量(evals/plan-quality/、evals/representative/) 脚本要求「locally held labelled observations」——人类裁决过的真实任务标注,仓库不含语料,也不许用 mock 推断
有 scorecard、但数据明确不公开 handoff 头条那个「58.7% recall alone, 75.0% with one search」 出自 evals/compaction/results/SCORECARD-2026-09-20.md

也就是说:十项能力里,外部人能独立重算出数字的只有三类模型侧决策;涉及真实会话和人工标注的那几项,谁都验不了。这和我上一篇评 laya 是同一件事,只是程度不同——laya 的头条数字连产物文件都没有,这里的第二类至少把脚本和验收口径都写清了(representative/compare.py 甚至会「reject missing arms、duplicates、unknown completion」而不是替你猜测成功),只是语料在你手上。

第三类最值得单说。那个 handoff 数字出自一套实验,输入是 7 个真实工作会话(243 到 614 行、含大量工具调用)加每份 15 道题的考卷。仓库的 README 里写着「Transcripts, exams and capsules stay off this repo」——数据不公开,所以任何人都复现不了,包括买了 key 的我。而这恰好是它全站最响的那个数字。

我特意核对了这段的表意,因为它容易被误读。这张表里 Jev 的表现是分裂的:

对照 结果 说明
Jev 的取舍标记 vs 按 recency 标记 11 胜 4 负 Jev 的判断确实更好
但 Jev 摘出来的 capsule vs plain tail 37.5% vs 48.1% 靠 Jev 写出来的胶囊反而更差

作者自己解释了原因:一个被标为「summarize」的轮次只保留前 400 字符,而七个会话里有五个平均每轮 1,400 到 7,400 字符,任何取舍策略都救不回被裁掉的部分。所以它没有采用 Jev 版 handoff,而是改成整段对话(上限 300,000 字符)+ 1,200 词预算。

这是整个仓库最诚实的一处:它测出自家核心功能没有更好的方案,就没上。表里那些「looked obviously right、measured、not shipped」的两行实验也一样。

还有一处:它把「不省事」也写进文档了

三条我觉得值得抄的工程习惯。

一、fail-open 不是口号,是实测。我在沙箱里故意不给 key 跑:jev doctor 仍然退出码 0;jev mail 把消息标成 unsorted、not_sent_to_jev: 1,而不是崩掉。README 的说法是「No key, timeout, rate limit, malformed reply, low confidence: routing keeps your current model, memory returns the original list, compaction drops nothing」——每一条都有对应的测试。

二、有安全护栏不依赖 Jev 答对。比如「风险词(production / delete / migration / security / payment / legal)永不被路由到最便宜的档」、「大上下文不在会话中途切更便宜的模型」、「转录轮次只在有把握时才丢」。这类护栏的意义是:决策模型错了,损失有上界。

三、隐私边界写得很具体,包括它做不到的部分。README 里有一整节「What leaves your machine」,逐项列出每个功能发出去什么:路由发的是被脱敏的用户这一轮(邮箱、手机、token 遮蔽,上限 2,500 字符),绝不含历史、工具结果、文件、记忆;而且它明说了一个不完美处——默认模式下路由发的是这一轮本身,「the agent has no say in that, because routing happens before it acts」,要彻底不出机器得配 private_profiles。邮箱那条更细:邮件是先解码再筛查(quoted-printable、percent-encoding、HTML entity、base64),因为「a newsletter footer carries your own address percent-encoded in the unsubscribe link」——纯文本脱敏器两个都看不见。

放到同类里看

这一篇要横着比,最自然的坐标是我昨天刚评完的 laya——同样是「决策不用生成」这条路线,同样有 Jev 作为对比对象,同样把「自家模型接近随机」这种难看的数字写在主文档里。

但两者的证据链是镜像的。laya 的 6 张基准表我离线复算逐格命中,而它全站主打的 0.766 准确率在仓库 14 个结果 JSON 里找不到任何支撑文件——那个数字出自一个保存输出数为 0 的 notebook。hermes-jev-skills 反过来:它最响的那批数字(路由、skill 选择、choose 校准)我买了 key 就重跑出来了;它的缺口在一张图,而那张图是它自己公开承认过的。

第二个坐标是评测方法论本身,和我写过的 addyosmani/agent-skills 复测 是同一个问题:自带评测的项目,它的分数该不该信。那次是 25 个技能自评 100% 全绿、我只对上 24%;这次是 6 个基准我复现 5 个,缺口在配图。一个稳定的规律正在形成——看它的评测脚本能不能被你重跑,比看它的分数高低有用得多。

如果你要一句话判断这个项目值不值得看:它的方法论比它的代码更值钱。 把「looked obviously right、measured、not shipped」写进 CHANGELOG、把自己输掉的对照表留在文档里、把「测试全绿可以骗人」写在测试文件顶部——这些习惯,比它那 823 个星更能说明这东西靠不靠得住。

适合谁:跑多 profile agent fleet、模型账单肉疼的团队(路由 + 合并请求直接省钱);要自托管、不想把工具结果发给第三方做决策的场景(它的隐私边界写得很细);任何想学「怎么诚实地做自评基准」的开发者。

不适合谁:只想开箱即用的人——它要 Jev 的 key,而 TypeSafe 目前不接受新注册(README 明写),得走 OpenCode Zen 免费层或 OpenRouter 才能起步。不用 Hermes 的人也能用那十个 SKILL.md,但 dashboard 和插件接缝是给 Hermes 做的。以及:它的 README 主图目前还不可信于「demo」二字——这事作者知道,只是还没换。

结论

工程纪律一流,数字经得起重算,缺口是它自己认下的那张图。

我买的 Jev key 花的钱不到一毛(几个 scorecard 自陈总额 under $0.05),换回来的是 5 个基准的逐格复现。在这个「自评数字满天飞」的赛道里,能做到这一点的项目是少数。

但它提醒了我一件更重要的事:连一个连自己输掉的实验都写进文档的作者,也会忘了换掉一张图。所以我的做法还是那句——别信 README 里最响的数字,去把它的脚本跑一遍。跑得出来,那个数字就是你的;跑不出来,它只是个声明。

关注 AI商业快讯,每天一篇 AI 热点深度解读。

相关阅读:

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

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 的控件结构做的:出发站输入框旁边有一排联想行,用裸 div 加 onclick 实现,没有任何 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 说做完了怎么验」。

Jev Ultrafast 深度评测:7 秒搜完机票的浏览器 Agent,一次决策只发一个请求

Jev Ultrafast 深度评测:7 秒搜完机票的浏览器 Agent,一次决策只发一个请求

7.1 秒,从一句自然语言,到 Google Flights 上列出苏黎世飞伦敦的航班,全程 1 倍速录屏,包含文本生成、模型调用和加载等待。Browser Use 与 TypeSafe 合作的开源 Agent 仓库 jev-ultrafast 靠这个数字刷屏,9 月 16 日创建,三天冲到 8,346 星。

我把它 clone 到本地,跑了官方全部离线测试,审计了它「一次决策要发几次网络请求」,把两个真实页面的动作表重放成请求体算了账,还独立复核了那段 7.1 秒视频和 $0.0039 的账单。

先说清楚一件事:我没有 TypeSafe 的 API key,没能跑通端到端任务。TypeSafe 目前是 waitlist 制,仓库 issue 里有人直接问「怎么拿到 TYPESAFE_API_KEY」。所以下面所有结论来自三处可独立验证的材料:官方 31 个离线测试与源码、官方公布的录制数据、以及我用真实网页 DOM 做的重放。跑不通的部分我会标出来。

7.1 秒是真的,但计时器是后开的

官方性能文档写得很直白:计时起点是「初始首页观察之后的第一次预测」,终点是「被接受的 DONE 选择」。浏览器启动、初始导航、以及任务结束后的独立结果校验,全部在计时之外。

这不是注水,是常规口径,但读者该知道这 7.1 秒买的是什么:页面已经打开、正文已经渲染完之后,Agent 从「看第一眼」到「确认结果正确」的耗时。

视频我也复核了。ffprobe 读出来 7.566 秒、227 帧、恒定 30fps;7.566 秒 = 公布的 7.073 秒运行 + 0.5 秒结尾停留,时间轴对得上。把浏览器画面区域单独裁出来逐帧比对,227 帧里有 224 帧互不相同——它不是靠重复帧把时长凑出来的。

有一处对不上:测量文件里写 video/source_frames = 187,而视频实际是 227 帧。这更可能是渲染脚本重跑之后元数据没同步,但可以确定的是,视频右下角那个跳动的秒表是渲染时按帧序号算出来的,不是硬件计时器。所以「1 倍速」这件事,外部无法只靠看视频证明,它依赖录屏时间戳被忠实映射。

还有一点值得给作者加分:官方在性能文档里保留了匹配对照的完整数据,三对样本,中位耗时 9.450 秒降到 7.092 秒,然后自己写了一句「三对样本太少,做不了强统计声明(双尾符号检验 p = 0.25)」。同一份文档里还留着自己失败的开发尝试——有一次跑到 8.697 秒更快,但独立校验没通过,被毙了。愿意把推翻自己的数据留在仓库里,这在爆款项目里不多见。

它把「决策」从字符串生成里抠了出来

jev-ultrafast 不是一个模型,是 Browser Use 给 TypeSafe 的 Jev 模型写的一层浏览器运行时。

Jev 是 TypeSafe 9 月 15 日发布的 System One 模型。它的输出不是文本,而是类型安全的决策值加校准概率——你事先定义好问题和选项,它一次查询并行吐出所有选项的概率,不做逐 token 自回归。官方定价 $0.042 每百万输入 token,输出 token 免费,端到端 70 到 500 毫秒。名字取自杰文斯(William Stanley Jevons),那位提出「效率提升反而推高总消耗」的经济学家。

这套东西落到浏览器里,做法是这样的:每次观察页面,运行时生成一张带编号的元素表,每个可见控件占一个索引(同一个 DOM 节点即使既能点又能填,也只占一个索引)。然后把整个目标、页面正文、元素表、最近十步动作打包,一次请求里同时问四个问题:下一步做哪个操作、如果点那么点哪个、如果填那么填哪个、如果下拉那么选哪项。

只有被选中的那个操作对应的目标头会被读取,其余的即使模型答了也不执行。这样一来,过去「先问该做什么,再问点哪里」的两次往返被压成一次,同时保证了不会拿一个 TYPE_TEXT 的目标去执行点击。

整个 Agent 主循环 agent.py 是 174 行。快照逻辑 snapshot.js 107 行。

我把它的每一步都拆开算了

离线部分全部通过。官方测试 31 个断言 1.04 秒跑完,一个不挂;ruff 静态检查干净;两个前端脚本 node --check 通过;uv build 能正常打出 wheel。代码总量 1,681 行 Python(其中测试 320 行),对一个需要驱动真实浏览器的项目来说小得反常。

一次决策确实只有一次网络往返。 我替换掉 HTTP 客户端做拦截,捕获到的请求体里同时挂着四个问题头:operation、click_target、type_text_target、select_target。返回的答案里,目标头带着完整的概率分布,但代码只取与所选操作匹配的那一个。README 里「两个决策,一次网络往返」的说法成立。

真实页面的账单我也算了。我用浏览器在目标站点上原样跑了一遍官方的快照脚本,拿到真实的动作表,再喂回官方 Python 的 action_space() 和 choose() 生成请求体:

页面(1120×780 视口) 可点元素 请求体 粗估 token
Google Flights 首页 21 个元素 / 24 个动作候选 9,935 字节 2,483
GitHub issue 列表页 57 个元素 / 60 个动作候选 17,395 字节 4,348

拿这个数字去对官方录制:那次跑动用 17 次请求消耗 90,558 输入 token,均摊每次 5,327 token。我的重放是 2,483 到 4,348,量级一致——说明 90,558 这个统计可信,而且后续步骤因为要带上历史动作和更满的结果页,单次开销还会涨。

账单也算得回来。90,558 × $0.042/百万 = $0.0038,官方宣传的任务成本是 $0.0039,差 2.6%,基本就是四舍五入。输出 token 不收费。折算下来一次跨境航班搜索不到 3 分钱人民币,而且这个数字里还不含浏览器和文本助手的开销(那部分官方实测是 $0.00006272)。Doom 那个演示跑 10 次决策每秒,作者说约合 $7 每小时。

安全边界经得起打。README 声明「模型输出永远不会变成选择器、坐标、shell 命令或可执行 JavaScript」。我构造了六种畸形响应去打它:把 choice 换成 document.querySelector('#x')、换成一段 script 标签、概率之和只有 0.5、概率里塞 NaN、选了个不是最大概率的选项、概率集合和候选对不上。六种全部被拦,一行动作都不会执行。

顺带发现一个代码里没写的原因:快照最多保留 250 个动作候选,而 TypeSafe 官方博客明确说 Jev 的选项基数上限是 255。250 这个数字大概不是随手取的。

视频、代理,和两个 AI 编出来的 issue

代理这一条,中文用户几乎必踩。issue #16 报告:httpx 在模块导入时就建了连接池且不处理代理,只要环境变量里有 ALL_PROXY=socks5://,程序在 import 阶段直接崩,报 ImportError: Using SOCKS proxy, but the 'socksio' package is not installed。我在沙盒里原样复现了。Clash、v2ray、xray 的默认配置都会导出这个变量。

代码默认值里还埋了一个坑。文本助手的 base URL 在代码里的默认值是 https://api.deepseek.com/v1,而 .env.example 和 README 写的是 OpenRouter。也就是说,一个人照着 README 只填了 TEXT_MODEL_API_KEY 就运行,他填进去的 OpenRouter 密钥连同页面文本会被发到 DeepSeek 的接口上。这条是 issue #36,我核对源码 164 行属实。

生态侧的数据就不那么好看了。仓库三天收了 40 个 PR,39 个没合并,唯一合掉的是作者自己改 README 的一条。16 个 issue 全部处于 open,一个都没关闭。三位贡献者里只有一位(作者本人),3 个 commit。

更麻烦的是信噪比。这里面混着明显是 AI 生成的幻觉报告,其中一条标着 HIGH:声称 README 的 clone 地址指向了错误的仓库——我 clone 过了,地址是对的;另一条说 agent.py 被压缩成了一行行的超长代码、违反项目自己的 120 字符行宽——实际文件 174 行、格式正常、ruff 检查干净。两条出自同一个账号,前后相隔 7 分钟。

也有真材实料的报告。issue #23 里,一位用户拿中国铁路 12306 的购票页去跑,结果是:60 个动作全部是往同一个输入框里打字,跑了 77 秒,120 次决策预算耗尽,出发站和到达站最后都被填成了「北京」。原因是快照只收集原生控件(a[href]、button、input 等)和固定清单里的 ARIA 角色,而 12306 的站点联想行是用裸 li/div 自己绑点击事件做的,模型根本看不见,只能反复重试它唯一看得见的那个框。

这暴露了动态索引动作空间的真实边界:它不是「看得懂网页」,而是「只看得见被预先定义好的那一类控件」。Google Flights 能用,是因为 Google 老老实实写 ARIA 标注。

值得看,但现在别急着拿它当脚手架

把结论分三层说。

方法层面,这个 demo 真的有价值。它证明了一件事:把「决策」从 LLM 的字符串生成里抠出来,换成一次并行的概率输出,是 Agent 提速最直接的一刀——不需要换更强的模型,不需要减少步骤,只是把「生成一段话再解析」改成「直接给答案」。这和 Pi Agent 砍工具数、unlazy 给完成状态装闸门是同一个方向:约束模型能做什么,比让它更聪明更有效。

工程层面,代码值得读。1,681 行、31 个测试、零运行时依赖、主循环 174 行,还能把「模型输出不变成选择器」这条安全不变量守住。想自己写浏览器 Agent 的人,这个仓库一小时能读完,比啃框架文档快得多。

产品层面,别急着接。三点:TypeSafe 还是 waitlist,拿不到 key 的话开源代码只能跑离线测试;中文站点上表现堪忧,12306 那种非标准控件直接崩;官方自己承认这不是基准测试,只是「一个任务在一个已有浏览器配置上跑三次」,而且性能对照的 p 值只有 0.25。

一句话:7.1 秒是真的,$0.0039 也是真的,但这两个数字测量的是「决策够快」,不是「网页够懂」。

想继续往下看,可以读这三篇:Pi Agent 实测 讲的是同一件事的另一个解法——默认只给模型四个工具;unlazy 深度评测 解决的是「Agent 说做完了怎么验」;OpenRouter 免费大模型全量拆解 里则有 Jev 上架 OpenRouter 之后的路由逻辑。