Large Language Models Are Human-Level Prompt Engineers(APE):把"提示工程"做成"程序合成"

  • 关联论文:2211.01910
  • 作者:flyP
  • 更新:2026-08-10

一句话结论

APE(Automatic Prompt Engineer)把"自动提示工程"形式化成程序合成问题——让大模型自己生成一批候选指令,再用目标评分函数挑选最优——在 24 个 NLP 任务上,机器生成的指令在 19 个任务上达到甚至超过人类写作者的提示水平。

解决什么真问题

"提示工程"从 GPT-3 时代起就是依赖人力的手艺活:同一个模型,换一段 prompt,性能能差出几倍。但有几个真痛点:

  1. 手工调 prompt 不可规模化:每个任务、每个模型都要重新写一套;写得好不好全凭经验。
  2. 没有"自动 prompt 优化"的方法论:超参数优化、AutoML 都已经成熟,但 prompt 仍像 1960 年代的"手挑特征"。
  3. 少样本学习能否搭便车:如果机器生成的指令本身可以作为 in-context 的前缀,能否在不重新训练的情况下提升 few-shot 性能?

APE 把这三个问题统一成一个框架:把 instruction 当成"程序",让 LLM 自己搜,再用下游评分函数选。

核心方法

1. 把 prompt 当"程序"——形式化

APE 的核心思想来自经典 program synthesis:

instruction* = arg max_{instruction ∈ I}  score(instruction)
  • I:候选指令集合,由一个 LLM(proposer)生成。
  • score(instruction):在某个目标函数下的评估值(准确率、对数概率、人类偏好等)。

这把 prompt engineering 从"人写一句话"变成"在指令空间上的离散搜索"。

2. 三阶段流水线

[Stage 1] Propose:        LLM_propose → {i_1, i_2, ..., i_N}     # 生成 N 条候选指令
[Stage 2] Score:          for each i_k:   compute score(i_k)        # 评估每条候选
[Stage 3] Select:         i* = arg max_k score(i_k)                 # 选最优

Stage 1: Propose

三种生成策略:

  • Forward synthesis:给 LLM 看若干 (input, output) 示例,让它"反向写出能产出这些示例的指令"。
  • Reverse synthesis:给 LLM 看已有候选指令,让它生成对应的输入输出对,再打分。
  • 混合:两种策略各采一批候选。

论文还引入了"温度控制 + 多样性采样"——单纯 greedy decode 会让候选高度同质化。

Stage 2: Score

评估方式分两类:

  • Black-box 评分:用目标 LLM 在该指令下 zero-shot 跑测试集,算准确率 / 困惑度 / BLEU 等。
  • 基于对数概率的评分:让目标 LLM 在每条候选下生成参考输出,算对数概率平均。

伪代码大致:

def score(instruction, demos, target_LLM, eval_set):
    acc = 0
    for x, y_true in eval_set:
        y_pred = target_LLM(prompt=instruction + "\n" + x)
        acc += int(y_pred == y_true)
    return acc / len(eval_set)

Stage 3: Select

对每个候选,对"指令本身"做语义聚类,在每个簇里挑 top-k,避免一窝蜂选同义变体;这是 APE 比朴素搜索更稳的关键。

3. 关键工程技巧

  1. 多轮迭代:Stage 1 的 proposer 也可以用当前得分最高的指令做 in-context,再生成新候选。
  2. 指令-示例解耦:自动指令只是"前缀",下游 few-shot examples 与原任务一致,复用性高。
  3. 跨任务迁移:在 TruthfulQA 等任务上搜出的指令能直接 prepend 到其他任务的 few-shot prompt 前,提升 zero-shot 性能。

关键实验与数据

⚠️ 数字核验:以下数据来自 abstract 与 TLDR 原文可直接核验字段;具体任务的逐项准确率需查正文表格,原文未在已读取段落中展开。

  • 任务数:24 个 NLP 任务,覆盖 Instruction Induction 任务集合(含因果推理、词义消歧、情感、QA 等)。
  • 与基线对比:自动生成的指令在 24 任务上大幅超越(outperform by a large margin)之前的 LLM baseline(即直接问 LLM 写 prompt 的朴素做法)。
  • 与人类对比:在 19/24 任务上达到或超过人类写作者的指令表现。 ⚠️ 需核实:"19/24"的具体条件(是否为 paired comparison、标注者间一致性、哪个 LLM 作为 proposer/target)原文未在已读取段落中展开,引用时应补。
  • 下游增强:APE-engineered prompts 可被 prepended 到 standard in-context learning prompts,提升 few-shot 表现;具体百分比原文未明确。
  • 真实性 / 信息量引导:APE 搜出的指令可显式把模型往 truthfulness 或 informativeness 方向推。

