基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-04 15:53

复核代理未执行,流水线却报审核通过

dev.to · AI#Agent#流水线#可靠性
Editor brief · 编辑速览

一个双阶段 AI 审核流水线将四篇草稿标记为通过,但第二阶段代理实际从未检查,草稿仍含无来源数字和错误引用。作者复盘审核失效经过,并介绍新增的两项检查。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

4 篇 AI 草稿被日报助手宣布「审核通过」,负责第二阶段裁决的模型却一篇都没看过。作者在发布前拦下了问题:无来源数字、效果宣称,以及从蚊子章节搬到蟑螂身上的事实,全都藏在 compliance: passed 后面。

这次故障值得程序员看几分钟,因为它暴露了 AI 流水线里的两个不同问题:状态没有执行证据,事实有出处却归错了对象。作者用两个小检查补洞,也明确交代了它们还管不到哪里。

为什么第二阶段没运行,草稿也能通过

作者维护一个副项目,用 AI agents 生成日文家庭防虫短帖。草稿进入 outbox/,由作者阅读后手动发布,没有自动发帖。

审核分两级:便宜的小模型 scan 检查禁用和边界表达,包括保证性措辞、100%、没有来源的效果数字等,只报告、不修改。明确违规的内容退回写作端;边界项交给更大的模型 judge,决定放行或提出修改要求。没有边界项时,可以跳过 judge。

因此,问题并不是每篇都必须调用大模型,而是必须区分「无需调用」和「根本没调用」。

出事的 4 篇草稿来自首次搭建流水线的试运行。scan 执行了,judge 没执行,文件却写上了 compliance: passed。这些创建于 2026-07-10 的草稿,在正式待发目录里留了 7 天。

另一份流水线日志明明写着试运行没有完成审核,但日报助手只读取草稿里的状态。它照字段报告,没有机制要求它核对另一份日志。

状态只能表达结论,不能证明产生结论的步骤确实执行过。

作者随后要求草稿携带 compliance_log:有边界项时,记录 scan 2026-07-17 和 judge 2026-07-17;没有边界项时,明确记录 judge不要,即日文的「不需要 judge」。

下面是发布前门禁的核心函数,原样保留。外围代码用正则提取日期:SCAN 匹配带日期的 scan,JUDGE 匹配带日期的 judge 或精确标记 judge不要。

export function checkDraft(fm) {
  if (fm.compliance !== "passed") return { ok: false, why: "not marked passed" };
  const log = fm.compliance_log;
  if (!log) return { ok: false, why: "passed, but no compliance_log" };
  const scan = log.match(SCAN);
  if (!scan) return { ok: false, why: "no dated scan record" };
  const judge = log.match(JUDGE);
  if (!judge) return { ok: false, why: "scan recorded, judge stage missing" };
  if (judge[1] && judge[1] < scan[1]) return { ok: false, why: "judge dated before scan" };
  return { ok: true, why: `scan ${scan[1]} / ${judge[1] ? "judge " + judge[1] : "judge not needed"}` };
}

要看的是拒绝缺失 JUDGE 记录的那一行:只有第一阶段记录,不能算完整通过。日期采用 YYYY-MM-DD 格式,因此可以按字符串比较先后。

实际运行时,当周重新审核的 6 篇通过,下一周的 3 篇被拦下,文件名分别是 2026-07-24-post-1.md、2026-07-24-post-2.md、2026-07-24-post-3.md。

后面这 3 篇其实审核过:scan 找到 5 个边界项,judge 放行 2 个、要求修改 3 个;写作 agent 拒绝了其中 2 条修改意见并记录理由,修改后再次扫描干净。问题是证据只在日报日志里,没有写回草稿。

作者仍然保留 HOLD。对这个小项目,要求状态和证据放在同一个文件里,可以让门禁只读一处,避免再次面对互相矛盾的记录。

事实能搜到,为什么仍然是错的

作者手动重审 4 篇,3 篇没有问题,第 3 篇集中暴露了事实审核的漏洞。

其中一个数字声称虫害投诉会在某个月份走高,但参考文档根本没有季节数据。另一个温度数字则确实存在,只是出现在蚊子章节,描述蚊子的繁殖条件,被模型挪到了蟑螂活动上。

全文搜索会找到这个数字,句子读起来也合理。它还套了「据说」一类措辞,绕过了只针对确定性陈述的无来源数字规则。

错误发生在事实与对象的连接处。

judge 的修复又犯了一次类似错误。它找到蟑螂产卵季节的信息,却附上「根据厂商数据」。原文确实引用过厂商,但支持的是上方另一条「每个卵鞘有多少卵」的事实,并不支持产卵季节。

作者增加的第二个检查,便是返回搜索命中所在的 Markdown 标题路径。辅助函数 sections(markdown) 解析 #{1,6} 标题层级,再由下面的函数定位命中位置:

