在浏览器代理的工程实践中,一个常见的思路是依赖更大、更强的云端模型来解决问题 —— 给模型更多的像素、更多的参数、更多的上下文,似乎就能自动化更复杂的网页流程。然而,这种「智能即可靠性」的假设在生产环境中往往站不住脚。Amazon 的购物流程包含动态加载的元素、弹窗干扰、页面状态突变等挑战,单纯的视觉代理容易陷入「静默失败」的困境:模型以为自己成功了,实际上页面毫无变化。
本文从 Sentience API 发布的 Amazon 案例研究出发,聚焦一个核心论点:可靠性来自于验证,而非智能本身。通过结构化快照、显式断言门控和三模型栈架构,即使使用约 3B 参数的本地模型作为执行器,也能在 Amazon 购物流程中实现端到端的自主完成。这不是模型能力的胜利,而是验证层设计的胜利。
从像素到结构:控制平面的范式转换
传统的视觉代理将截图作为控制平面,每一次决策都基于像素的解读。这种方法的问题在于它的脆弱性:当页面出现微小的 UI 变化、元素位置偏移、或者相似的视觉特征干扰时,模型很容易产生误判。更大的模型可以降低误判概率,但无法消除根本的不确定性 —— 因为像素本身不携带语义信息,模型只能猜测意图与当前状态的对应关系。
结构化快照(structured snapshot)的思路与此不同。它将页面视为一个包含角色(role)、文本、几何信息和关键性权重的结构化数据对象,而不是一张图片。模型接收的不再是「看起来像个按钮的像素区域」,而是「ID 为 add-to-cart-button、角色为按钮、包含文本『加入购物车』的可点击元素」。这种表达方式消除了视觉歧义,让模型的动作选择变得可验证、可调试。
在实践参数上,Sentience 的快照包含的元素数量经过精心过滤。原始 DOM 可能包含数百个节点,但实际传递给模型的结构化快照通常控制在 50-100 个关键元素以内。这种过滤不仅减少了 token 消耗(约 43% 的压缩比,从约 35,000 降至 19,956),更重要的是它移除了分散模型注意力的干扰项,让决策聚焦于任务相关的核心元素。
验证即门控:Jest 风格的代理测试
如果结构化快照解决的是「模型看到什么」的问题,那么验证层解决的是「如何判断模型做对了没有」的问题。这借鉴了软件测试中的断言(assertion)概念:每个代理动作执行之后,系统不是等待模型的自我报告,而是主动检查页面状态是否达到了预期的结果。
具体实现中,验证断言以谓词(predicate)的形式定义,作用于当前的结构化快照。例如,一个典型的断言可能是 url_contains("/gp/cart")(检查是否已跳转到购物车页面)或 exists("[data-test-id='add-to-cart']")(检查加入购物车按钮是否存在且可见)。这些断言是确定性的:给定相同的页面状态,它们总是返回相同的结果,不受模型「自信程度」的影响。
验证层的门控机制体现在它的阻断性上。如果一个断言失败,当前的步骤不会被标记为「完成」,而是触发重试逻辑或修正流程。在 Amazon 案例中,当点击商品后页面没有正常跳转,验证层会检测到 URL 未变化,从而阻止代理继续执行后续的「加入购物车」操作。这种设计将「静默失败」转化为「显式失败」,为调试和恢复提供了明确的锚点。
断言的工程化实现包含几个关键设计。首先是 required 参数:标记为 required=True 的断言如果失败,会触发失败工件(screenshot、DOM 快照、trace)的持久化,便于后续分析。其次是 check() 方法的流式接口,支持 .once()(立即检查)或 .eventually()(等待条件满足,超时则失败)的组合使用,适应异步 UI 的不确定性。最后是确定性覆盖(deterministic override):当验证层明确知道用户意图时,可以主动覆盖代理的动作选择 —— 例如,当检测到 Amazon 的弹窗出现时,验证层会直接执行关闭操作,而不是等待代理模型「理解」并处理这个干扰。
三模型栈架构:规划、执行与验证的分离
案例中的架构采用了规划、执行、验证三角色分离的设计,这就是所谓的「三模型栈」。每个角色有明确的职责边界,通过结构化的接口进行通信。
规划模型(planner)负责高层次的任务分解和策略制定。它接收用户目标(如「在 Amazon 购买一台 ThinkPad」),输出一个包含多个步骤的结构化计划,每个步骤都附带验证目标的定义。例如,规划模型可能会输出:「步骤 3:点击第一个搜索结果。验证:当前 URL 包含 /dp/ 且页面包含产品标题元素。」在 Amazon 案例中,规划模型使用 DeepSeek-R1 系列或 Qwen 2.5-7B,本地运行以控制成本。
执行模型(executor)负责根据当前快照选择具体的动作。它不关心任务的全貌,只需要从可用的动作选项(CLICK、TYPE、SCROLL 等)中选择符合当前上下文的一个。执行模型被有意设计得「小」—— 案例中使用约 3B 参数的本地 Qwen 模型 —— 因为它的输入经过高度压缩,输出只是简单的动作序列。小模型的推理延迟低、本地运行零成本,这为大规模部署提供了经济基础。
验证模型在 Sentience 架构中不是一个独立的 LLM,而是运行时(runtime)中的确定性逻辑。它对结构化快照执行预定义的断言,生成 PASS/FAIL 结果,并根据结果决定是否放行当前步骤。这种设计避免了「用模型验证模型输出」可能导致的循环问题:验证逻辑是显式的、可审计的、行为一致的。
三者之间的数据流转遵循固定的模式。规划模型输出 JSON 格式的计划 → 运行时接收计划并按步骤执行 → 每一步先由执行模型选择动作 → 动作执行后由运行时拍摄快照并运行断言 → 断言结果决定步骤是成功、重试还是回滚。整个流程的 trace 会被记录并上传到 Sentience Studio,用于事后分析和调试。
Amazon 购物流实测数据:云端基线与本地自主的对比
案例设计了四个逐步演进 demo,任务统一为「Amazon 搜索 thinkpad → 点击第一个商品 → 加入购物车 → 结账」。这四个 demo 覆盖了从云端基线到完全本地自主的完整光谱,提供了可量化的对比数据。
Demo 0 是云端基线,使用 GLM-4.6 级别的云端模型配合 Sentience SDK。结果显示单次运行成功,耗时约 60,000 毫秒,token 消耗约 19,956。值得注意的是,仅通过结构化快照和元素过滤,token 消耗就从估计的 35,000 降低了约 43%。这验证了「接口设计优于模型选择」的论点:更好的数据结构带来的效率提升,可能超过模型尺寸升级的效果。
Demo 1 引入人类编写的计划(human-authored steps),执行器换成约 3B 参数的本地 Qwen 2.5 模型。结果是 9/9 步骤全部通过,耗时 207,569 毫秒,token 消耗降至 5,555。这个 demo 证明了只要验证层健壮,小模型完全可以胜任执行任务。
Demo 2 让规划也本地化,使用 Qwen 2.5-7B 作为规划器、Qwen 2.5-3B 作为执行器。结果是 7/8 步骤成功,耗时 435,446 毫秒,token 消耗 13,128。这里出现了规划漂移(planner drift)的问题:规划器生成的验证目标偶尔会指向脆弱的选择器,导致步骤失败。但关键在于,失败是被验证层显式捕获的,而不是隐藏在看似成功的表面之下。
Demo 3 是最终形态,使用 DeepSeek-R1 系列作为规划器、本地 Qwen 系列作为执行器。多次运行的结果显示:一次运行 7/8 步骤成功,重新运行后达到 7/7 全通过。平均耗时约 400,000-500,000 毫秒,token 消耗约 11,000-13,000。虽然耗时显著高于云端基线,但增量成本为零 —— 所有推理都在本地 Mac Studio(M4 芯片)上完成。
工程化参数与阈值配置
从案例中提炼出几个关键的工程化参数,可作为类似代理系统设计的参考。
在快照粒度上,建议将页面元素过滤后控制在 50-100 个核心节点。过滤标准包括:可见性(仅保留 display:none 之外的元素)、角色相关性(优先保留按钮、输入框、链接等交互元素)、以及文本长度(截断过长的文本节点以控制 token 消耗)。
在断言设计上,每个步骤建议配置 1-3 个断言,涵盖成功条件(must-pass)和期望条件(nice-to-have)。成功条件断言标记为 required=True,失败时立即触发工件保存和流程阻断;期望条件断言用于记录和监控,不阻断流程。
在超时与重试上,案例中单步操作的超时设置约为 30-60 秒,考虑到本地模型推理的延迟。重试策略建议采用指数退避,首次失败后等待 1 秒重试,第二次等待 2 秒,最多重试 3-5 次。超过重试次数后,将步骤标记为失败并进入人工介入队列或回滚流程。
在确定性覆盖的触发条件上,案例展示了两种典型场景:弹窗干扰(如 Amazon 的加购弹窗)和意图明确的选择(如点击搜索结果的第一个商品)。覆盖逻辑应该保守 —— 只有当验证层有 100% 信心时才覆盖代理决策,避免引入新的错误路径。
可观测性与调试:从失败中学习
验证层的另一个重要价值是可观测性。每个步骤的快照、断言结果、执行动作、覆盖决策都会被记录,形成完整的执行 trace。这些数据对于理解代理行为、定位失败根因、持续优化系统至关重要。
在 Amazon 案例中,Sentience Studio 提供了时间线视图,展示每个步骤的验证信号分布。成功的步骤会显示绿色的断言通过标记,失败的步骤会高亮显示具体哪个谓词未通过,以及失败时的页面快照。截图对比功能允许开发者快速定位「预期状态」与「实际状态」的差异 —— 例如,断言预期 URL 包含 /cart 但实际仍停留在 /search。
案例还展示了失败模式的一种类型:当规划器生成的选择器过于脆弱(如使用易变的 data-test-id),即使代理正确点击了元素,断言也可能因为选择器未匹配而失败。这种情况下,优化方向是改进规划器提示或使用更稳定的选择器策略,而非加强验证层本身。
Trace 上传和视频生成功能为事后复盘提供了完整的上下文。案例中的每次运行都会生成一个短视频,压缩了从开始到结束的关键页面变化,配合结构化的 trace 数据,使得非实时调试成为可能。
从案例到实践:何时以及如何引入验证层
验证层的价值在不同场景下有不同的权重。对于一次性演示或原型开发,验证层可能显得过于复杂 —— 快速迭代、频繁变更任务定义时,维护断言逻辑的成本可能超过其收益。但对于任何需要稳定运行、可重复执行、可审计追溯的生产系统,验证层几乎是必选项。
引入验证层的时机建议在代理系统能够完成基本任务之后。此时引入验证层的目标不是「让代理能做更多」,而是「让代理做对了能被知道」。过早引入验证层会增加调试负担,因为任务定义本身还在频繁变化;过晚引入则可能积累大量难以追溯的静默失败。
渐进式引入的策略是从关键路径开始。首先识别任务流程中不可失败的步骤 —— 例如支付、提交订单 —— 为这些步骤添加高信度的断言。然后逐步扩展到中间步骤,直到整个流程都有可验证的里程碑。每个断言的添加都应该有明确的预期收益,而不是为了「全面覆盖」而堆砌。
验证层的维护成本需要纳入长期规划。网页 UI 会变化,选择器会失效,断言需要随着 UI 变更而更新。建议为断言库建立版本管理,并为每个任务维护一套断言模板,以便在新任务复用时快速适配。
结论:可靠性不是模型给的,是架构给的
Amazon 案例揭示了一个反直觉的事实:在浏览器代理领域,更大的模型和更多的视觉信息并不能自动带来更高的可靠性。可靠性来自于对执行结果的显式验证,来自于对不确定性的主动捕获,来自于将「模型认为」替换为「系统确认」的设计决策。
结构化快照、三模型栈分离、Jest 风格的断言门控 —— 这些技术组合在一起,构成了一个可以让本地小模型可靠运行的框架。虽然单次运行的延迟显著高于云端模型,但零边际成本、本地数据隐私、以及可预测的失败模式,使得这种架构在企业级部署中具有独特的吸引力。
如果你正在构建或评估浏览器代理系统,不妨从这个问题开始:「当代理声称它完成了某一步,我有什么证据可以验证这个声明?」如果答案是「没有」或「模型自己说自己成功了」,那么无论使用多强大的模型,系统都仍然停留在演示阶段。只有当每个步骤都有可检查、可记录、可审计的验证点时,代理才能真正走向生产可靠。
参考资料
- Sentience API: A verification layer for browser agents: Amazon case study (https://sentienceapi.com/blog/verification-layer-amazon-case-study)