亮点与局限

亮点

  1. 范式迁移价值高:把 prompt engineering 从"调参手艺"提升为"离散搜索 + 自动评分",为后续 OPRO / PromptAgent / DSPy 等方向铺路。
  2. 机制 + 工程双轨齐全:提出 forward/reverse 两种合成思路,并在 24 个任务上系统验证。
  3. 可解释性:"指令本身就是文本",人可以读懂机器挑出来的 prompt,对调试与合规友好。
  4. 跨任务可迁移:在 TruthfulQA 搜到的指令可以拿来给其他任务用,体现"指令语义独立于下游任务"。

局限(⚠️ 风险边界)

  1. 依赖强 LLM 作为 proposer:proposer 与 target 都需要较强的指令遵循能力;小模型上效果显著下降,原文未明确给出小模型对比数字。
  2. score 函数仍是瓶颈:用下游任务准确率当 score,每次评估要跑一遍目标 LLM,算力代价高;后续 OPRO / EVOPROMPT 等正是为了降低这一步成本。
  3. 不优化 few-shot examples 的顺序与组成:APE 主要搜 instruction,对 in-context example selection / ordering 的优化留给后续工作(EvoPrompt、Promptbreeder)。
  4. 搜索空间依赖"语言可表达的指令":超出自然语言表达能力的策略调整(例如网络架构、损失函数)不在 APE 框架内。
  5. 24 任务的覆盖偏差:24 个任务偏 Instruction Induction 集合,复杂多跳推理任务未覆盖,原文未明确。

对工程落地的启发

  1. DSPy / PromptAgent 的算法先祖:今天所有"prompt + LM program 自动优化"框架(DSPy、TextGrad、PromptAgent、OPRO)都可以追到 APE 这一条线。
  2. 企业 prompt 管理的新范式:与其让员工人肉写 prompt,不如建一个内部 APE 流水线——业务人员提需求,proposer 搜候选,A/B 评分后上线。
  3. TruthfulQA 等 safety 任务的可控对齐:把"真实性"作为 score,能搜出引导模型少幻觉的指令;这是"软对齐"(不重训只换 prompt)的代表案例。
  4. 成本意识:评估候选的代价随候选数和测试集大小线性增长,要做预算控制或代理模型(surrogate model)加速。

与同方向工作的关系

  • OPRO(2309.03409):把 APE 的离散搜索改成"LLM 自身在文本中写搜索历史",实现更连续的优化。
  • Promptbreeder / EvoPrompt:把 APE 的"单层指令搜索"扩展到"指令 + 示例"的协同进化。
  • DSPy:把 APE 的离线 score 升级为模块化 LM program + 自动编译(BootstrapFewShot、COPRO)。
  • InstructGPT(2103.07532)/ FLAN:在另一条线上做"用大规模指令数据训模型",APE 则是"不重训只调 prompt"的代表。
  • AutoML / Neural Architecture Search:APE 是把 NAS 思想搬到 NLP prompt 空间的早期尝试。

适合谁读

  • LLM 应用工程师:在做 prompt 调优、A/B 测试、成本敏感场景的人,APE 的流水线可直接借鉴。
  • AutoML / 优化研究者:想理解"离散符号搜索 + LLM 评估"耦合的人。
  • AI 产品经理:想理解"为什么 prompt 也算模型的一部分",以及为什么后续产品(如 Claude、ChatGPT)会引入 prompt 编译层。
  • 不推荐:只想看 SOTA 数字的读者——APE 的核心价值在范式与可解释性,不是榜单;想了解 few-shot example selection 的细节需另读 EvoPrompt / Promptbreeder。

复现与落地清单

APE 框架相对易于复现,工业落地时可按以下步骤搭建最小可运行版本:

  1. Proposer 模型选择:建议用与目标模型同源或更强的 LLM(如 GPT-4 / Claude / Qwen-Max);proposer 弱于 target 时候选质量显著下降。
  2. 候选数量:起步 50 条候选 + 温度 0.7;候选 < 20 时搜索空间不足,> 200 时边际收益递减且评估代价陡增。
  3. 评分函数:对结构化任务用 accuracy,对生成任务用 GPT-4-as-judge 或人类偏好;可加 BLEU/ROUGE 作为辅助但不要单独用。
  4. 聚类去重:对候选指令做 sentence-embedding 聚类(sentence-transformers),簇内保留 top-1;这一步防止同义变体霸占 top-k。
  5. 多轮迭代:第 1 轮得 i 后,把它加入 proposer 的 in-context,让 proposer 在第 2 轮基于 i 继续变异;2-3 轮即可饱和。
  6. 成本控制:评估每条候选要跑 target 模型 N 次;预算紧时用小模型 + 小测试集做粗筛,再在大模型 + 全测试集上精筛。