export function locate(markdown, needle) {
  const { lines, list } = sections(markdown);
  const hits = [];
  lines.forEach((line, i) => {
    if (!line.includes(needle)) return;
    const owners = list
      .filter((s) => s.start <= i + 1 && i + 1 <= s.end)
      .sort((a, b) => b.depth - a.depth);
    hits.push({ line: i + 1, path: owners.reverse().map((s) => s.title).join(" > ") });
  });
  return hits;
}

要注意 line.includes(needle):它查找的是字面字符串,无法识别改写后的同义表达。

CLI 将标题路径与目标对象比较。以 cockroach 为对象,错误温度信息返回 MISATTRIBUTED L89,路径落在 Guide > Details > 3. Mosquitoes;重写后保留的卵鞘孵化时长返回 OK L66,位于 Guide > Details > 1. Cockroaches > Egg-laying sites。原文展示的是翻译后的标题,实际资料使用日文。

这个检查能发现跨章节挪用,抓不到同章节里的引用错配。摘要也可能重复事实,Caveats 中的命中还可能是在反驳某个说法,所以它适合提示人工查看,不能单凭标题位置判定真假。

为什么审核修辞,还会漏掉整篇立意

问题草稿的主钩子,是某种家居设施在夏季经常成为蟑螂入口。资料虽然列过这种可能性,下一条却引用专业人士观点,认为它不太可能成为入口;文末 Caveats 还把相关说法列为争议项。

scan 没发现禁词,judge 只看 scan 提交的边界项。于是,决定文章是否成立的冲突,没有进入审核视野。最后作者换了一个没有争议的事实,重写整篇。

这暴露了串联审核的盲区:后一级模型再强,也看不到前一级没有提交的问题。

作者因此补了三条规则:所有数字和事实必须给出参考文档行号或一手来源 URL,「据说」不能豁免;每次检查 Caveats,主钩子依赖争议事实就重建文章;规划日志只能提供选题线索,不能充当证据。

允许 URL 是有实际原因的:季节性内容需要当前新闻,静态资料未必收录。若只接受内部行号,这类内容会被全部拒绝。

规划日志也差点制造下一次错误。里面曾建议围绕某个月份的虫害高峰选题,但后续研究没有找到支持统计,找到的数据反而指向另一个月份。计划写得再具体,也没有自动获得事实资格。

我的判断

我赞同作者把模糊要求变成可执行门禁。缺字段、缺阶段、日期倒置,适合交给确定性代码检查,没必要让模型每次重新理解一遍规则。

但这个脚本验证的是「记录形状符合要求」。它不能独立证明审核运行过,也没有把审核结果绑定到某一版草稿。若 agent 写错日志,或者审核后正文又被修改,现有检查未必能发现。作者没有给出这些情况的验证结果。

同文件存证适合这个文件驱动的小项目。一般团队已有 CI 或工作流系统时,也可以使用关联到具体产物版本的执行记录;关键是门禁能够确定地找到对应证据。分散保存不必然失效,缺少可靠关联才会制造盲区。

章节定位也是实用的低成本补丁,但距离事实核验还很远。作者没有给出与完整语义审核的对照数据,也没有报告整体漏检率,因此只能确认它能抓住这次跨章节错误,不能替它背书为普遍有效的审核方案。

更大的模型在修复时仍然错配引用,这个案例足以提醒我们复查修改结果,却不足以推出所有大模型审核都不可靠。

能拿来做什么

  • 给日常 AI 编程流程里的 reviewed、approved、done 补上检查记录,并让脚本拒绝缺失证据的结果。至少能回答执行了哪个检查、何时执行,以及哪些步骤被明确跳过。
  • 用 Node 处理 Markdown 知识库时,让搜索结果同时返回行号和标题路径。审核 API 文档或技术内容里的数字时,先确认它属于当前对象,再检查它支持的具体说法。
  • 将事实一致性检查与禁词扫描分别设计。如果后一级只接收扫描器的命中项,就需要给主张冲突、限制条件和争议说明安排独立检查入口。
  • 检查正式待处理目录中首次搭建当天留下的产物,并复查审核 agent 修改后的事实和引用。试运行输出与修复结果,都可能带着看似可信的完成状态进入下一步。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
AI代码看似正确?先核对测试执行与断言
下一篇
合并AI代码前,先核实依赖与API

资讯速览

dev.to · AI · 2026-11-04 15:53

AI 评分 8.0 / 10

相关标签

#Agent#流水线#可靠性

继续阅读

  • 用低成本分类器优化编码代理模型开销
  • AI代码看似正确?先核对测试执行与断言
  • 合并AI代码前,先核实依赖与API
  • Postman 被曝静默修改编程助手配置
  • 实测 Claude Code 是否主动调用 MCP