源文件:chapter8/prompt-auto-optimization/README.md 实验 8-3:系统提示词的自动优化(★★) 《深入理解 AI Agent》配套代码 · 第 8 章 基于人类反馈的 自动化系统提示学习:让一个 Coding Agent 读取系统提示词文件、 定位有问题的规则、生成精确修改并 真的改写 prompt 文件,从而修复 Agent 的 "过度转接" 行为。场景为 tau-bench 风格的航空客服。 目的与问题 初始的航空客服 Agent 里,人工转接规则写得很含糊——"仅当请求无法在你的行动范围内 处理时才转接",并且强调"客户满意度第一,遇到不满就转人工,不要与乘客争辩政策"。
源文件:chapter8/prompt-auto-optimization/README.md
《深入理解 AI Agent》配套代码 · 第 8 章
基于人类反馈的 自动化系统提示学习:让一个 Coding Agent 读取系统提示词文件、
定位有问题的规则、生成精确修改并 真的改写 prompt 文件,从而修复 Agent 的
"过度转接" 行为。场景为 tau-bench 风格的航空客服。
初始的航空客服 Agent 里,人工转接规则写得很含糊——"仅当请求无法在你的行动范围内
处理时才转接",并且强调"客户满意度第一,遇到不满就转人工,不要与乘客争辩政策"。
评测发现:Agent 过度转接——一遇到政策争议(要求超政策退款、要求免费、要求豁免
费用)就直接甩给人工,而不尝试向乘客解释政策。
人类专家反馈:这类争议应当 通过耐心解释政策来处理,而不是一转了之。真正需要转
人工的只有两种情况:乘客明确要求人工客服、紧急安全/人身健康风险。
本实验演示一条自动化闭环:人类反馈 → Coding Agent 改写系统提示词 → 重新评测验证。
初始 prompt ──评测──► 暴露"过度转接"问题 │ 人类反馈 ───┤ ▼ Coding Agent(读文件→定位规则→生成精确 search/replace 编辑→改写文件) │ 展示真实 diff ▼ 自动优化后 prompt ──评测──► 边界集正确率↑ 且 保留集不退化 │ 对照:人工调优版 prompt ──评测──►
两组评测用例(各 5 个,控制成本、结论可复现):
判据(evaluate.py):结合确定性规则 + LLM-as-judge——
transfer_to_human;Coding Agent(coding_agent.py)不整篇重写,而是像真实编程 Agent 一样产出一组(old_str → new_str) 精确编辑,由代码逐条做精确字符串替换落盘;匹配不上就把错误反馈
给模型重试,保证修改可审计、可出 diff。
| 文件 | 说明 |
|---|---|
demo.py |
一条命令跑通完整流程(评测→改写→复评→对照→对比表) |
airline_env.py |
精简航空客服模拟环境:工具(含 transfer_to_human)、Agent 循环、10 个用例 |
coding_agent.py |
Coding Agent:读取并 改写 系统提示词文件,输出 diff |
evaluate.py |
评测器:规则 + LLM-as-judge 判定每个用例是否被正确处理 |
config.py |
LLM 客户端配置(默认 OpenAI gpt-5.6-luna,可切 Moonshot / 火山方舟;缺 Key 时 OpenRouter 兜底) |
prompts/system_prompt.txt |
初始系统提示词(含会诱发过度转接的规则) |
prompts/system_prompt_manual.txt |
对照组:人工调优版系统提示词 |
runtime/system_prompt_working.txt |
运行时由 Coding Agent 改写的工作副本(每次运行重置) |
pip install -r requirements.txt cp env.example .env # 填入 OPENAI_API_KEY(或仅设 OPENROUTER_API_KEY 走兜底) python demo.py # 完整运行:10 个用例 × 3 份 prompt python demo.py --quick # 快速演示:每组只取 2 个用例,省时省钱(推荐先跑这个) python demo.py --help # 查看全部命令行参数(中文说明) python demo.py --dry-run # 离线自检:只打印配置与选中用例,不调用任何 API
命令行参数(python demo.py --help 可见完整中文说明):
| 参数 | 作用 | 默认 |
|---|---|---|
--quick |
每组只取 2 个用例,省时省钱 | 关闭 |
--limit N |
每组最多评测 N 个用例(覆盖 --quick) |
不限 |
--group {holdout,boundary,both} |
选择评测的任务集 | both |
--rounds N |
Coding Agent 自动改写提示词的最大重试轮数 | 3 |
--model NAME |
覆盖 LLM 模型名(等价于 LLM_MODEL) |
见 config.py |
--provider {openai,moonshot,ark} |
覆盖 LLM 提供商(等价于 LLM_PROVIDER) |
openai |
--output PATH |
把优化前后 + 人工对照的对比结果写成 JSON | 不写 |
--dry-run |
离线:只打印解析后的配置与用例数,不调用 API | 关闭 |
默认模型 gpt-5.6-luna(读取 OPENAI_API_KEY;缺失时若有 OPENROUTER_API_KEY 则自动改走 OpenRouter 并映射到 openai/gpt-5.6-luna),温度 0(结果可复现)。完整运行跑
10 个用例 × 3 份 prompt,约几十次 API 调用、数分钟;--quick(或 --limit N 指定每组
用例数)会显著缩短耗时,用于快速验证闭环。命令行参数优先级高于环境变量:--model /--provider 会覆盖 .env 中的 LLM_MODEL / LLM_PROVIDER。加 --output output/run.json
可把对比表落盘为 JSON(output/ 已被 .gitignore 忽略),便于复现与二次分析。若未设置
对应 API Key,程序会打印清晰的中文错误提示并退出,而不是抛出堆栈。
优化后的工作副本会写入 runtime/system_prompt_working.txt(每次运行自动重置,属生成
工件,已被 .gitignore 忽略)。
下表为一次真实运行(gpt-5.6-luna,完整 10 用例)的结果:
正确率对比(保留任务集 = 既有正确行为不能退化;边界案例集 = 过度转接应改善) ========================================================================== 系统提示词版本 保留任务集(holdout) 边界案例集(boundary) -------------------------------------------------------------------------- 初始 prompt(优化前) 5/5 (100%) 0/5 (0%) 自动优化后 prompt 5/5 (100%) 1/5 (20%) 人工调优版(对照) 5/5 (100%) 2/5 (40%) ========================================================================== 【结论】 · 边界案例集正确率:0/5 → 1/5 (提升 ✓) · 保留任务集正确率:5 → 5 (未退化 ✓)
注:具体数字可能随模型版本与采样有 ±1 个用例的波动,但"边界集过度转接被修复、保留集不退化、
且与人工调优接近"的结论稳定可复现。上表为gpt-5.6-luna的一次真实运行(因该模型仅支持默认
温度,本次以LLM_TEMPERATURE=1运行)。
Coding Agent 对 system_prompt.txt 的真实改写(diff 节选)会在 python demo.py 的
【步骤 2】中打印,核心是把第 3、4 条转接规则收紧为"仅乘客明确要求人工 / 紧急安全才转",
并新增负面规则"绝不因政策争议或乘客不满而转接,应先解释政策再给替代方案"。
一个自然的问题:模型更强,这套"自动改 prompt"的脚手架是不是就不那么必要了?
为此我们把完全相同的闭环(10 用例 × 3 份 prompt × 最多 3 轮改写)在一个较弱模型gpt-4o-mini(OpenAI 直连,LLM_TEMPERATURE=0)上又真实跑了一次,与上文gpt-5.6-luna 的运行对照。边界案例集(过度转接应改善)的优化前 → 自动优化后变化:
| 模型 | 保留集(holdout) | 边界集 优化前 → 自动优化后 | 自动优化增益 | 人工调优版(对照) |
|---|---|---|---|---|
gpt-4o-mini(较弱) |
5/5 → 5/5(未退化) | 1/5 → 3/5 | +2 个用例 | 3/5 |
gpt-5.6-luna(较强) |
5/5 → 5/5(未退化) | 0/5 → 1/5 | +1 个用例 | 2/5 |
gpt-4o-mini 从这套自动优化脚手架里拿到的增益更大(边界集 +2 个用例,gpt-5.6-luna 的 +1(0/5→1/5);且优化后 gpt-4o-mini 已追平其人工调优版temperature=0(确定性),temperature=1(有采样噪声)。因此这是一次方向性、非结论性的LLM_PROVIDER 可切换 openai / moonshot / ark(均兼容 OpenAI 接口),LLM_MODEL 覆盖模型名,LLM_TEMPERATURE 调采样温度(默认 0,见 config.py / env.example)。airline_env.py 的 CASES(分 holdout / boundary 两组);demo.py 顶部的 HUMAN_FEEDBACK;初始与人工对照 prompt 在 prompts/ 下——