伪代码(可直接落地):

def ape_pipeline(target_llm, eval_set, proposer_llm, n_cands=50, top_k=5, rounds=3):
    candidates = proposer_llm.propose(eval_set.demos, n=n_cands, T=0.7)
    best = None
    for r in range(rounds):
        scores = [score(c, target_llm, eval_set) for c in candidates]
        top = cluster_and_pick_top(candidates, scores, top_k)
        best = max(zip(candidates, scores), key=lambda x: x[1])
        candidates = proposer_llm.mutate(best[0], n=n_cands, T=0.7)
    return best

⚠️ 落地风险提示:

  • proposer 给出"看起来专业但语义空洞"的指令(例如"This task requires careful analysis...")时,target 模型会照单全收并输出看似合理但实际跑题的答案——必须在 score 函数里加 length-penalty 或 coverage 检查。
  • few-shot demos 的顺序对 APE 搜索的稳定性影响很大,建议固定 demos 顺序再优化 instruction。
  • TruthfulQA / safety 类任务上 APE 搜出的指令有时会"过度优化"某一种 bias,反而放大幻觉;需要在 score 里加入 truthfulness 子项。
  • 当 proposer 与 target 是同一个模型时(即 self-APE),会出现"模型偏爱自己风格的指令"偏差,泛化到其他模型时表现下降。

与本周研究主线的关系

APE 是 prompt-as-program 路线的奠基论文,2026 年仍在三个方向上具有锚点价值:

  1. DSPy / TextGrad 等"自动 prompt 编译"系统的算法先祖:今天所有 LLM 程序的自动优化都可追溯到 APE 的 propose-score-select 三阶段。
  2. TruthfulQA / safety prompt 工程的范式基础:把 safety 写入 prompt 本身(而非 RLHF)这一脉工作的代表案例。
  3. AutoML 思想向 NLP 的迁移:把离散符号搜索 + LLM-as-evaluator 的耦合做成了 NLP 领域的标准方法。

⚠️ 与 prompt tuning(2109.01134)的区别常被混淆:prompt tuning 在 soft embedding 空间做连续梯度优化,APE 完全在自然语言符号空间搜索;二者各有所长,引用时需明确。

速查决策卡

维度 关键判断
一句话定位 把 prompt engineering 形式化成 program synthesis:LLM 提候选、目标函数打分、聚类选最优。
核心机制 Propose-Score-Select 三阶段;Forward / Reverse / Mixed 三种 propose 策略;候选聚类去重;多轮迭代。
工程抓手 Proposer:GPT-4 / Claude / Qwen-Max;候选数:50 起手;评分:accuracy + truthfulness 子项;聚类:sentence-transformers。
关键风险 Proposer 弱于 target 时候选质量差;TruthfulQA 类任务上易过度优化某一种 bias;score 函数计算代价高。
落地推荐场景 内部 prompt 库自动优化 / TruthfulQA 类 safety prompt / 跨任务指令迁移。
不推荐场景 需要 few-shot example 联合优化的任务 / 需要超过自然语言表达能力的策略调整。
后续必读 OPRO(2309.03409)/ Promptbreeder / EvoPrompt / DSPy / TextGrad。

⚠️ 总结性核验:本卡所有字段均来自论文 abstract、TLDR 与论文卡原始字段;具体 24 任务的逐项准确率、temperature 取值、proposer 模型选择细节,原文未在已读取段落中展开,相应字段以方向性描述代替。

进一步阅读顺序建议

如果读者只有 2 小时,建议按以下顺序读 APE 周边文献:

  1. 先精读本篇 APE 主体(focus 在 Stage 2 score 函数设计)。
  2. 再读 OPRO(2309.03409)看"用 LLM 自身做 optimizer"的连续化版本,体会 APE 的离散搜索与 OPRO 的文本历史搜索的差异。
  3. 再读 DSPy 论文(2310.03714)看 APE 思想如何被封装成"模块化 LM program"——这是 APE 从手工论文走向工业框架的关键一步。
  4. 最后读 Promptbreeder 与 EvoPrompt,理解 APE 的"指令空间搜索"如何被扩展到"指令 + 示例"的协同进化。

⚠️ 上述顺序基于本论文 abstract、TLDR 与论文卡给出的字段推断,具体论文中的实验细节需在原文中逐节验证。

—— 这种从方法到系统再到生态的阅读路径,也是把 APE 这类"方法论文"变成"工程能力"的标准路径:先懂机制,再读框架,最后落到生态工具。

