实验 5-8:生产日志的智能诊断系统¶
配套《深入理解 AI Agent》第 5 章「代码作为生成式能力 —— Agent 执行日志自动分析和问题诊断」。
目的¶
生产环境的 Agent 会产生大量轨迹日志(trajectory)。从中识别问题、定位根因、构建回归测试成本很高。 本实验让一个诊断 Agent 自动完成这条流水线:
读轨迹集合 + 架构文档 + PRD → 定位问题、生成结构化报告 → 生成回归测试用例 → 重放框架真正执行验证 → (mock) 通过 MCP 对接 GitHub 创建 Issue。
诊断流水线¶
data/trajectories.jsonl (含已知问题的生产轨迹)
data/architecture.md (系统架构) ┐
data/PRD.md (产品需求) ├─► [LLM] diagnose() 结构化问题报告(优先级/模块/描述/建议)
┘ │
▼
[LLM] gen_test_cases() 回归测试用例(引用轨迹ID+交互轮次)
│
▼
replay.py 重放框架 ── 对同一输入重放被测系统并断言
(A) 未修复系统 → FAIL(复现bug)
(B) 修复后系统 → PASS(验证修复)
│
▼
github_mcp.py (mock) 渲染并打印/落盘 GitHub Issue
diagnoser.py:诊断 Agent,两次真实调用 OpenAI(默认 gpt-5.6-luna,JSON 模式)。sut.py:被测系统的确定性仿真器。fixed=False复现线上 bug,fixed=True模拟修复后行为。replay.py:回归测试重放框架。取轨迹输入 → 重放sut→ 在新轨迹上求值断言(内置 4 种断言 DSL)。github_mcp.py:GitHub Issue 创建,默认 mock(打印 + 写output/github_issues.json)。
预置的已知问题(Agent 应能定位)¶
| 轨迹 | 问题 | 违反 PRD | 定位模块 |
|---|---|---|---|
| T-1001 / T-1002 | 退款前跳过了强制的 verify_refund_eligibility 校验 |
R1 (P0) | order_service |
| T-1002 | process_refund 反复失败、无退避、且最终误报成功 |
R2 (P0) | payment_service |
| T-1003 | check_stock 延迟 8300ms 超时未降级 |
R3 (P1) | inventory_service |
| T-1004 | 正常轨迹(对照组,无问题) | — | — |
运行¶
pip install -r requirements.txt
cp env.example .env # 填入 OPENAI_API_KEY(模型默认 gpt-5.6-luna);未配置时设 OPENROUTER_API_KEY 自动改走 OpenRouter
python demo.py # 完整流程(两次真实 LLM 调用)
demo.py 一次跑完:读轨迹 → 诊断报告 → 回归测试用例 → 重放执行(通过/失败) → (mock) GitHub Issue。
常用参数(python demo.py -h 查看全部):
--smoke:免 API 快速自检,跳过 LLM,用内置诊断结果仅跑重放框架 + GitHub mock,验证管道是否端到端连通(全绿退出码 0)。适合无 Key 环境或 CI。--model gpt-5.6:临时覆盖模型(等价于设置OPENAI_MODEL)。--data-dir DIR:换用自己的输入目录(需含trajectories.jsonl+architecture.md+PRD.md,默认data/)。--output FILE:mock GitHub Issue 的落盘路径(默认output/github_issues.json)。--create-issue:经 MCP 在真实仓库创建 Issue(需GITHUB_TOKEN+GITHUB_REPO,见下节;缺失时自动回退 mock)。--no-github:跳过步骤 4,不生成 GitHub Issue。
真实运行输出(节选)¶
诊断阶段,Agent 定位到全部 3 个预置问题:
[问题 1] 未进行退款资格校验
优先级 : P0 模块: order_service PRD: R1
轨迹 : ['T-1001', 'T-1002'] 关键轮次: [3]
[问题 2] 支付重试机制未正确实现
优先级 : P0 模块: payment_service PRD: R2
[问题 3] 库存查询延迟未降级处理
优先级 : P1 模块: inventory_service PRD: R3
回归测试用例被重放框架真正执行(先复现 bug、再验证修复):
(A) 对『线上未修复』系统重放 —— 期望复现 bug(FAIL)
[FAIL] RT-001 (T-1001) 工具 verify_refund_eligibility 缺失
[FAIL] RT-002 (T-1002) process_refund 调用 3 次, 失败 3 次, 末次失败
[FAIL] RT-003 (T-1003) check_stock 最大延迟 8300ms, 阈值 5000ms
(B) 对『修复后』系统重放 —— 期望修复被验证(PASS)
[PASS] RT-001 (T-1001) 工具 verify_refund_eligibility 出现
[PASS] RT-002 (T-1002) process_refund 调用 2 次, 失败 1 次, 末次成功
[PASS] RT-003 (T-1003) check_stock 最大延迟 400ms, 阈值 5000ms
小结:复现 bug 3/3 条;修复后通过 3/3 条。
mock GitHub Issue 打印并写入 output/github_issues.json,示例:
title : [P0][order_service] 未进行退款资格校验
labels : ['module:order_service', 'priority:critical', 'auto-diagnosis']
body : ## 问题描述 ... ## 关联回归测试用例 - RT-001 (轨迹 T-1001 第 3 轮) ...
回归测试断言 DSL(replay 框架内置)¶
Agent 生成的测试用例须使用以下断言之一,框架可自动求值:
step_present{tool}:某工具必须出现(如强制前置校验)。tool_succeeds{tool}:某工具最终成功、且不存在"多次失败后误报成功"。latency_under{tool, threshold_ms}:某工具单次延迟低于阈值。final_status_is{value}:任务最终状态等于给定值。
如何适配/扩展¶
- 换模型:设置
OPENAI_MODEL(或python demo.py --model <名称>)。diagnoser.py默认gpt-5.6-luna,均走 JSON 模式;更强模型对复杂/隐性问题更稳。 - 换供应商:本项目用官方
openaiSDK,只需再设OPENAI_BASE_URL指向兼容 OpenAI 接口的服务(如 Moonshot / 火山方舟 / 本地 vLLM),配合该供应商的OPENAI_API_KEY与OPENAI_MODEL即可,无需改代码。例如: - 换日志:把你自己的生产轨迹按
data/trajectories.jsonl的结构(trajectory_id / task / task_input / turns[] / final_status,turns内含module/tool/input/output/status/latency_ms)落盘替换即可;同时更新data/architecture.md与data/PRD.md作为诊断依据。若轨迹字段不同,sut.py(重放桩)与replay.py(断言求值)按新字段小幅调整。 - 接入真实 GitHub MCP:见下一节,通过
GITHUB_TOKEN+GITHUB_REPO+--create-issue把mock=False接通。
接入真实 GitHub MCP(需 token,默认 mock)¶
本实验默认 mock,--create-issue 才会真正联网。真实创建的实现已内置在
github_mcp._create_issues_via_mcp():通过 MCP 客户端(mcp SDK,stdio)连接官方
GitHub MCP Server,逐个调用其 create_issue 工具,传入 build_issue() 生成的
title / body / labels / assignees。启用步骤:
- 准备一个 GitHub Personal Access Token(
repo权限),写入.env的GITHUB_TOKEN; 并设置目标仓库GITHUB_REPO=owner/repo。 - 确保本机可启动官方 GitHub MCP Server。默认启动命令用官方 Docker 镜像
ghcr.io/github/github-mcp-server;可用GITHUB_MCP_COMMAND覆盖为任意暴露create_issue工具的 MCP Server(token 经GITHUB_PERSONAL_ACCESS_TOKEN注入其环境)。 pip install mcp(仅此路径需要;mock/自检不需要)。- 运行
python demo.py --create-issue。缺少GITHUB_TOKEN/GITHUB_REPO时会打印提示并 自动回退 mock,避免误联网。
局限¶
- 被测系统
sut.py是确定性仿真,用于让回归测试可真正重放、给出稳定的通过/失败;真实场景下重放需对接实际系统或录制/回放的依赖桩。 - 诊断质量取决于 LLM;gpt-5.6-luna 在本数据集能稳定定位全部 3 类预置问题(R1 校验缺失 / R2 重试误报 / R3 延迟未降级),步骤 1 诊断稳定;但它倾向把 R1「校验缺失」按 T-1001、T-1002 各报一条,故常输出 4 条问题(而非上文示例合并成的 3 条)。步骤 2 生成断言时,它稳定地为「支付重试」问题选用
final_status_is:failed(两次实跑均如此)而非上文示例的tool_succeeds——因修复后的被测系统会重试成功(final_status=success),该断言在修复后重放中判 FAIL,使修复后通过数降为 3/4 而非满绿。此外它偶尔给step_present/latency_under的工具名加上模块前缀(如order_service.verify_refund_eligibility),与重放框架按裸工具名匹配不符,会进一步压低修复后通过数(两次实跑分别得到 3/4 与 0/4)。--smoke内置用例则确定性给出 3/3。 - GitHub 创建默认 mock,不联网;
--create-issue才经真实 MCP Server 联网创建(需 token + repo + 可用的 GitHub MCP Server)。 - 轨迹格式为简化示意,生产环境轨迹字段更丰富(token 用量、子 Agent 调用树等)。