auto-prompt-文本梯度
ProTeGi(Prompt Optimization with Textual Gradients)是什么?
ProTeGi 是一种把“改 Prompt”做成可迭代的误差驱动优化的方法。它的关键点是:不像 APE/GrIPS 主要靠“生成很多候选 → 打分 → 再改写”,ProTeGi 会先让当前 prompt 在一批数据上跑一遍,收集模型输出与标准答案的差异,再让另一个 LLM 用这些差异对 prompt 进行“批评(critique)”,形成类似“梯度信号”的文本梯度(textual gradients),并据此提出更有针对性的 prompt 修改。
你可以把它理解为:
把“误差”转成“可执行的改动建议”,再用小规模探索选择最有效的改动。
核心思想:什么叫“文本梯度(Textual Gradients)”?
在普通深度学习里,梯度告诉你“参数该往哪个方向调,loss 才会下降”。
ProTeGi 里没有对 prompt 做可微分训练(prompt 是自然语言文本),于是用 LLM 生成的“批评/改动建议”来充当梯度方向,这就是“文本梯度”:
- 观察错误:模型哪里答错了、漏了什么、格式错在哪
- 归因到 prompt:是定义不清?缺少约束?输出格式不严?步骤缺失?
- 产出改动:具体应增加/删除/改写哪句话、加什么规则/反例/自检
这种“由错误驱动的定向修改”通常比纯随机/纯改写式的搜索更高效。
论文摘要里提到的 ProTeGi 多步流程(工程化拆解)
你引用的描述可以拆成 5 个模块:
Step 1:用当前 prompt 模板跑一批数据(batch)
- 输入:prompt template + 一批 inputs
- 输出:模型 predictions
这里的“template”通常是可复用的提示词骨架,例如:
- 任务指令 + 输入占位符
- 约束与输出格式
- (可选)少量示例
Step 2:把(模型输出、标准答案、原 prompt)喂给“批评器 prompt”
这一步是 ProTeGi 的精髓:让另一个 LLM 充当“prompt critic / prompt reviewer”。
批评器的输入通常包括:
- 原 prompt(你是怎么指挥模型的)
- 模型输出(你得到的结果)
- ground truth(你想要的正确结果)
- 可能还有:任务定义、评分规则、失败样例合集
批评器产出:
- 这条 prompt 为什么导致这些错误(归因)
- 可执行的修改建议(文本梯度)
Step 3:从批评中生成多个新 prompts(基于“文本梯度”更新)
不是盲目 paraphrase,而是“按批评建议修改”。例如:
- “模型经常编造缺失字段” → prompt 里加“缺失填 null,禁止推测”
- “把个人攻击误判成仇恨” → prompt 里加边界规则与反例
- “JSON 经常不合法” → prompt 里加“仅输出 JSON + 输出前自检”
Step 4:用 bandit 算法选择一个新 prompt(探索-利用)
ProTeGi 不一定每轮都评估全部候选到收敛,而是用**多臂老虎机(bandit)**思路在候选 prompt 中进行:
- 探索:尝试看似有潜力但不确定的改动
- 利用:优先选择历史表现稳定更好的改动
这能在调用预算有限时更高效地找到好 prompt。
(你提到的 Gabillon et al., 2011 是 bandit 相关工作。)
Step 5:迭代
选出一个表现最好的新 prompt 后,继续下一轮:再跑 batch → 再批评 → 再生成 → 再 bandit 选择。
ProTeGi 相比 APE/GrIPS “独特”在哪里?
1)更“诊断驱动”(error-driven)
- APE:从 exemplars 归纳指令,再大量生成与 paraphrase,偏“全局搜索”
- GrIPS:对起始 prompt 做离散编辑算子搜索(加/删/换/改写),偏“局部结构搜索”
- ProTeGi:用 ground truth 对照输出,先生成“批评/梯度”,再按梯度方向更新,偏“基于误差的定向优化”
2)对“哪里错了”更敏感
ProTeGi 在每轮都显式利用:
- 模型输出 vs 标准答案的差异
- 具体失败模式聚合 因此常能做出更“精准”的 prompt 修复,而不是靠运气搜到。
3)bandit 帮你省预算
与“全量评估所有候选”比,bandit 更适合预算受限的迭代优化。
适合与不适合的应用场景
适合(很推荐)
- 有标准答案/可自动对比的任务
- 分类(accuracy/F1)
- 抽取(字段级准确率、解析率)
- 结构化生成(schema match)
- 一部分问答/阅读理解(exact match/包含关键点)
- 你已经有一个 prompt,但存在稳定的错误模式
- 经常漏字段、乱编、格式不稳、边界误判
- 你想要“可解释的改动轨迹”
- ProTeGi 的批评文本能形成“改动日志”:为什么改、改哪、解决什么错
- 你想在较少迭代中获得提升
- 相比纯搜索,误差驱动通常更省调用
不适合(或要额外机制)
- 没有 ground truth / 无法可靠评分
- 纯创意生成、主观质量(除非引入偏好模型或人工反馈)
- ground truth 本身噪声很大
- 批评会学到错误信号,导致 prompt 往错误方向优化
- 任务高度开放且“正确答案不唯一”
- 需要把评价函数设计成“要点覆盖/格式/事实引用”等软指标
- 高风险内容任务且没有安全护栏
- 批评/改写可能生成不合规 prompt(需要过滤与审计)
至少 3 个中文例子:ProTeGi 的提示词写法(含“批评器 prompt”)
下面每个例子都给你:
- 任务 prompt 模板(待优化对象)
- 批评器 prompt(产生 textual gradients)
- 基于批评生成新 prompt 的 prompt(把批评落实为改写)
例子1:信息抽取(融资新闻→JSON),修复“编造金额/JSON不合法”
(A) 初始任务 prompt 模板
你是信息抽取引擎。
从文本中抽取融资信息,输出 JSON:
{"公司名":"","轮次":"","金额":"","投资方":[],"时间":""}
文本:{文本}
(B) 批评器 prompt(Critique Prompt = 产生文本梯度)
你是提示词审阅员。你的任务是批评并改进“信息抽取提示词”。
我会给你:原提示词、模型输出、标准答案。
请输出两部分:
1)错误诊断:指出模型输出相对标准答案的具体错误类型(编造/漏抽/字段混淆/格式错误等),并说明可能是提示词哪一句导致的。
2)文本梯度(可执行修改建议):用要点列出应如何修改提示词(增加哪些规则/删除哪些歧义/强化哪些格式约束),每条建议要具体到可直接写进提示词。【原提示词】
{prompt}
【输入文本】
{input}
【模型输出】
{pred}
【标准答案】
{gold}
(C) “根据批评生成新 prompt”的生成器 prompt
你是提示词改写器。请根据以下“文本梯度(修改建议)”对原提示词做最小必要修改,以提升抽取准确率与 JSON 可解析率。
约束:
- 字段名必须保持不变:公司名、轮次、金额、投资方、时间
- 缺失信息必须填 null(投资方缺失填 [])
- 禁止输出除 JSON 外的任何文字
输出:只输出改写后的完整提示词。【原提示词】{prompt}
【文本梯度】{critique_suggestions}
例子2:仇恨言论分类,修复“引用转述误判/个人辱骂误判”
(A) 初始任务 prompt
判断文本是否为仇恨言论。输出:仇恨/非仇恨。文本:{文本}
(B) 批评器 prompt(特别要求“边界规则”)
你是内容安全提示词审阅员。
给定原提示词、输入文本、模型输出与标准答案,请:
1)找出误判的原因(例如:把攻击个人当攻击群体;把引用当立场;忽略否定/反讽)
2)输出“文本梯度”:把需要补充进提示词的边界规则写成可执行条款(例如“仅当满足A且满足B时才判仇恨”),并给出1条反例规则。原提示词:{prompt}
输入:{input}
模型输出:{pred}
标准答案:{gold}
(C) 基于梯度改写 prompt(要求结构化输出减少漂移)
根据以下文本梯度改写任务提示词,使其更少误判。
强约束:
- 输出固定为 JSON:{"标签":"仇恨/非仇恨","指向群体":null或字符串,"证据":null或片段}
- 不确定时输出“非仇恨”,其余字段为 null
只输出最终提示词。
原提示词:{prompt}
文本梯度:{critique_suggestions}
例子3:数学应用题,修复“漏项/单位错误/最后一步算错”
(A) 初始任务 prompt
解题并给出答案。题目:{题目}
(B) 批评器 prompt(把错误归因为“缺少检查步骤”)
你是数学解题提示词的审阅员。
给定:原提示词、题目、模型解答、标准答案。
请输出:
1)错误类型:漏项、列式错误、计算错误、单位错误、抄错数字等(可多选)
2)提示词缺陷假设:原提示词缺少哪些强制步骤导致上述错误
3)文本梯度:把要加入提示词的具体步骤写出来(例如“先列式,再逐步计算,最后代回检查”),并要求固定输出格式“答案:”。原提示词:{prompt}
题目:{input}
模型解答:{pred}
标准答案:{gold}
(C) 改写器 prompt(将梯度落实为“解题协议”)
请将文本梯度整合进原提示词,生成一个更鲁棒的数学解题提示词。
约束:
- 必须包含:列出已知量与单位、列式、逐步计算、单位检查、合理性检查
- 最后一行必须是:答案:{数值}{单位或空}
输出:只输出改写后的提示词。
原提示词:{prompt}
文本梯度:{critique_suggestions}
实操建议:你怎么从 0 开始跑一个“简化版 ProTeGi”
- 准备数据:至少 50~200 条(输入、标准输出)
- 写一个 baseline prompt template(尽量简洁)
- 每轮抽一批(batch),例如 20 条:生成预测
- 把失败样例(pred vs gold)喂给 Critique Prompt,得到“文本梯度”
- 用“改写器 prompt”生成 5~20 个候选新 prompt
- 评估候选(全量或小批)
- 用 bandit/或简单 top-1 选择进入下一轮
- 留验证集防过拟合;记录每轮改动与指标
如果你告诉我你的具体任务类型(分类/抽取/生成)以及你现在的 baseline prompt 和 5 条失败样例(input、pred、gold),我可以按 ProTeGi 的方式:
- 给你写一套高质量的 Critique Prompt(适配你的任务)
- 生成第一轮“文本梯度”示例
- 给出 5 个改写后的候选 prompt(并解释每个改动针对的错误模式)。