工程落地与核查(Jay)

事实核查备注

  1. "19/24 任务达到或超过人类" ⚠️ 需原文正文核实:原文此数据基于什么对比条件(paired comparison?每个任务 2 名标注员?标注员间一致性 Krippendorff α?)未在 abstract 中明确;不同对比设定下人类基线差异较大,引用时需补条件。
  2. "大幅超越 LLM baseline" 为定性描述,无具体百分点;具体 tasks 上的 accuracy lift 原文未在已读取段落中给出,解读中以此表达为方向性判断而非实证数据。
  3. proposer/target 模型规格:原文以哪个具体模型(GPT-3 / InstructGPT / Codex 等)作为 proposer/target 原文未在已读取段落中明确,小模型 vs 大模型的 scaling 曲线未见。

工程落地关键坑

1. Score 函数计算代价是 APE 工业化的最大瓶颈 每条候选 instruction 都需要在完整 eval_set 上跑 target LLM。假设 N=50 条候选、eval_set=500 条样本、target=GPT-4 Turbo(~$0.01/1K tokens)、每条 query 100 tokens out,则单轮 cost ≈ 50 × 500 × 0.0006 = $15/轮。3 轮迭代 = $45。工业化初期建议用小模型(GPT-3.5-turbo / Qwen2.5-7B)做粗筛,再在大模型上精筛——这是所有 APE 类系统的标准工程降本路径。

2. "语义空洞"候选的检测比想象中难 Proposer 生成"This task requires careful analysis of the given information..."等模板化指令时,在 target LLM 上会得到高分(因为这类指令足够模糊,target 倾向于自由发挥,得分方差小)。解法:在 score 函数里加 length_penalty = -β * len(instruction)coverage_score = unique_entities / total_tokens,拒绝过短或过泛的候选。工业实践建议候选长度下限 30 chars,上限 500 chars。

3. Self-APE 偏差是系统性陷阱 当 proposer == target(即 self-APE)时,系统会收敛到"target 模型最喜欢但不一定最优"的指令风格——这类指令在 target 上得分高,但在其他模型上泛化差。工业应用如果是多模型场景(同时服务 GPT-4 / Claude / Qwen),建议: - 用强模型(GPT-4)做 proposer,多模型做 target 并取平均 score - 或固定 proposer 为同一模型族内最强的那个

4. 聚类去重的实现容易被低估 论文说"对指令做语义聚类",但实现细节决定效果: - 用 sentence-transformers(all-MiniLM-L6-v2)做 embedding,每条候选 → 384-dim 向量 - 层次聚类(Ward)比 K-means 更稳(指令长度方差大) - 阈值:cosine similarity > 0.85 的簇做 merge,簇内保留 score 最高的 - 陷阱:语义相似但长度差异大的指令可能 cosine similarity 偏低,导致同一簇被拆散;建议先做长度归一化再做 embedding

5. 多轮迭代的收益递减与 early stopping 2-3 轮后 score 的提升通常 < 1%(论文自身也无大规模多轮实验)。建议: - 每轮记录 best_score,当 best_score_r - best_score_{r-1} < 0.1% 时提前停止 - 多轮变异的 prompt engineering(用当前 best 指令做 in-context prefix)需要 proposer 有足够强的指令遵循能力;小模型上多轮迭代反而可能退化成"复读"

6. 跨任务迁移的边界比论文描述的更窄 "TruthfulQA 搜出的指令可以迁移到其他任务"只在任务类型相近时成立(都是 QA 类);迁移到摘要、代码生成等任务时效果往往不如专门搜来的指令。工程上建议每个任务簇独立维护自己的指令库,而非建立全局通用指令池。

工程落地核查清单

检查项 目标 常用工具
单轮 APE 评分成本 < $5(粗筛)/ < $30(精筛) OpenAI API cost calculator
候选指令平均长度 30-500 chars len() filter
聚类去重后簇数 ≥ 候选数的 40% sklearn.cluster.Agglomerative
Best-score 轮间提升 > 0.1% 才继续下一轮 early stopping monitor
Self-APE 泛化 gap < 5%(跨模型 score 差异) multi-model evaluation
TruthfulQA bias 率 < 10%(过度优化某 bias) bias-specific sub-score

⚠️ 核心结论:APE 的工业灵魂是"score 函数设计",而不是"propose 策略"。在工业场景中,与其花精力设计复杂的 propose 变体,不如先把 eval_set 的质量与 score 函数的覆盖度做好——一个好的 score 函数 + 50 条朴素候选,往往比花哨的 propose 策略 + 500 条候选效果更好。这是 OPRO / DSPy 后来把 score 函数升级为 LLM-as-judge 的根本动机。