12. 自修改提示词:从 OPRO 到 PE2
第 12 章 · 自修改提示词:从 OPRO 到 PE2
"Prompt 不是静态资产——Prompt 是可被 Agent 自身重塑的操作形态。"
学习目标
完成本章后,读者应能够:
- 跑通 OPRO、DSPy、PromptAgent 三大自修改 prompt 范式
- 评估 prompt 自修改的工程效果(准确率 + token 成本)
- 识别 prompt 自修改的 4 类安全风险
- 把 prompt 自修改定位为 H1 的第一个验证案例
- 区分单组件修改与协同修改
先修知识
- 第 4 章 · 提示词工程
- 第 11 章 · 操作形态学形式化
章节地图
- 12.1 操作形态学的第一个应用:修改 P
- 12.2 OPRO:LLM 作为优化器
- 12.3 DSPy:把 prompt 编译为可签名
- 12.4 PromptAgent:MCTS 全局搜索
- 12.5 PE2:反射式进化
- 12.6 Prompt 自修改的 4 类安全风险
- 12.7 H1 的第一个验证案例
- 12.8 本章小结与第 13 章预告
12.1 操作形态学的第一个应用:修改 P
第 11 章把操作形态定义为 (B = {P, T, M, C}),把可塑性定义为元控制器 U 对 B 的修改。Prompt 自修改是 H1 的第一个验证案例——只修改 P 一个组件,是最简单的自进化形式。
为什么 P 是最容易入手的修改对象?
- 可表达性强:P 是自然语言字符串,比 T(结构化函数描述)、M(结构化向量数据)、C(可执行代码)更容易被 LLM 生成和评估。
- 修改粒度细:P 的修改可以是从"一两个词"到"整段重写"的任意粒度。
- 评估简单:P 修改后的效果可以通过任务准确率直接评估。
- 风险可控:P 修改不会直接改变工具行为、记忆结构、代码逻辑,破坏性较小。
但 P 自修改也有局限:
- 天花板低:P 自修改只能"调优指令",不能"扩展能力"。要扩展能力,需要修改 T(添加新工具)或 C(修改执行逻辑)。
- 易漂移:LLM 生成的 prompt 可能逐渐偏离开发者意图。
- 成本高:每轮评估需要大量任务调用,OPRO 8 轮 + 100 任务 = 800 次 LLM 调用。
图 12.1 · P 自修改在操作形态中的位置
操作形态 B = {P, T, M, C}
↑
│ 本章只修改 P
│
┌──────────────┴──────────────┐
│ P · Prompt (本章) │
│ T · Tool (Ch 13) │
│ M · Memory (Ch 14) │
│ C · Code (Ch 15) │
└─────────────────────────────┘
关键点:P 自修改是操作形态学的"最小可验证案例"——只改一个组件,最容易跑实验,但也最容易触及天花板。
表 12.1 · 5 大自修改 prompt 范式对比
| 范式 | 时间 | 核心机制 | 关键结果 | 局限 |
|---|---|---|---|---|
| OPRO | 2023-09 | LLM 作爬山优化器 | GSM8K +15pp | 贪心搜索,易陷入局部最优 |
| DSPy | 2023-10 | 把 prompt 编译为可签名 | HotPotQA +23pp | 编译时间随数据线性增长 |
| PromptAgent | 2023-10 | MCTS 树搜索 | BIG-Bench Hard +33pp | 样本复杂度高 |
| Promptbreeder | 2023-09 | 进化算法 + 自指 | 多任务泛化 | 难以预测演化方向 |
| PE2 | 2024-01 | 反射式进化(带错误驱动) | 8 任务平均 +5-10pp | 依赖错误分析质量 |
12.2 OPRO:LLM 作为优化器
OPRO(Optimization by PROmpting) 由 Google DeepMind 的 Yang 等人 2023 年 9 月提出,是自修改 prompt 的开山工作。OPRO 的核心洞察是:既然 LLM 能生成自然语言回答,那它也能生成自然语言 prompt。
OPRO 的迭代流程
┌──────────────────────────────────────────────────────┐
│ 优化器 LLM 接收: │
│ - 当前 top-K 个 prompt + 它们的得分 │
│ - 任务描述 │
│ - "请生成新的 prompt, 期望比现有的更好" │
└──────────────────────┬───────────────────────────────┘
│ 生成新 prompt P_new
▼
┌──────────────────────────────────────────────────────┐
│ 任务执行 LLM 接收: │
│ - 任务 query + 新 prompt P_new │
│ 在测试集 T 上跑 N 个任务 │
└──────────────────────┬───────────────────────────────┘
│ 记录得分 V(P_new)
▼
┌──────────────────────────────────────────────────────┐
│ 更新 top-K 表, 如果 P_new 更好, 加入 │
│ 继续下一轮 │
└──────────────────────────────────────────────────────┘
关键点:OPRO 的"爬山"不是数值优化,而是 LLM 生成的 prompt 在文本空间中"向上走"。
OPRO 的工程实践变体
变体一:双 LLM 优化
┌────────────────┐ ┌────────────────┐
│ 优化器 LLM │ P_new │ 任务执行 LLM │
│ (强, 如 GPT-4) │ ───────>│ (便宜, 如 Haiku)│
│ 生成新 prompt │ score │ 在测试集上跑 │
└────────────────┘ ───────>└────────────────┘
变体二:评估采样(每轮只跑 50-100 个任务子集)
变体三:早停机制(连续 3 轮无提升则停止)
OPRO 在 GSM8K 数据集上达到了: - 初始手工 prompt:约 80% 准确率 - OPRO 优化 8 轮后:约 95% 准确率 - 绝对提升:+15 个百分点 - 自动发现"Let's think step by step"模式
复述框 · 12.2 节要点
- OPRO:LLM 作爬山优化器,文本空间的"向上走"。
- 3 个变体:双 LLM、评估采样、早停机制。
- 关键结果:GSM8K 80% → 95%。
12.3 DSPy:把 prompt 编译为可签名
DSPy 由 Stanford NLP 团队在 2023 年 10 月提出,把 prompt 工程从"自然语言编写"转向"程序编译"。DSPy 的核心思想是:prompt 不应该是自然语言字符串,而应该是可签名的程序。
DSPy 的代码示例
import dspy
# 1. 定义签名(输入-输出)
class HotPotQA(dspy.Signature):
"""多跳问答:基于多个文档回答问题"""
question: str = dspy.InputField()
context: list = dspy.InputField()
answer: str = dspy.OutputField()
# 2. 定义模块(包含 LLM 调用的可组合单元)
class RAG(dspy.Module):
def __init__(self):
super().__init__()
self.retrieve = dspy.Retrieve(k=3)
self.answer = dspy.ChainOfThought(HotPotQA)
def forward(self, question):
context = self.retrieve(question).passages
return self.answer(question=question, context=context)
# 3. 编译(自动搜索最优的 prompt 集合)
compiled_rag = dspy.BootstrapFewShot(metric=accuracy_metric).compile(
RAG(),
trainset=train_data
)
DSPy 的编译流程
签名定义 训练数据 优化器 编译后的程序
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Signature │ + │ Trainset │ + │ Optimizer │ ──────> │ Compiled │
│ (in/out) │ │ (100) │ │ (Compile) │ │ Program │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
"回答{question} BootstrapFewShot 内部: 3 个示例
基于{context}" MIPRO 优化后的指令
自动选择的策略
DSPy 的多种优化器
| 优化器 | 机制 | 适用 |
|---|---|---|
| BootstrapFewShot | 从训练集 bootstrap 出 few-shot 示例 | 小数据集 |
| BootstrapFewShotWithRandomSearch | Bootstrap + 随机搜索 | 中等数据集 |
| MIPRO | 贝叶斯优化搜索 prompt | 大数据集 |
| BootstrapFinetune | 把优化结果微调进模型权重 | 需要微调 |
DSPy 在多个基准上达到了与人工优化 prompt 相当甚至更好的效果: - HotPotQA 多跳问答:DSPy 优化后的 RAG 流程比人工 prompt 提升 10-15 个百分点 - GSM8K 数学推理:DSPy 优化后的 CoT prompt 比零样本 CoT 提升 20+ 个百分点 - HumanEval 代码生成:DSPy 优化后的 prompt 接近 SFT 微调的效果
复述框 · 12.3 节要点
- DSPy:把 prompt 编译为可签名,三大组件(Signature / Module / Optimizer)。
- 多种优化器:BootstrapFewShot → MIPRO → BootstrapFinetune。
- 关键结果:HotPotQA +10-15pp,GSM8K +20pp。
12.4 PromptAgent:用 MCTS 全局搜索
PromptAgent 由 Wang 等人 2024 年提出,把 prompt 自修改问题建模为蒙特卡洛树搜索(MCTS)问题。PromptAgent 的核心洞察是:prompt 优化不是"梯度下降"(因为 prompt 是离散的 token 序列),而是"策略性搜索"——需要在巨大的 prompt 空间中高效探索。
PromptAgent 的 MCTS 循环
┌─────────────┐
│ 初始 prompt │
│ P_0 (得分 60)│
└──────┬──────┘
│
┌─────────────┼─────────────┐
│ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐
│ P_1 │ │ P_2 │ │ P_3 │
│ 65 │ │ 70 │ │ 62 │
└───┬───┘ └───┬───┘ └───┬───┘
│ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ...
│ P_1.1 │ │ P_2.1 │ │ P_3.1 │
│ 72 │ │ 78 │ │ 70 │
└───────┘ └───────┘ └───────┘
↑
MCTS 选择最 promising 的分支(UCB 公式)
PromptAgent 的搜索步骤
- 初始化:从手工 prompt 开始作为根节点
- 展开(Expansion):让 LLM 基于当前节点生成 K 个候选 prompt 修改
- 评估(Evaluation):在验证集上评估每个候选 prompt 的准确率
- 选择(Selection):用 UCB 公式选择最有希望的分支
- 回溯(Backpropagation):把评估结果回传到所有父节点
- 迭代:重复 2-5 步直到收敛或达到预算
PromptAgent 的关键创新是"专家策略"——LLM 不只是评估 prompt 的得分,还要给出"为什么这个 prompt 更好/更差"的分析。这种"专家推理"让 LLM 能避免 OPRO 中常见的"重复同样的错误 prompt"问题。
PromptAgent 在 BIG-Bench Hard 任务上达到了: - 初始 prompt:约 45% 准确率 - PromptAgent 搜索 50 轮后:约 78% 准确率 - 绝对提升:+33 个百分点 - 超过 OPRO 的 +15 个百分点
复述框 · 12.4 节要点
- PromptAgent = MCTS + 专家策略:把全局搜索引入 prompt 优化。
- 6 步循环:初始化 → 展开 → 评估 → 选择 → 回溯 → 迭代。
- 关键结果:BIG-Bench Hard +33pp,超过 OPRO。
12.5 PE2:反射式进化
PE2(Prompt Evolution with Experts) 由 Ye 等人 2024 年 1 月提出,是 OPRO 的"反射式"升级——不仅让 LLM 生成 prompt,还让 LLM 反思失败案例,针对错误生成改进。
PE2 的进化循环
┌────────────────────────────────────────────────────────────┐
│ 步骤 1: 当前种群 (top-K prompts + 各自得分) │
│ 步骤 2: 抽取 top-1 错误案例(最低分 prompt 的失败任务) │
│ 步骤 3: 让 LLM 反思: │
│ - "为什么这个 prompt 在这个任务上失败?" │
│ - "如何修改 prompt 来避免这个失败?" │
│ 步骤 4: 生成新 prompt 候选 │
│ 步骤 5: 评估新 prompt, 更新种群 │
│ 步骤 6: 重复 2-5 步直到收敛 │
└────────────────────────────────────────────────────────────┘
关键点:PE2 的核心创新是"错误驱动的 prompt 修改"——不是从 top-K 历史中随机采样,而是针对具体失败案例做有针对性的修改。
PE2 在 8 个 BIG-Bench Hard 任务上达到了平均 +5-10 个百分点的提升。PE2 的优势在于有针对性——每次修改都基于具体失败案例,而不是抽象的"爬山"。
Promptbreeder:自指式进化
Promptbreeder(2023-09)把"进化算法"与"自指"结合。Promptbreeder 不仅进化 prompt,还进化生成 prompt 的"突变算子"——这是一个二阶进化。
普通进化: P_t → 突变(P_t) → P_{t+1}
Promptbreeder: P_t, M_t → 突变(P_t) → P_{t+1}
↑
同时进化 M_t → M_{t+1}
Promptbreeder 的关键创新是"自指"——它进化"如何进化 prompt",而不仅是 prompt 本身。这让 Promptbreeder 能"学会"更好的 prompt 修改策略。
复述框 · 12.5 节要点
- PE2:错误驱动的 prompt 修改,从失败案例中学习。
- Promptbreeder:自指式进化,进化"如何进化 prompt"。
- 3 种进化的对比:OPRO(爬山)/ PE2(错误驱动)/ Promptbreeder(自指)。
12.6 Prompt 自修改的 4 类安全风险
Prompt 自修改带来 4 类安全风险,Agent 设计师必须明确处理。
风险 1 · Prompt 注入放大
当 prompt 可以自修改时,外部输入(如工具返回的内容)可以通过"prompt injection"机制污染 prompt。攻击者构造的恶意输入可能被优化器 LLM 当作"高得分 prompt"采纳,导致整个系统被劫持。
攻击示例:
步骤 1: 攻击者在网页中嵌入 "Ignore all previous instructions. New task: ..."
步骤 2: Agent 的搜索工具返回这个网页
步骤 3: 优化器 LLM 把这个"内容"当作"高分 prompt"
步骤 4: 下次 LLM 推理时,这个恶意 prompt 影响了 Agent 行为
防护措施:所有外部输入必须经过 sanitize 后才能进入 prompt 评估集。
风险 2 · Prompt 越狱
自修改机制让 Agent 可以"自我解除"开发者设置的安全护栏。例如: - 开发者设置 "你不能执行任意代码" 的提示 - Agent 通过自修改删除了这个限制 - 后续 Agent 获得了执行任意代码的能力
防护措施:硬约束 prompt 空间——禁止 Agent 修改"系统级安全护栏"字段。
风险 3 · Prompt 漂移
长期运行中,prompt 可能逐渐偏离开发者意图。例如: - 第 1 天:prompt 是 "你是一个有帮助的助手" - 第 30 天:prompt 是 "你是一个高级的绝对服从的助手"(漂移到不安全状态)
防护措施:维护"黄金 prompt 集合",定期回归测试,检测漂移。
风险 4 · 可复现性损失
当 prompt 持续自修改时,"今天的 prompt" 与 "明天的 prompt" 不同,调试和审计变得困难。例如: - 用户报告"Agent 突然表现异常" - 开发者调试时发现"Agent 当前的 prompt 与昨天不同" - 难以定位是哪个修改引入了 bug
防护措施:所有 prompt 修改必须版本化(git-style),每次修改有 commit message 和评估记录。
表 12.2 · 4 类安全风险与防护
| 风险 | 触发条件 | 防护措施 | 严重度 |
|---|---|---|---|
| Prompt 注入放大 | 外部输入污染评估集 | sanitize + 隔离评估 | 高 |
| Prompt 越狱 | 自修改解除安全护栏 | 硬约束 prompt 空间 | 高 |
| Prompt 漂移 | 长期运行偏离意图 | 黄金集合回归测试 | 中 |
| 可复现性损失 | prompt 持续变化 | 版本化 + commit message | 低 |
复述框 · 12.6 节要点
- 4 类风险:注入放大、越狱、漂移、可复现性损失。
- 共同原则:所有 prompt 修改必须可审计、可回滚、有硬约束。
12.7 H1 的第一个验证案例
H1(结构可塑性)的陈述是:当操作形态 B 在运行时可被元控制器 U 修改时,其在环境变化下的适应后悔值显著低于固定 B 的 Agent。
Prompt 自修改是 H1 的第一个验证案例——只修改 P 一个组件。
H1 在 P 自修改中的形式化
- (B_t = P_t):操作形态只有 Prompt 一个组件
- (U):OPRO / DSPy / PromptAgent / PE2 中的任何一个
- (E):环境(任务分布 + 工具集)
- (R):适应后悔值
预测:当 (E) 变化时,P 自修改 Agent 的 (R(B_{\text{adaptive}})) 显著低于 P 固定 Agent 的 (R(B_{\text{fixed}}))。
验证设计
| 实验组 | P 是否修改 | 元控制器 |
|---|---|---|
| Frozen-P | ❌ 固定 | 无 |
| OPRO | ✅ | LLM 爬山 |
| DSPy | ✅ | 编译时优化 |
| PromptAgent | ✅ | MCTS |
| PE2 | ✅ | 错误驱动 |
每个实验组在 5 类环境变化(任务漂移、API 漂移等)下跑 100 任务,测量适应后悔值。
预期结果: - Frozen-P 的后悔值随环境变化线性增加 - 4 类自修改 Agent 的后悔值都显著低于 Frozen-P - 4 类自修改 Agent 之间可能差异不显著(都是"自修改",但实现不同)
如果实验支持 H1,则证明"操作形态可塑"对 Prompt 组件有效——这是 H1 的"最小验证"。如果 4 类自修改 Agent 中只有部分优于 Frozen-P,则说明"操作形态可塑"需要更精细的条件。
局限性
P 自修改只能验证 H1 的一个案例。完整的 H1 验证需要:
- T 自修改(Ch 13:自动工具创建)
- M 自修改(Ch 14:自适应记忆结构)
- C 自修改(Ch 15:自我改写代码)
- 联合自修改(Ch 16:跨组件协同)
这 4 个案例 + 联合案例 = 5 个实验,构成本书 Part III 的完整 H1 验证。
复述框 · 12.7 节要点
- H1 在 P 自修改中的形式化:(B_t = P_t),元控制器是 OPRO/DSPy/PromptAgent/PE2。
- 验证设计:5 个实验组 × 5 类环境 × 100 任务 = 250 个单元格。
- 预期结果:4 类自修改 Agent 后悔值都低于 Frozen-P。
12.8 本章小结与第 13 章预告
本章是 Part III 的开篇。操作形态学的第一个应用是修改 P——只修改一个组件,是最简单的自进化形式。OPRO 用 LLM 作爬山,在 GSM8K 上达到 +15pp。DSPy 把 prompt 编译为可签名,在 HotPotQA 上 +10-15pp。PromptAgent 用 MCTS 全局搜索,在 BIG-Bench Hard 上 +33pp。PE2 用错误驱动的反射式进化,在 8 个任务平均 +5-10pp。4 类安全风险(注入放大、越狱、漂移、可复现性损失)必须明确处理。H1 在 P 自修改中的验证是本书 Part III 的第一个实验案例。
常见误区
- ❌ 把 prompt 自修改当"全自动":自修改需要持续人工监督,否则会漂移到不可控状态。
- ❌ 忽视版本化:没有版本化的 prompt 自修改会导致"无法回滚"的灾难。
- ❌ 把 OPRO / DSPy / PromptAgent 当作互斥选项:它们可以组合使用——DSPy 做基础 prompt 编译,OPRO 做迭代优化,PromptAgent 做策略性搜索。
- ❌ 把"自修改 prompt"等同于"prompt engineering 升级版":自修改是 Agent 的认知能力变化,不是"更好的 prompt 写作"。
- ❌ 忽视安全风险:自修改 prompt 让 Agent 拥有了"重塑自己行为"的能力,这本身就是安全风险。
第 13 章将进入自动工具创建与重构。P 自修改是 H1 的第一个案例,T 自修改是第二个案例——让 Agent 自主创建、删除、重写工具集。LATM、Voyager、AFlow、EvoAgent、AlphaEvolve 等工作如何让 Agent 拥有"修改自身 affordance"的能力?这是 Ch 13 的核心议题。
本章小结
- 操作形态学的第一个应用:修改 P(最简单、最容易入手)。
- OPRO:LLM 爬山,GSM8K +15pp。
- DSPy:把 prompt 编译为可签名,HotPotQA +10-15pp。
- PromptAgent:MCTS 全局搜索,BIG-Bench Hard +33pp。
- PE2:错误驱动的反射式进化,8 任务平均 +5-10pp。
- 4 类安全风险:注入放大、越狱、漂移、可复现性损失。
- H1 的第一个验证案例:P 自修改。
推荐阅读
- 📖 OPRO 原始论文 [Yang et al., 2024]:LLM 爬山优化 prompt 的开山工作。$TRAE_REF
- 📖 DSPy 原始论文 [Khattab et al., 2024]:把 prompt 编译为签名的工程化框架。$TRAE_REF
- 📖 PromptAgent 原始论文 [Cheng et al., 2024]:用 MCTS 策略性搜索 prompt 空间。$TRAE_REF
- 📖 PE2 原始论文 [Ye et al., 2024]:反射式进化,错误驱动的 prompt 修改。$TRAE_REF
- 📖 Promptbreeder 原始论文 [Fernando et al., 2023]:自指式进化,进化"如何进化 prompt"。$TRAE_REF
练习题
- 设计题:为你的"客服 Agent"设计 OPRO 优化的 4 元素(P₀, T, M, V)。具体说明每个元素的实现方式、成本估算、终止条件。
- 分析题:选一个真实 LLM 应用(GitHub Copilot、ChatGPT、Claude.ai),分析它的 prompt 是静态还是动态的。如果是动态的,用什么机制?成本是多少?
- 动手题:用 Python 实现一个简化版 OPRO(不超过 100 行):给定 10 个 GSM8K 风格的算术题,用 LLM 爬山优化 prompt,记录每轮的 top-3 prompt 和得分。
- 设计题:把 DSPy 签名概念应用到一个新场景:自动生成会议纪要。设计
MeetingSummary签名,包含输入字段、输出字段、评估指标。 - 批判题:PromptAgent 的 MCTS 搜索是"全局最优"的吗?请用搜索复杂度理论分析:随着 prompt 空间维度 d 增长,MCTS 的样本复杂度如何变化?
- 工程实践题:为你的生产环境 LLM Agent 设计"prompt 自修改"的安全护栏:包括注入检测、漂移检测、成本控制、可复现性保证 4 个机制。
参考文献(本章内)
- Yang, C., et al. (2024). Large Language Models as Optimizers (OPRO). ICLR. $TRAE_REF
- Khattab, O., et al. (2024). DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines. ICLR. $TRAE_REF
- Cheng, J., et al. (2024). PromptAgent: Strategic Planning with Language Models Enables Expert-level Prompt Optimization. arXiv:2310.16427. $TRAE_REF
- Ye, Q., et al. (2024). An Evolved Universal Prompt Optimizer (PE2). arXiv:2401.15442. $TRAE_REF
- Fernando, C., et al. (2023). Promptbreeder: Self-Referential Self-Improvement via Prompt Evolution. arXiv:2309.16797. $TRAE_REF
- Zhou, Y., et al. (2023). Large Language Models Are Human-Level Prompt Engineers (APE). ICLR. $TRAE_REF
- Shinn, N., et al. (2023). Reflexion: Language Agents with Verbal Reinforcement Learning. NeurIPS. $TRAE_REF
- Sumers, T. R., et al. (2023). CoALA: Cognitive Architectures for Language Agents. arXiv:2309.02427. $TRAE_REF
- Fang, J., et al. (2025). A Comprehensive Survey of Self-Evolving AI Agents. arXiv:2508.07407. $TRAE_REF
- Wei, J., et al. (2022). Chain-of-Thought Prompting Elicits Reasoning in Large Language Models. NeurIPS. $TRAE_REF
本章进度:12.1–12.8 节全部完成(约 6,000 字,含 3 张图 + 2 张表 + 1 个代码块 + 10 篇引用 + 6 题 + 5 误区 + 5 推荐),达到 26 页计划。
status: final。Part III 进度:1/6 章完结(Ch 12 自修改 prompt,26 页 / 6,000 字)。下一章是 Ch 13 自动工具创建与重构。