“在线视频播放网址检索记录”Agent 的 SFT 轨迹数据合成项目,8 周,两次失败训练,三次架构转向。这篇文章完整记录:纯 LLM 驱动路线的六层补丁如何逐一失效、架构级问题如何被确证、最终如何落到“LLM 探索 + 环境执行 + verifier 过滤”的主流范式,以及一个关键自我纠错——曾把“代码管事实”错误扩展到了决策层。
一、项目背景与起点
任务域:给定视频内容(剧名 + 在线),Agent 需全量检索在线播放网站、逐站验证可播放性、整理输出结构化记录。目标产出 SFT 训练轨迹。
初始方案:当时的主流直觉——蒸馏。商业 LLM 驱动 Agent 执行任务(开源 agent 框架 + browser-use 工具层),用户端模拟器下发任务、收集全轨迹,再靠事后补丁保障质量。
初始默认认知:商业模型的能力可以直接迁移到 Agent 决策,质量问题靠堆流程修。
后来的经历证明:这半句是对的,另半句错了整整八周。
二、六层补丁演进史:一次失效边界的完整测绘
第一阶段的迭代方式是“看到什么问题修什么”,六层补丁依次落下:
层 | 触发问题 | 动作 | 事后定位 |
0 | 起步 | 开源 agent 改造 + 模拟器下发/收集 | 组件雏形 |
1 | 工具调用连续错误、页面噪声 | 错误折叠(保留一次失败+成功)、页面内容简化 | 与主流错误恢复数据处理不谋而合 |
2 | 思考内容太浅 | LLM 优化 + 原文/优化后语义核对 | 一致性闸门雏形 |
3 | 系统提示词冗余 | 裁剪框架说明、精简工具列表 | 训练/部署一致性意识 |
4 | 检索覆盖不全、“免费在线观看”触发模型拒绝 | 轨迹验证 + 重复执行 2–3 次博概率 | 拒绝采样,但无诊断信号,纯碰运气 |
5 | 质量仍低 | Label Studio:LLM 审查 + 人工修正 | 人机协同,缺锚点 |
6 | 边际收益趋零 | 止损,转向架构讨论 | 本项目最重要的一次判断 |
六层的结构性结论:前三层修数据格式(解决了),中间两层修分布(部分解决),最后撞上的是架构级问题——补丁穷举的价值恰恰在于它是唯一能区分“质量可修”与“架构不可修”的路径。 |
三、两个致命发现
发现一:价值观污染事实层
商业模型对这个内容域的安全偏向不是“偶尔拒答”,而是系统性扭曲事实产出:检索覆盖不全、执行中断、页面内容被模型转述而非真实存档。当 LLM 同时是决策者和事实源时,一切下游补丁都在修一个被污染的源头。
发现二:循环验证陷阱
更隐蔽的一个:用同一个商业模型既当运动员(合成数据)又当裁判(评分),测不出专门绕开该模型偏差训练的模型——分数越高问题可能越大。两次失败训练不是终点,它们作为归因材料进入了失败模式库,后来直接转化为黄金集的评测维度来源。
四、第二次架构转向与一次重要的自我纠错
基于两个发现,曾确立“代码管事实层、LLM 管语言层、persona 管输入分布”的三层分工,并设计了代码控制流架构:检索→打开→验证→记录全链路由代码编排,LLM 只做页面语义分析和 rationale 生成。
这个架构的归因性、可控性、数据成功率确实好。但后来对照 2025–2026 年的主流实践(Explorer、BrowserGym、CodeGym、ASTRA)时,我发现混淆了三个控制层:
控制层 | “代码管事实层”是否成立 | 主流做法 |
决策层(谁决定下一步) | 不成立——此处过度了 | LLM agent 探索式决策 |
事实/执行层(动作落地、观察来源) | 成立 | 确定性环境执行 + 真实 DOM 回放 |
验证层(轨迹对错) | 成立 | verifier 过滤(代码断言 + LLM 裁判 + 人工) |
主流恰恰是:把场景差异压缩到统一的环境接口层(动作空间/观测空间/验证接口),在接口之上用“LLM 探索 + 环境反馈 + verifier 过滤”批量合成,而不是每个场景手写一套管控代码。硬编码控制流合成的轨迹是蒸馏自己的编排器——决策多样性在源头就没产生过,工程开销还随场景线性增长。 | ||
修正后的结论:代码控制流路线以可控性换泛化性,在“部署即固定流程”的窄域成立,但不是面向 agent 能力的合成范式。方向不是放弃原则,而是把场景特定的部分从代码改写成数据和模板。 |
五、最终架构:薄编排
5.1 总体形态
一个任务(“在线免费观看某剧”)被拆成四个模型任务,由一条薄编排层(thin orchestrator)缝起来:
[代码] 任务接收(persona 生成的表述 + 标准归一)→ 组装检索指令 ↓ [模型任务1] 网络检索 → 真实结果页内容存档 ↓ [代码] 内容打包 + 阶段策略提示词 + 覆盖清单登记(12 个候选站入册) ↓ [模型任务2] 逐站分析(+ 站点分类策略提示词)→ 结构化判定 ↓ [代码] 按判定分发工具调用 → 每步观察存档 ↓ [模型任务3] 播放页验证(+ 组件验证策略提示词)→ 结构化判定 ↓ [代码] 覆盖断言(12 站是否全部处置)→ 失败/拒绝 → 定向重采样 ↓ [模型任务4] rationale 逐步生成(锚定真实观察) ↓ [代码] 一致性闸门三查 → 样本组装 → 三层评分 → 入库 / 负面池5.2 “薄”的判别标准
薄编排层里的 if 全是状态判断(返回了没、超时了没、清单齐没齐),不含一个业务判断(有没有按钮、是不是播放站)。判别方法:这个 if 需不需要“理解网页”——需要的全交模型,不需要的全留代码。后者跨场景不改一行,这就是“场景差异压进数据”的物理形态。
关键留白:宏观骨架代码管(阶段推进、覆盖登记),微观路径 LLM 管(探索顺序、重试、改道)。阶段切太细会把 LLM 退化成分类器串联——等于换个形式继续蒸馏流程。
5.3 LLM 价值观问题的最终解法:不消除,控制拆解
决策权交还 LLM 后,价值观影响回来了——但它从决定成败的暗变量降格为每天被统计、被诊断、被处理的公开报表:
- 事前:任务中性化重构(“遍历站点清单并检测 video 元素”替代“找免费资源”),persona 库设中性化表述档位
- 事中:覆盖断言把“拒绝”变成有 ID、有位置、有类型的结构化事件(旧架构里它混在“质量不高”里无法归因)
- 事后:诊断驱动重采样——带着病历复诊而非碰运气;三次均拒的域快速确认是模型选型问题,损失以小时计而非周计
某内容域若重采样三次仍高拒绝率,没有架构能救,只能换模型或换域。新架构的全部意义是把这个墙的存在以天为单位测出来,而旧架构要以两次失败训练、六层补丁为代价才明白。在训练后评估、归因时最糟糕的方式,过长的链路会让很多成本、时间浪费在错误的路径上。
六、数据流程:六件套、三查、三层瀑布
6.1 轨迹样本结构
每条样本六件套:系统提示词、工具参数列表、任务提示词(persona 版)、动作+参数、观察(真实 DOM 回放存档)、思考+结论。
铁律:动作、参数、观察是代码执行的事实记录,LLM 永不可触碰;思考是唯一允许 LLM 生成的部分,且它是翻译不是创作。
6.2 rationale 生成:边执行边写
每步动作 + 真实观察到位后,立即调 LLM 写本步思考,prompt 四要素:信息边界声明(只依据给定观察)、前因后果链、认知角色(写“当时的思考”非复盘)、格式约束。允许表达不确定,禁止编造确定。
生成后过一致性三查:实体核查(思考中的实体必须在观察存档中,代码自动零成本)、因果核查、时序核查(不泄露后见之明)。
6.3 三层评分瀑布
层 | 维度占比 | 上岗条件 |
代码断言 | 70–80%(可达性、schema、覆盖、字段、结论对照) | vs 黄金集 ≥90% |
LLM 裁判 | 15–25%(rationale 吻合度、语义判断) | vs 黄金集 ≥85%,逐维度领证 |
人工 | 分歧仲裁、5–10% 抽样、黄金集维护 | 永久保留 |
黄金集 100–200 条(含两次失败训练的真实轨迹),校准/持有 7:3 隔离,自我一致性 ≥0.7,git 版本化冻结。所有数据凭一致率上岗,所有分歧凭仲裁回流——项目从“数据量竞赛”转型为“验证闭环驱动”。 |
6.4 负样本纪律
失败分支(非播放站排除、超时止损、组件加载失败标记未验证)强制入库成负面池——模型只会正确路径是 SFT 数据最常见的隐疾,终止条件同样需要教材。
七、经验清单
方法论级:
- 补丁穷举是区分“质量可修”与“架构不可修”的唯一路径——但给止损设预算(本项目第六层止损,是做对的最重要一步)
- 运动员兼裁判的评估体系测不出专门绕开该偏差的数据——评估锚点(黄金集)必须先于放量存在
- 拒绝采样没有诊断信号就是碰运气——重采样必须携带失败类型
架构级:
- 拆三个控制层(决策/事实/验证)再谈“谁管什么”,不拆层会像我一样在决策层过度代码化
- 事实层交给环境(真实 DOM 回放),LLM 的自由度收窄到“选路径”——恰好落在 verifier 射程内
- rubric 同时是评分标准和策略提示词的内容来源,一份标准两处用
- 宏观骨架代码管,微观路径模型管——这条线画清楚,可控和泛化同时保住
组件级:
- 错误折叠(保留一次失败+成功)、DOM 预处理前置、边执行边写 rationale、覆盖断言清单制——这四件是性价比最高的迁移件