资讯动态

AI Agent 交付物验收:Evidence 证据采集的工程实践

发布时间:2026/10/30 2:17:44 来源:尧图企业网站定制
目录1. 核心原则自述描述 ≠ 硬证据2. 证据采集的起点从 Rubric 定义开始3. 为什么不把整个 GitHub 仓库直接丢给 LLM4. 证据分级不同来源的可信度并不相同4.1 测试报告语义证据不是系统事实4.2 CI 是当前最强的一类证据5. Runtime Evidence 的明确边界6. 采集之后先过证据预检再交给 LLM6.1为什么缺证据时不应该继续调用 LLM7. 采集器本身也会产生“假证据”8. 描述性文本的定位与潜在风险9. Issue 为什么要纳入证据体系10. 统一证据字典与证据快照10.1 多源归一统一证据字典10.2 证据快照为什么要给 Evidence 做 Hash11. 当前方案的边界与局限12. 落地AI Tutor Engine 中的证据体系13. 总结摘要上一篇文章我们讨论了 Agent 任务验收的核心逻辑不能让 LLM 仅凭文本回复打分要基于可核验的交付物证据做判断。但新的问题随之而来这些证据从哪里来不同来源的证据可信度一样吗能不能直接把整个 GitHub 仓库丢给 LLM本文承接上一篇的四道闸门体系聚焦 Evidence Collection 证据采集环节的工程实现讲解如何从 GitHub、CI、Issue、测试报告等多渠道采集证据为什么要做证据分级关键文件筛选的取舍逻辑以及采集器本身可能产生的假证据问题。文章同样基于 AI Tutor Engine 的真实落地实践信科院智能助手暨南大学 AI 教学与学习助手https://jnuxky.xyz/信科院智能助手 · INFO SYSTEM在此明确当前方案的能力边界引擎本身不执行被评估项目运行类结论依赖外部证据。1. 核心原则自述描述 ≠ 硬证据先看一个最基础的场景任务要求实现一个登录接口并完成测试提交者只给出一句说明登录功能已经实现测试全部通过。如果评估系统只拿到这段文字实际上什么都无法确认。我们至少还需要知道代码在哪里接口逻辑是否对应需求测试文件是否存在测试是否真的执行CI 有没有通过有没有实际运行结果所以在设计 Evidence Collection 之初我先定下了一条基础原则描述可以作为上下文参考但不能自动等价于硬证据。当前系统会把提交者的 description 收集进证据集合供 Reviewer 理解上下文但在硬证据预检中会显式排除它。简单说description → 可以看、可以参考code / CI / runtime / report → 才可以参与对应的硬证据判断这一点看起来简单但如果不在系统层面明确区分很容易出现 “提交者说完成了 → LLM 觉得描述合理 → 直接 PASS” 的问题本质上是把自述当成了证据。2. 证据采集的起点从 Rubric 定义开始证据采集不能脱离任务本身凭空采集。任务不是一句标题而是要落地到具体的 Rubric 验收标准。例如一个 Rubric 的完整定义rubric: id: rb_lit01_1 task_id: lit_t01 criterion: 脚本能正确统计并输出前 10 名 required_evidence: [code, runtime] pass_condition: 代码中存在读取-计数-排序逻辑运行输出含至少 10 条「人物 次数」 weight: 2 evaluation_role: acceptance这里包含了两个完全不同的概念不能混为一谈required_evidence评估时必须看到哪些类型的证据是有没有的问题pass_condition满足什么条件才算通过是够不够的问题比如 required_evidence [code, runtime] 只说明必须有代码和运行证据但没说代码里具体要有什么。具体的验收标准需要通过 pass_condition 表达。因此完整的 Evidence Collection 流程是从 Rubric 开始的而不是从 GitHub API 开始的——先明确要什么再去采什么。3. 为什么不把整个 GitHub 仓库直接丢给 LLM拿到 GitHub 仓库地址后最直接的想法是下载所有代码全部塞给 LLM 让它自己判断。但工程上这样做并不理想。一个稍具规模的仓库可能包含 .git 目录、依赖包、测试数据、构建产物、锁文件、大量文档和日志这些内容并不是每次验收都需要。同时上下文越大不代表模型看得越仔细反而可能稀释核心信息。所以当前实现没有采用全仓库全文送审而是做了一层关键文件筛选。code_evidence.py 先通过 GitHub Tree API 获取仓库路径再按优先级选择需要读取的文件。同时设置了明确的量级限制图 1 关键文件筛选先按优先级挑关键文件再施加明确的量级限制这套策略不代表 “前 10 个文件等于整个项目” 它是一个工程上的取舍优先让 Reviewer 看到最有可能决定验收结果的核心内容。4. 证据分级不同来源的可信度并不相同证据不能只分有和没有不同来源的证据证明力天差地别。比如提交者说“我已经测试过了”和GitHub Actions 显示 Test → success显然不能按同一种证据处理。把当前系统中的 7 类证据按证明力做了明确区分证据类型主要能证明什么主要不能证明什么证据强度CI某个自动化检查的执行结论整个项目所有功能都正确强Code代码中存在某种实现逻辑代码一定能成功运行中强Runtime存在实际运行的痕迹与结果所有功能都经过完整验证中Report提交者记录的测试与问题记录的内容一定真实中Issue问题的发现与处理过程问题一定被彻底解决中弱Deployment存在可访问的线上入口所有需求均被满足中弱Visual截图中的可观察事实程序内部逻辑正确弱Description提交者的自述说明自述内容一定真实参考图 2 证据分级不同来源的证明力并不相同处理方式也随之不同对应的处理原则也不同强证据系统可以直接验证、直接判定中等证据需要 LLM 做语义解释与判断弱证据只能作为辅助补充信息参考信息仅用于理解上下文不参与硬证据判定4.1 测试报告语义证据不是系统事实在所有证据里测试报告需要特殊对待。README 描述项目怎么运行代码描述项目怎么实现而测试报告描述的是项目做过哪些验证。当前采集逻辑会优先寻找报告类文件比如 TEST_REPORT.md、test_report.md、bugs.md 等采集后会专门标记为「测试报告/问题记录」再提取正文内容。但这里有一个必须明确的边界测试报告本身不是绝对可信的报告写着 “登录测试正常” 只能说明提交者写了一份这样的记录不能直接证明测试确实执行过。所以报告适合作为语义证据而不应该自动升级成系统级事实——这也是报告和 CI 在系统里地位不同的核心原因。4.2 CI 是当前最强的一类证据如果说代码只能证明这里写了这个逻辑那么 CI 可以进一步证明某个自动化检查得到了什么结论。当前系统通过 GitHub Actions 获取 workflow runs把结果归一化为 name、dimension、conclusion 的统一结构CI 维度主要对应 build、test、runtime 三类。在 test → success 这个结论和提交者说我已经测试过了有本质区别前者来自自动化执行的客观结果后者来自主观自述。这也是为什么 CI 属于强证据可以直接触发 PASS / FAIL 判定。5. Runtime Evidence 的明确边界这是当前系统最容易被误解的地方。按普遍定性而论自动验收约等于默认系统会拉取代码、启动项目、自动运行测试、返回结果。但目前并不是这样。 当前引擎不会执行提交的代码没有 Docker 沙箱没有 pytest Runner没有进程隔离与资源限制也没有自动启动器。运行类证据目前主要来自三个渠道CI 执行结论README 或提交说明中的运行描述部署地址 URL甚至运行命令的提取也只是从文本中做关键字匹配。所以这里必须把两个概念严格分开Execution实际执行代码Execution Evidence执行产生的证据当前系统没有自己完成 Execution但可以收集和验证 Execution Evidence。这也正是上一篇文章中“代码只能证明‘写了什么”不能证明跑没跑通的底层原因。6. 采集之后先过证据预检再交给 LLM假设最终采集到了 code、ci、runtime、report、issue、description 全套证据这时候还有一个很容易忽略的步骤当前任务要求的证据真的齐了吗所以采集完成后会先经过 Evidence Precheck 证据预检这部分逻辑我们在上一篇文章中已经详细介绍过核心就是只做证据完整性检查不做任何语义评价。核心逻辑简化为needed set(r.required_evidence) - optional_bonus missing needed - present missing_real { m for m in missing if m ! description } if missing_real: forced.append({ rubric_id: r.id, missing: sorted(missing_real), reason: 缺少必要证据无法自动判定 })比如要求 code runtime实际只有 code结果直接返回 NEED_REVIEW不进入 LLM 环节。6.1为什么缺证据时不应该继续调用 LLM因为这时候模型无论怎么判断都只能靠猜。看到代码写得合理就很容易说出“从代码逻辑上看 应该可以正常运行”但问题就出在应该。系统真正需要的是已经证明可以运行而不是看起来应该可以运行。所以整个链路的职责划分非常清晰Evidence Precheck → 证据够不够LLM Reviewer → 有了证据是否满足语义要求Deterministic Aggregation → 最终分数和状态是什么这三件事不能混在一起。7. 采集器本身也会产生“假证据”这是目前系统里已经发现的一个真实问题也很有代表性证据采集本身也可能出错不能默认采集到的就是真的。比如 trace 证据目前的判断方式if agent_trace.json in repo_code_text: ev[trace] 仓库中包含 agent_trace.json...判断看起来很合理但实际场景中如果 README 里只是写了一句“本项目未来会生成 agent_trace.json字符串匹配也会触发这个条件。于是提到了文件名就被当成了文件存在这显然是不对的这说明 Evidence Collection 不能简单等于字符串搜索。更可靠的校验应该是三层文件是否真实存在文件是否可以正常读取文件内容是否符合预期这也是当前一个明确的优化点。8. 描述性文本的定位与潜在风险这里有一个看起来矛盾的设计description 会进入证据集合也会渲染给 Reviewer但 Evidence Precheck 又明确不把它算作硬证据。原因很简单一段自述虽然不能证明这个功能真的完成了但它可以告诉 Reviewer提交者认为自己做了什么。比如描述里提到 “登录接口使用 JWT增加了刷新 Token 逻辑” 这对于理解仓库上下文是有帮助的。所以当前的策略是description → 可以作为参考上下文description → 不能独立作为硬证据不过这里存在一个结构性风险它虽然通不过证据预检但 LLM 仍然看得到它。如果 Rubric 本身没有强硬证据要求模型理论上可能被一段说服力很强的自述影响。这是当前评估链里一个比较明显的漏洞面。9. Issue 为什么要纳入证据体系项目的代码只能告诉你现在有哪些代码但 Issue 能提供另外一条时间线发现问题 → 记录问题 → 尝试修复 → 关闭 Issue。当前系统会从 GitHub Issues 获取问题记录过滤掉 Pull Request同时限制数量和正文长度。这样 Reviewer 看到的就不只是代码快照还有完整的问题处理过程。比如Issue #12 登录失败原因Token 过期后未刷新Issue #15 修复 Token 刷新逻辑这类证据不能直接说明最终功能一定正确但对于判断项目有没有真实的开发过程、问题处理过程会比单纯的代码快照多一层信息。10. 统一证据字典与证据快照10.1 多源归一统一证据字典不同来源的数据结构都不一样GitHub API、CI API、Issue API、提交、部署地址、视觉证据。如果让后续逻辑分别处理很快就会变成一堆特殊判断。所以当前实现会把所有来源的证据统一归一化成标准的 Evidence Dictionary{ code: ..., ci: ..., runtime: ..., report: ..., issue: ..., deployment: ..., visual: ..., description: ... }之后所有评估环节都从这个统一结构读取采集来源和评估逻辑完全解耦。以后如果增加新的证据来源比如 MCP、外部测试平台或者其他 CI 系统只需要扩展采集层不需要重新设计整个 Reviewer。完整的采集链路如下图 3 Evidence 采集链路多源汇聚 → 归一 → 预检 → 分支10.2 证据快照为什么要给 Evidence 做 Hash还有一个容易被忽略的问题如果用户连续提交 5 次同一个任务、同一份代码、同一个 CI、同一份报告每次都重新调用 LLM本质上是在重复评估完全相同的信息。所以当前实现会对 task_id evidence ci 做规范化处理然后计算 SHA-256 生成快照哈希canonical json.dumps({ task_id: task_id, evidence: dict(sorted(available.items())), ci: sorted(...) }, ensure_asciiFalse, sort_keysTrue) snapshot_hash hashlib.sha256( canonical.encode(utf-8) ).hexdigest()[:16]再结合 rubric_version、prompt_version、engine_version、model 一起组成缓存键。这样做的核心是同一份 Evidence Snapshot 复用评审结果而不是同一次请求复用结果。前者围绕系统看到了什么做缓存后者围绕用户什么时候点击按钮做缓存两者区别很大。11. 当前方案的边界与局限把整个实现跑通以后也能清晰看到它的能力边界这里主动列出来引擎没有真正执行项目 这是最大的限制。如果没有 CI 或外部运行环境提供证据代码本身无法证明运行成功。关键文件筛选存在信息损失 当前并不是把整个仓库交给 Reviewer。“没有被采集”不等于“项目中不存在”只能说明当前评估没有看到这部分内容。部分证据存在性检查不够严格 比如字符串匹配判断文件存在的方式存在“声明即证据”的问题后续需要优化为真实文件校验。自述仍然可能影响 LLM 虽然 description 不能通过硬证据预检但 Reviewer 仍然可以看到它存在主观影响的可能性。12. 落地AI Tutor Engine 中的证据体系前面的所有讨论都来自我正在开发的 AI Tutor Engine 系统信科院智能助手 · INFO SYSTEM的真实实现这是面向编程类项目制学习场景的系统。在这个系统里用户使用 AI 编程工具完成项目再提交到 GitHub。评估系统不会只读取一句“我已经完成了”而是尝试采集多维度的证据GitHub 仓库代码、README、测试文件CI 执行结果Issue 记录测试报告运行证据、部署地址、视觉证据然后统一转成标准 Evidence 结构再进入完整的评审链路证据预检 → CI 直接判定 → LLM 语义评审 → 确定性聚合。这套设计的出发点其实不是“让 AI 看更多东西”恰恰相反让 AI 只看那些与当前任务验收真正相关、并且能够被解释的东西。13. 总结把文章压缩成一句话这样描述 Evidence Collection不是“把更多数据丢给 LLM”而是“把与任务相关、来源明确、作用边界清楚的证据组织给 LLM” 。整个完整工作流可以归纳为图 5 Evidence Collection 完整工作流从任务定义到评审其中最重要的几个原则是自述 ≠ 硬证据Code ≠ RuntimeCI 事实优先于 LLM 猜测证据不只是“存在/不存在”还有可信度分级采集器本身也需要防止误判证据不足时不应该逼 LLM 做二选一当前这套实现仍然存在不少问题比如运行环境沙箱、静态分析、证据真实性校验、关键文件筛选粒度、缓存策略优化等。但至少到这里Agent 的验收过程已经从“LLM你觉得这个项目做完了吗”进化成了更工程化的问题链任务要求什么 我拿到了什么证据 这些证据分别能证明什么 还缺什么 哪些地方可以直接判断 哪些地方才需要 LLM而这也是 Evidence Collection 在 Agent Evaluation 里真正应该解决的问题。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