我们如何为 AI 网页智能体构建可扩展的评估基础设施
深入了解我们高度可扩展的 LLM-as-a-judge 评估平台,该平台解决了网页智能体的方差问题。
评估一个浏览真实网络的智能体,与在文本基准上评估 LLM 并不相同。网络是混乱的、非确定性的,并且不断变化。
一个加载慢 100 毫秒的弹窗就可能打乱整个智能体轨迹。一个随机的 A/B 测试就可能破坏选择器。因此,智能体轨迹本质上是混乱的。
我们的评估任务来源于数百万条 LLM 标注的用户片段,而非合成网站,因为合成环境完全无法捕捉真实网络构建方式中离奇的现实、复杂性和丑陋。
Task Selection Pipeline:图片未能保存,请查看原文。
但处理真实网站意味着要应对方差。单次运行的确定性测试在这里毫无用处。
令人担忧的是,许多 AI 智能体基准测试不包含误差棒或方差估计;来自实验粒子物理背景的我们,这种统计严谨性的缺失令人警醒。
你需要真正的统计严谨性。这意味着多次运行完全相同的任务,调整大量智能体设置,确保这些设置的完全可复现性,并使用统计自助法汇总结果。
要大规模地做到这一点,你需要大规模并行化。以下深入介绍了我们如何构建一个高度并行、完全可观测且完全由智能体驱动的评估循环。
构建评估引擎
5 分钟内完成 100 个任务
我们试用了几款第三方评估工具,最终将它们弃用,转而自研引擎。
通过在 GitHub Actions 上使用 Blacksmith 运行器,我们实现了惊人的扩展能力,在不到 5 分钟的端到端时间内并行运行 100 个复杂的网络任务。
关键在于,我们将 LLM 评审直接内置于智能体代码本身,在智能体返回 done 之后运行。这意味着评审器还可以在常规使用期间充当智能体的实时验证层。
Evaluation Engine Architecture:图片未能保存,请查看原文。
大规模可观测性
仅仅运行得快是不够的;你需要绝对的可观测性。我们通过 Laminar 将每一个 token、提示词、计时指标和成本直接流式传输到 ClickHouse,后者高效处理海量的 LLM 消息。
我们甚至记录每个浏览器会话并将帧保存到 Laminar。(对于实时 UI 状态和制作仪表板,我们依靠 Convex 让工程师与活跃的运行和结果保持同步。)
这种架构创建了一个庞大的、可查询的智能体行为数据集,我们的团队——以及我们的智能体——都可以利用它。
LLM 评审与聚类的失败
为什么确定性检查会失败
当任务涉及导航真实网站时(例如,“从 JFK 找到飞往 LHR 的最便宜航班并创建一个包含选项的文档”),没有简单的 assert(success == true)。
这需要复杂的推理和判断,但人类评审无法扩展。相反,我们需要一个智能体评审。
LLM 评审
我们迭代了许多评审框架,并用 200 条精心手工标注的轨迹对其进行校准。gemini-2.5-flash 驱动着我们最终的评审器,达到了与人类标注 87% 的一致率。
关键在于,评审器在出错时是无偏的,因此通过多次运行任务和评审,可以减轻这种轻微的不一致性。
我们发现,简单的提示词和绝对的 True/False 判定效果最好。复杂的评分标准会导致评审犹豫不决。
为了强制产生严格、可执行的输出,我们要求 LLM 评审员必须严格按以下 JSON 结构作答。如果某个任务确实损坏或无法完成,评审员可以依据我们明确的说明将其标记为不可能:
{
"reasoning": "Breakdown of user task into key points.
Detailed analysis covering: what went well,
what didn't work, trajectory quality assessment,
tool usage evaluation, output quality review,
and overall user satisfaction prediction.",
"verdict": "<boolean>",
"failure_reason": "Max 5 sentences explanation of why
the task was not completed successfully in case
of failure. If verdict is true, use empty string.",
"impossible_task": "<boolean>",
"reached_captcha": "<boolean>"
}聚类陷阱
最初,我们尝试对失败的轨迹进行嵌入和聚类,以找出共性问题。结果完全失败——这些聚类并不能代表可执行的产品改进。
转变:我们改为让 Claude Code 从评审员处提取原始的 failure_reason 字符串。
Claude 阅读数百条这样的原始原因,提出具体类别,剔除小类别,并对大类别进行迭代子分类,直到我们得到高度具体、可执行的错误分类。我们每天对这些失败模式进行抽样和分类,以寻找容易解决的问题。
智能体自我改进循环
Agentic Self-Improvement Loop:图片未能保存,请查看原文。
Slack 作为控制中心
在自定义仪表板中手动比较 A/B 运行结果令人不堪重负。构建 MCP 服务器有所帮助,但与旧架构存在摩擦。
因此,我们重建了整个评估流程,使其以智能体为先,直接集成到 Slack 中。
Claude Code 编排器
- 开发者在 Slack 中向 Claude 发送消息:“在全新的 gemini-3.1-pro-preview 模型上运行五次评估。将其与 gemini-3-pro 的现有结果进行比较,并报告它是否在统计上显著更好。在哪些任务上它成功而旧模型失败?”
- Claude 通过我们自定义的 MCP 服务器并运行 Python 脚本来触发 Blacksmith 运行器。轨迹会流式传输到 Laminar 和 ClickHouse。
- 完成后,Claude 会收到通知。我们向它提供 Laminar 架构和一个示例片段,以便它知道如何直接查询原始轨迹数据:
import httpx
import os
def query(sql: str) -> list[dict]:
resp = httpx.post(
"https://api.lmnr.ai/v1/sql/query",
timeout=30,
headers={
"Authorization": f"Bearer {os.environ['LMNR_PROJECT_API_KEY']}"
},
json={"query": sql},
)
resp.raise_for_status()
return resp.json()["data"]
# Claude writes custom SQL like this
# to fetch the results for its analysis:
datapoints = query(f"""
SELECT
trace_id, index, scores,
group_id, executor_output
FROM evaluation_datapoints
WHERE evaluation_id = '{EVAL_ID}'
""")-
Claude 针对 ClickHouse 执行其生成的 SQL 查询并进行统计 A/B 分析,然后在 Slack 中发布摘要,建议为什么会出现差异。
-
开发者随后可以通知 Claude 根据该理论对代码库进行更改。如果后续的评估运行证明修复有效,我们就合并它。
结论与开源
这个流程不仅用于手动测试——它会在我们开源仓库中的每个 PR 上自动运行,以确保我们不会出现性能回退。
我们对开源的承诺仍然是首要任务。我们已在 github.com/browser-use/benchmark 为 LLM 提供商和研究人员开源了一个基准测试。评审提示词和设置位于我们的开源智能体 github.com/browser-use/browser-use 中。
我们正朝着完全闭环的方向迈进:一个自动化的无限自我改进循环,智能体评估自身、发现自身缺陷、编写自己的补丁,并以统计方式证明其成功。
要了解这些模型的实际比较情况,请查看我们的权威模型基准测试。有关我们早期 WebVoyager 结果的完整技术报告,请参阅我们的SOTA 技术报告。