Self-Refine: Iterative Refinement with Self-Feedback
一句话总结:让同一个固定的 LLM扮演三种角色——先生成初稿、再给自己写反馈、然后据反馈修订——如此迭代,不需要任何监督数据、额外训练或强化学习;仅靠 few-shot prompting,就能在测试时把 7 个不同任务的输出质量平均绝对提升约 20%,连 GPT-4 这样的最强模型也能被进一步提升。
- 来源:Aman Madaan, Niket Tandon, Prakhar Gupta, Skyler Hallinan, Luyu Gao, Sarah Wiegreffe, Uri Alon, Nouha Dziri, Shrimai Prabhumoye, Yiming Yang, Shashank Gupta, Bodhisattwa Prasad Majumder, Katherine Hermann, Sean Welleck, Amir Yazdanbakhsh, Peter Clark(CMU / AI2 / UW / NVIDIA / UCSD / Google Research),arXiv:2303.17651v2,2023-05-25(NeurIPS 2023)
- 项目页 / 代码:https://selfrefine.info/
- 本地 PDF:ref14_self-refine.pdf
TL;DR 速览
- 问题:LLM 常常"第一次就写不好"——尤其是多目标任务(对话回复要相关+有趣+安全…)或目标难定义的任务(提升代码可读性)。传统迭代改进要么训练一个专用 refiner + 领域数据,要么靠外部奖励模型 / 昂贵人工标注;这些监督成本高、不通用。作者问:能不能不训练、只用一个现成 LLM,在测试时自己改自己?
- 方法:提出 Self-Refine——一个 generate→feedback→refine 的迭代闭环,同一个模型 \(M\) 同时当生成器、反馈者、修订者: 1. 初始生成:\(y_0 = M(p_{gen}\|x)\); 2. FEEDBACK:\(fb_t = M(p_{fb}\|x\|y_t)\),反馈必须具体(specific)且可执行(actionable)——指出哪个 phrase 有问题、该怎么改; 3. REFINE:\(y_{t+1}=M(p_{refine}\|x\|y_0\|fb_0\|...\|y_t\|fb_t)\),把整段历史(所有历史输出+反馈)拼进 prompt,让模型"从过去的错误里学、不重复犯"; 4. 迭代直到 \(M\) 自己判断"无需再改"或达到上限(本文最多 4 轮)。全程只靠 few-shot prompt 里的少量示范来引导,无需训练。
- 关键数字(Table 1,7 任务 × 3 模型):
- 平均绝对 +20% 左右;对话回复 GPT-4 偏好率 25.4→74.6(+49.2)、情感反转 GPT-4 3.8→36.2(+32.4)、约束生成 GPT-4 15.0→45.0(+30.0)。
- 代码优化 GPT-4 27.3→36.0(+8.7);GSM8K 数学在 GPT-4 上几乎无提升(92.9→93.1)——因为模型难以判断自己的推理链是否有错(ChatGPT 对 94% 实例的反馈都是"everything looks good")。
- 消融(最关键):反馈质量决定成败——具体反馈 vs 泛化反馈 vs 无反馈,在情感反转上是 43.2 → 31.2 → 0(无反馈直接归零)。
- 一句话评价:这是"推理时自我改进"谱系里最简洁、最早被广泛复现的奠基工作之一——它把"人类写作先出草稿再改"的直觉,压缩成三个 prompt 的循环,不动一个权重就拿到测试时增益。它最深刻的经验教训是"生成 ≠ 评判"——模型评判自己产物的能力(feedback 质量)才是自我改进的真正瓶颈:在能自我诊断的任务(对话、代码效率)上狂涨,在难自我诊断的任务(数学对错)上几乎不动。这条"评判能力是天花板"的观察,直接串起了后续 [[ref05_self-rewarding-language-models]](把 judge 也训进模型)、[[ref17_self-harness]](用确定性 verifier 锚定失败)、[[ref09_meta-harness]](把原始 trace 而非摘要喂给优化器)。
tags: #自我改进 #iterative-refinement #self-feedback #in-context-learning #test-time-improvement #prompting #无需训练
related: [[ref05_self-rewarding-language-models]](把"当评委"内化进训练)· [[ref17_self-harness]](自我改进但改的是 harness 面,且有回归门)· [[ref09_meta-harness]](外部 Agent 优化、强调不压缩反馈)· [[ref19_gepa]](反思式 prompt 进化,Self-Refine 的训练时/搜索式后继)· [[ref07_ace-agentic-context-engineering]](累积上下文的自我改进)· [[ref06_spin-self-play-finetuning]]
摘要
和人类一样,LLM 也不总能"第一次就生成最好的输出"。受"人类如何打磨文字"的启发,我们提出 Self-Refine:通过迭代的反馈与修订来改进 LLM 的初始输出。核心想法是——用 LLM 生成一个初始输出,然后同一个 LLM 给自己的输出写反馈、并据此自我修订,反复迭代。Self-Refine 不需要任何监督训练数据、额外训练或强化学习,而是用单个 LLM 同时充当生成器、修订者、反馈提供者。
作者在 7 个多样任务(从对话回复生成到数学推理)上、用 SOTA 模型(GPT-3.5 与 GPT-4)评估。所有任务上,Self-Refine 的输出都被人类和自动指标偏好于同一模型的常规单步生成,任务表现平均绝对提升约 20%。这项工作表明:即便是 GPT-4 这样的最强 LLM,也能用这个简单、独立(standalone)的方法在测试时被进一步改进。
1 介绍:把"人类先出草稿再改"搬进 LLM
论文的动机极其朴素、也极其有共鸣:LLM 能生成连贯的输出,但常常达不到复杂要求。作者点了两类典型场景:
- 多目标任务(multifaceted objectives):如对话回复生成——一句好回复要同时相关、有信息量、有趣、安全、体现对用户的理解……单次生成很难一次全占。
- 目标难定义的任务(hard-to-define goals):如提升代码可读性——没有一个干净的标量能刻画"好读",但人类一眼能看出哪里能改。
在这些场景里,现代 LLM 能产出一个"看得过去"的初稿,但能从进一步的迭代改进中受益。而传统迭代改进的做法都带着沉重的监督负担:要么训练一个依赖领域数据的 refinement 模型(Reid & Neubig 2022;Welleck et al. 2022),要么依赖外部监督 / 奖励模型 + 大训练集或昂贵人工标注(Ouyang et al. 2022)。这些成本"未必总能付得起"。于是本文要找的是——一个不需要大量监督、能适配各种任务的有效 refinement 方法。
关键洞察来自认知科学:迭代式自我改进(iterative self-refinement)是人类解决问题的基本特征(Simon 1962;Flower & Hayes 1981;Amabile 1983)——先写初稿,再基于自己给自己的反馈去改。论文举了两个贴切的例子:
[!NOTE] 两个人类直觉例子(贯穿全文的锚点) - 写邮件:想向同事要一份数据,第一反应写 "Send me the data ASAP"(直接、略冲);反思后意识到不够礼貌,改成 "Hi Ashley, could you please send me the data at your earliest convenience?"。 - 写代码:先实现一版 "quick and dirty" 的能跑代码,反思后重构成更高效、更可读的版本。
这两个例子的共同结构就是 Self-Refine 的骨架:同一个"大脑"既能产出初稿、也能反思出问题、还能据此改好——不需要请第二个人。
作者由此提出 Self-Refine:一个在两个生成步骤 FEEDBACK 与 REFINE 之间交替的迭代算法。给定 \(M\) 生成的初始输出,把它喂回同一个 \(M\) 拿反馈;反馈再喂回同一个 \(M\) 去修订上一版草稿。反复,直到指定轮数或 \(M\) 判断"无需再改"。全程用 few-shot prompting(Brown et al. 2020)引导 \(M\) 既能写反馈、也能把反馈吸收进改进版。
[!TIP] 什么是 in-context learning / few-shot prompting? few-shot prompting(也叫 in-context learning, ICL)是 GPT-3 论文(Brown et al. 2020)确立的范式:不更新任何权重,只在 prompt 里放 \(k\) 个"输入-输出"示范对 \(\langle x_i, y_i\rangle\),模型就能在推理时"照葫芦画瓢"地完成新任务。它是 Self-Refine 的技术地基——本文的三个 prompt(\(p_{gen}, p_{fb}, p_{refine}\))都是 few-shot 的: - \(p_{gen}\) 放的是 \(\langle x^{(k)}, y^{(k)}\rangle\)(怎么做初稿); - \(p_{fb}\) 放的是 \(\langle x^{(k)}, y^{(k)}, fb^{(k)}\rangle\)(好反馈长什么样); - \(p_{refine}\) 放的是 \(\langle x^{(k)}, y^{(k)}, fb^{(k)}, y^{(k)}_{t+1}\rangle\)(怎么把反馈变成改进)。
为什么重要:正因为一切靠 ICL、不靠训练,Self-Refine 才能"即插即用"到任何足够强的现成 LLM 上——但这也埋下了它唯一的硬约束(见 §6 局限):基座模型必须有足够强的 few-shot / 指令遵循能力,否则连"按格式写反馈"都做不到(Vicuna-13B 就栽在这里)。
结果预告:在 7 个跨领域生成任务上,Self-Refine 超过 GPT-3.5(text-davinci-003、gpt-3.5-turbo)和 GPT-4 的直接生成 5–40% 绝对提升;代码任务上对强代码模型 CODEX(code-davinci-002)也能提升最高 13% 绝对。核心信息:即便 LLM 第一次给不出最优解,它往往也能给出有用的反馈、并据此改好自己的输出。

Figure 1 逐元素解读(全文最招牌的一张图,把"三合一"讲得一目了然): - 中央紫色块「Model \(\mathcal{M}\)」:唯一的模型,图里画成一颗"大脑"。三个箭头都从它出发、又回到它——强调 generate / feedback / refine 共用同一个 \(M\)、不引入第二个模型或人类。 - 步骤 ⓪「Input」→ \(M\)(顶部蓝色小箭头):输入 \(x\) 进入模型,产出初始输出 \(y_0\)。 - 步骤 ①「Feedback」(左侧红色块 + 底部注 "Use \(M\) to get feedback on its own output"):把 \(y_0\) 喂回 \(M\),让它对自己的输出写反馈。箭头是一个"出去又回来"的环,视觉上就是"自我评判"。 - 步骤 ②「Refine」(右侧橙色块 + 底部注 "Use \(M\) to refine its previous output, given its feedback"):把反馈喂回 \(M\),改出更好的 \(y_{t+1}\)。 - 闭环含义:① 和 ② 反复交替,直到停止条件满足。整张图没有任何人类参与、没有任何外部奖励模型——这正是"standalone / 无需训练"的视觉宣言。
2 方法:Self-Refine 的三步形式化
本节是全文核心。Self-Refine 只依赖一个合适的语言模型 + 三个 prompt(初始生成、反馈、修订),不需要训练。
2.1 三个生成步骤 + 停止
Step 1 — 初始生成。给定输入 \(x\)、生成 prompt \(p_{gen}\)、模型 \(M\):
其中 \(\|\) 表示拼接,\(p_{gen}\) 是任务专用的 few-shot prompt(内含若干 \(\langle x^{(k)}, y^{(k)}\rangle\) 示范)。
Step 2 — FEEDBACK。用同一个 \(M\)、配一个专用反馈 prompt \(p_{fb}\),对自己的输出 \(y_t\) 写反馈:
\(p_{fb}\) 里放的是"输入-输出-反馈"三元组 \(\langle x^{(k)}, y^{(k)}, fb^{(k)}\rangle\),用来教模型写出可执行(actionable)且具体(specific)的反馈。反馈可以覆盖多个方面(如代码的效率、可读性、整体质量)。
Step 3 — REFINE。用 \(M\) 根据自己的反馈修订最近一版输出:
\(p_{refine}\) 放的是"输入-输出-反馈-改进版"四元组 \(\langle x^{(k)}, y^{(k)}_t, fb^{(k)}_t, y^{(k)}_{t+1}\rangle\)。
Step 4 — 迭代 + 停止 + 保留历史。FEEDBACK 与 REFINE 交替直到 \(stop(fb_t, t)\) 满足:要么到指定步数 \(t\),要么从反馈里抽一个停止指示器(如一个标量 stop score)——模型可以被 prompt 成在 \(p_{fb}\) 里顺便生成这个指示器,条件按任务定。关键一笔是:为让模型知道前几轮发生了什么,要把历史反馈和输出全部拼回 prompt,于是式 (3) 实际上被实例化为:
最后用最后一版修订 \(y_t\) 作为 Self-Refine 的输出。
| 符号 | 含义 |
|---|---|
| \(M\) | 唯一的、固定的语言模型,全程不改权重,同时充当生成器 / 反馈者 / 修订者 |
| \(x\) | 任务输入(如一段待优化代码、一句对话上下文) |
| \(p_{gen}, p_{fb}, p_{refine}\) | 三个任务专用 few-shot prompt:初始生成 / 写反馈 / 据反馈修订 |
| \(y_t\) | 第 \(t\) 轮的输出(\(y_0\) 是初稿) |
| \(fb_t\) | \(M\) 对 \(y_t\) 写的反馈(须 actionable + specific) |
| \(\|\) | 序列拼接 |
| \(stop(fb_t, t)\) | 停止条件:到指定步数、或从反馈中抽出的停止指示器触发 |
[!TIP] 把式 (1)–(4) 讲透 + 举例(以代码优化为例,对应 Figure 2 下排) 逐项物理含义:这三个式子其实就是同一个 \(M\) 被喂三种不同的 prompt 前缀。变的只有 prompt(\(p_{gen}/p_{fb}/p_{refine}\))和拼进去的内容,模型本身一字未改。
具体走一遍(输入 \(x\) = "生成 \(1+\dots+N\) 的和"): 1. 式 (1):\(M\) 产出初稿 \(y_0\)——一个
for循环累加:def sum(n): res=0; for i in range(n+1): res+=i; return res。功能正确,但 \(O(N)\)。 2. 式 (2):把 \(y_0\) 喂回 \(M\),它写出反馈 \(fb_0\) = "This code is slow as it uses brute force. A better approach is to use the formula \(\dots (n(n+1))/2\)"。这条反馈是 actionable(给了动作:"用公式")、又是 specific(点名了问题:"for loop / brute force")。 3. 式 (3)/(4):把 \(y_0 + fb_0\) 喂回 \(M\),它改出 \(y_1\) =def sum_faster(n): return (n*(n+1))//2——\(O(1)\)。 4. 若继续,式 (4) 会把 \(\{y_0, fb_0, y_1, fb_1\}\) 全部拼进 prompt。为什么式 (4) 要保留全历史(而不是只喂上一版 \(y_t, fb_t\))? 作者的直觉是"让模型从过去的错误里学、别重复犯"——如果只喂最新一版,模型可能把上一轮已经否掉的坏方案又提一遍,或在多方面反馈任务里"改好 A 又改坏 B"。带上全历史,等于给模型一个"我已经试过什么、为什么不行"的短期记忆。这是一个很关键、也很容易被忽视的设计——它预示了后来 [[ref09_meta-harness]] 那句"不要压缩反馈、把原始历史留给优化器"的更激进版本。
[!TIP] 什么是 iterative refinement(迭代修订)?它和 RL / CoT 有何不同? iterative refinement = 反复把一个候选输出映射成一个更好的输出。Self-Refine 把它实现成"生成→评判→修订"的循环。要理解它的定位,和三个相邻概念对比: - vs Chain-of-Thought(CoT,Wei et al. 2022):CoT 是在单次生成内部展开推理步骤("让我一步步想"),是单向、一次性的;Self-Refine 是跨多次生成、带反向修订的——先出答案,再回头批判、再改。两者正交,可叠加。 - vs 强化学习(RL / RLHF):RL 把反馈压成一个标量奖励去更新模型权重,且模型看不到对某个中间产物的具体反馈;Self-Refine 不更新任何权重,反馈是自然语言、针对具体中间产物、在推理时起作用。一句话:RL 改的是"模型本身",Self-Refine 改的是"这一次的输出"。 - vs 训练一个专用 refiner(如 Self-Correction, Welleck et al. 2022):那类方法要为每个新任务训一个 corrector;Self-Refine 同一个模型同时当 refiner 和反馈源,靠 few-shot 跨任务通用,不训练。
在本文里,iterative refinement 的角色是"把 LLM 从'一次性生成器'升级成'能自我纠错的迭代求解器'"——而且是用最轻的方式(三个 prompt)。
2.2 算法全貌

Figure 3 / Algorithm 1 逐行解读(这是方法的可执行骨架):
- Require:输入 \(x\)、模型 \(M\)、三个 prompt \(\{p_{gen}, p_{fb}, p_{refine}\}\)、停止条件 \(stop(\cdot)\)。
- 行 1:\(y_0 = M(p_{gen}\|x)\) —— 初始生成(式 1)。
- 行 2:for iteration t ∈ 0, 1, ... do —— 进入 FEEDBACK-REFINE 主循环。
- 行 3:\(fb_t = M(p_{fb}\|x\|y_t)\) —— 对当前输出写反馈(式 2)。
- 行 4–5:if stop(fb_t, t) then break —— 先判停,若反馈里的停止指示器触发(或到步数上限)就退出。
- 行 6–7:else \(y_{t+1} = M(p_{refine}\|x\|y_0\|fb_0\|...\|y_t\|fb_t)\) —— 否则据全历史修订(式 4)。
- 行 10:return y_t —— 返回最后一版(多方面任务里会按分数选最优,见 §3.4)。
[!NOTE] 注意 Figure 2 与 Algorithm 一致:
stop判断放在 refine 之前——意味着当模型"觉得没啥可改了"时,会保留当前版本、不做无谓修订。这个"模型自己决定何时停"的机制,把"迭代几次"这个超参从人手里部分下放给了模型自己。

Figure 2 逐格解读(上排=对话,下排=代码,两行同构,直观展示"输入→反馈→修订"):
- 上排 (a) 输入/当前输出 \(x, y_t\):用户说"我想打乒乓球",初始回复 "I'm sure it's a great way to socialize, stay active"——空泛、没信息量。
- 上排 (b) FEEDBACK \(fb\):模型自评——"Engaging: 完全没提乒乓球本身怎么打;User understanding: 没理解用户的需求和心态"。注意这是多方面(multi-aspect)反馈,逐项点名短板。
- 上排 (c) REFINE \(y_{t+1}\):改后回复变成 "That's great to hear! It's a fun sport requiring quick reflexes and good hand-eye coordination. Have you played before, or are you looking to learn?"——有了具体信息 + 反问、更 engaging。
- 下排 (d)/(e)/(f):同一套流程用在代码优化上——初稿是 \(O(N)\) 的 for 循环求和;反馈诊断"brute force、应该用公式 \(n(n+1)/2\)";改后是 \(O(1)\) 的 sum_faster。
- 两行并置的用意:证明 Self-Refine 不是针对某一类任务的 trick,而是一套通用的"生成-反馈-修订"模板——从自然语言(对话)到源代码都适用,且反馈都遵循"具体+可执行"的规格。
3 实验:7 任务、3 模型,一致提升
3.1 实验设置
- 7 个任务(跨自然语言与代码):情感反转(Sentiment Reversal, Zhang et al. 2015)、对话回复生成(Mehri & Eskenazi 2020)、代码优化(Madaan et al. 2023)、代码可读性改进(Puri et al. 2021)、数学推理(GSM8K, Cobbe et al. 2021),外加两个作者新引入的任务:缩写词生成(Acronym Generation)和约束生成(Constrained Generation——CommonGen 的加难版,把关键词约束从 3–5 个提到 20–30 个)。
- 迭代设置:FEEDBACK-REFINE 迭代直到达标或满足任务准则,最多 4 轮。为跨模型一致,即便对 ChatGPT/GPT-4 这类会遵循指令的模型,也统一用 few-shot prompt 实现 FEEDBACK 和 REFINE。
- 基座 LLM:三个强基座——GPT-3.5(text-davinci-003)、ChatGPT(gpt-3.5-turbo)、GPT-4;代码任务另加 CODEX(code-davinci-002)。所有任务里 GPT-3.5 或 GPT-4 都是当时的 SOTA。解码用 temperature 0.7。
- 三类指标:① 任务专用自动指标(数学=解题率、代码优化=优化程序占比 %OPT、约束生成=覆盖率);② Human-pref(无自动指标的任务做盲测 A/B 人评);③ GPT-4-pref(用 GPT-4 当人类偏好代理,与人评相关性 68–82%)。
3.2 主结果(Table 1)
Self-Refine 在所有任务、所有模型规模上都一致超过基座,并超过各任务此前的 SOTA。
| 任务 | GPT-3.5 Base | +SR | ChatGPT Base | +SR | GPT-4 Base | +SR |
|---|---|---|---|---|---|---|
| 情感反转 | 8.8 | 30.4 (↑21.6) | 11.4 | 43.2 (↑31.8) | 3.8 | 36.2 (↑32.4) |
| 对话回复 | 36.4 | 63.6 (↑27.2) | 40.1 | 59.9 (↑19.8) | 25.4 | 74.6 (↑49.2) |
| 代码优化 | 14.8 | 23.0 (↑8.2) | 23.9 | 27.5 (↑3.6) | 27.3 | 36.0 (↑8.7) |
| 代码可读性 | 37.4 | 51.3 (↑13.9) | 27.7 | 63.1 (↑35.4) | 27.4 | 56.2 (↑28.8) |
| 数学推理 | 64.1 | 64.1 (0) | 74.8 | 75.0 (↑0.2) | 92.9 | 93.1 (↑0.2) |
| 缩写词生成 | 41.6 | 56.4 (↑14.8) | 27.2 | 37.2 (↑10.0) | 30.4 | 56.0 (↑25.6) |
| 约束生成 | 28.0 | 37.0 (↑9.0) | 44.0 | 67.0 (↑23.0) | 15.0 | 45.0 (↑30.0) |
几个值得记的观察: - 偏好类任务涨得最猛(对话/情感/缩写词)——因为这些任务"多目标、答案空间大",初稿很容易漏掉某些维度,Self-Refine 正好把它们补回来。约束生成尤其受益(要塞进 30 个概念,第一次几乎必漏,迭代能逐个补齐 + 更好地探索巨大的合理输出空间)。 - 强模型解锁潜力:GPT-4+SR 普遍优于 GPT-3.5+SR / ChatGPT+SR,即使 GPT-4 的初始 base 分更低(如对话 GPT-4 base 才 25.4 却在 +SR 后冲到 74.6)。作者据此认为 Self-Refine 让强模型"释放出单步生成没表达出来的潜力"。 - 数学几乎不动(+0 到 +0.2)——这是全文最有信息量的"负结果",见下。
[!IMPORTANT] 为什么数学推理几乎不涨?——"评判能力"才是天花板 作者把数学的疲软归因到"无法准确判断是否有错":数学错误往往细微(限于某一行、某个错误运算),而"看起来自洽的推理链会骗过 LLM,让它以为'everything looks good'"——ChatGPT 对 94% 的数学实例的反馈就是这句话。也就是说:Self-Refine 的修订能力(refine)没问题,卡住的是评判能力(feedback)——如果模型察觉不到错,就无从改起。 关键验证(Appendix H.1,Table 9):一旦引入外部信号 / Oracle 反馈(只在答案确实错时才进入 refine),数学立刻涨——GPT-3 +4.8、GPT-4 +0.7、ChatGPT +1.4。这直接证明:bottleneck 不在"改",而在"知道该不该改"。→ 这条洞察是通往 [[ref17_self-harness]](用确定性 verifier 判失败)和 [[ref05_self-rewarding-language-models]](把 judge 能力也训进模型)的逻辑起点。
3.3 消融一:反馈质量决定成败(Table 2)
作者比较三种条件:Self-Refine 具体反馈 vs 泛化反馈(generic) vs 无反馈(模型仍可迭代改,但不给它反馈)。
| 任务 | 具体反馈 | 泛化反馈 | 无反馈 |
|---|---|---|---|
| 代码优化 | 27.5 | 26.0 | 24.8 |
| 情感反转 | 43.2 | 31.2 | 0 |
| 缩写词生成 | 56.4 | 54.0 | 48.0 |
[!IMPORTANT] 具体、可执行的反馈是 Self-Refine 起作用的关键成分。 对比例子很说明问题:代码优化里 "Avoid repeated calculations in the for loop"(具体、指出问题+给出方向)远胜 "Improve the efficiency of the code"(泛化、没方向)。效应在情感反转上最极端——从具体反馈 43.2 掉到泛化 31.2,无反馈直接归零(任务彻底失败)。这与 §3.2 的数学负结果互为印证:反馈的信息含量,就是自我改进的上限。
3.4 消融二:多轮迭代有效但边际递减(Figure 4)

Figure 4 逐面板解读: - 左表(Iteration-wise score):三个任务在 \(y_0 \to y_3\) 的分数轨迹——代码优化 22.0→27.0→27.9→28.8、情感反转 33.9→34.9→36.1→36.8、约束生成 29.0→40.3→46.7→49.7。每一轮都在涨,约束生成涨幅最大(第一次漏概念多、后续补得多)。 - 右图(每轮增量 \(\Delta\) 柱状图):把相邻两轮的提升 \(\Delta(y_0\to y_1)\)、\(\Delta(y_1\to y_2)\)、\(\Delta(y_2\to y_3)\) 画出来。明显的边际递减——约束生成(红)从 +11.3 → +6.4 → +3.0;代码优化(蓝)从 +5.0 → +0.9 → +0.9;情感反转(棕)从 +1.0 → +1.2 → +0.7。 - 结论:大部分收益集中在前几轮,多轮迭代整体有益但回报递减——这解释了为什么本文把上限设成"最多 4 轮"就够。 - 注意事项(非单调):在多方面反馈任务(如缩写词生成)里,输出质量可能在迭代中波动——某一方面改好了、另一方面反而退步(Table 10:TACC-SIM 17 分 → TACCSF 12 分 → TACC-SIMF 17 分)。为此 Self-Refine 让反馈生成各方面的数值分数,最后按跨迭代最高总分选输出(Algorithm 1 行 8 的选择逻辑),而非盲目取最后一版。
3.5 消融三:是"迭代修订"在起作用,不是"多采样"
[!TIP] 关键对照实验(Figure 6, Appendix H):Self-Refine vs Best-of-k 一个自然的质疑:Self-Refine 涨分,会不会只是因为它多生成了几个候选(相当于多次采样取最好),而非"根据反馈修订"本身有用?作者做 1 vs k 评估:让 ChatGPT 直接采样 \(k=4\) 个初始输出(无反馈无修订),再让 Self-Refine 的单个输出去和这 4 个初稿 PK。结果:即便处于"1 打 4"的劣势设定,Self-Refine 的输出仍被人类偏好于全部 4 个初稿(情感反转 51.1 vs 15.5、缩写词 53.8 vs 6.1)。→ 证明"按反馈修订"的价值超过"单纯多生成几个初稿"。这是把 Self-Refine 与"Best-of-N 采样"划清界限的关键证据。
3.6 消融四:弱模型撑不起 Self-Refine
[!TIP] Vicuna-13B 的失败(Appendix G)——方法的能力门槛 作者用较弱的 Vicuna-13B(LLaMA-13B 在网络对话上微调)跑 Self-Refine:它能生成初稿,但撑不起修订过程——无法稳定地按要求格式写反馈;即便给它 Oracle / 硬编码反馈,它也常常不遵循 refine prompt,要么原样重复输出、要么幻觉出一整段对话。作者的假设:Vicuna 是在对话数据上训练的,不像 instruction-based 模型那样能泛化到测试时的 few-shot 任务。 一个有趣的补救(mixed-refine):用 Vicuna-13B 做初始化、用 ChatGPT 做 FEEDBACK+REFINE——数学从 24.18% 提到 40.5%。说明"生成"和"反馈+修订"可以解耦到不同能力的模型上。→ 这也侧面呼应了 [[ref09_meta-harness]]/[[ref17_self-harness]] 里"越弱的基座、harness/refinement 优化空间越大"的观察,只不过这里弱基座连自我反馈都做不了,得靠强模型补位。
3.7 定性分析:反馈错误是主要失败源
作者手工分析 70 个样本(35 成功 + 35 失败)@代码优化 + 数学推理: - 失败案例中,绝大多数问题来自"反馈错误"而非"修订错误":33% 是反馈没定位准错误位置,61% 是反馈给了不合适的修法,仅 6% 是 refiner 正确反馈却实现错了。 - 成功案例中:61% 是"准确反馈 → 精确修复";有趣的是 33% 是反馈部分错误、refiner 仍改对了——说明 refiner 对次优反馈有一定鲁棒性(Table 12:对话任务里 60% 的情况下模型能"无视坏反馈")。

Figure 5 逐元素解读(最有说服力的成功案例):
- 左「Slower code」:baseline(Madaan et al. 2023)的输出——几乎和原始慢程序一样,用了六层嵌套循环穷举所有硬币组合,只改了读输入的逻辑,没真正优化效率。
- 右「Faster code」:Self-Refine 的输出——识别出这是个找零/背包问题,改用动态规划(dp 数组 + 双层循环),时间复杂度从指数级降到 \(O(amount \times coins)\)。
- 中间的驱动力(见 caption 高亮):Self-Refine 先生成反馈 "This code is slow because it is using six nested loops to iterate through all possible combinations of coins…",并建议 "a more efficient approach would be …"——正是这条精准诊断的反馈,让模型从"穷举"跳到"DP"。
- 启示:这张图把 §3.7 的统计结论具象化了——当反馈足够准(点出"六层嵌套=穷举"这个根因),修订就能实现质的算法跃迁,而不只是表面微调。反过来也印证:反馈质量是杠杆的支点。
4 相关工作:把 Self-Refine 放进 refinement 谱系
作者按反馈的来源 / 表示 / refiner 的获得方式三个维度组织相关工作,并用 Table 3 / Table 5 做系统对比。下面把关键前作讲透。
[!TIP] ① 反馈的来源(Source of feedback) - 人类反馈(Tandon et al. 2021;Bai et al. 2022a 等):最有效,但昂贵。 - 标量奖励函数当人类的替身(Bai et al. 2022a;Le et al. 2022a;Welleck et al. 2022):便宜些,但只有一个数、没有可诊断的细节。 - 领域专用信号:编译器(Yasunaga & Liang 2020)、Wikipedia edits(Schick et al. 2022b)——只在特定域可得。 - LLM 生成反馈(Fu et al. 2023;Peng et al. 2023):通用域也能生成反馈。
Self-Refine 的独特点(作者原话):"ours is the only method that generates feedback using an LLM on its own output, for the purpose of refining with the same LLM"——同一个 LLM 对自己的输出写反馈、再自我修订,这个"自产自评自改"的闭环是它区别于所有前作的核心。
[!TIP] ② 反馈的表示(Representation) - 非自然语言反馈:人给的示范对(Dasgupta et al. 2019)或标量奖励(Liu et al. 2022;Le et al. 2022b)。 - 自然语言(NL)反馈:Self-Refine 选这条路。原因是——NL 反馈让模型能用"生成输出的同一个 LM"轻松自评,同时直接复用现成 LLM(如 GPT-4)的语言能力,无需额外结构。
[!TIP] ③ refiner 的类型(Types of refiners) - 训练监督 refiner(Schick et al. 2022b PEER;Yasunaga & Liang 2020):靠反馈-修订对训练,数据昂贵。 - 用模型自生成训 refiner(Welleck et al. 2022 Self-Correction;Peng et al. 2023):省了人工,但每个新域都要重训一个 refiner。 - Self-Refine:不训练任何独立 refiner——同一个模型靠指令 + few-shot 跨域当 refiner + 反馈源。
[!NOTE] Table 3 的三维分类(Self-Refine 独占右下角):Table 3 用三个属性给方法分类——supervision-free refiner(不用监督训 refiner) / supervision-free feedback(反馈不用监督) / multi-aspect feedback(多方面反馈) / iterative(迭代)。已训练的 refiner(PEER、Self-critique、CodeRL、Self-correction)或被 prompt 的 refiner(Augmenter、Re3、Reflexion)都只满足部分属性,只有 Self-Refine 四项全占——既不训 refiner、反馈也自产、又是多方面、又迭代。
与几个近邻的正面对比(Appendix B):
| 方法 | 反馈来源 | 是否训 refiner | 迭代 | 多方面反馈 | 与 Self-Refine 的关键差别 |
|---|---|---|---|---|---|
| Reflexion(Shinn et al. 2023,并发工作) | LLM 自反思 | 否 | ✓ | ✗(自由形式) | Reflexion 在 ReAct 规划里"找下一个更好的解 / 判断某步是否执行对";Self-Refine 是更细粒度、结构化的多维反馈+分数,适用于不涉及分步规划的开放任务(如对话) |
| Self-Correction(Welleck et al. 2022) | 学到的 corrector | 是(每任务一个) | ✓ | ✗ | ① 不生成显式反馈、只训 refine;② 每任务训一个 corrector;③ 同基座 GPT-3 同设定下 GSM8K:Self-Correction 45.9 vs Self-Refine 55.7(+9.8) |
| RLHF / RL(Stiennon 2020;Lu 2022;Le 2022a) | 标量奖励 | —(改权重) | ✗(训练时) | ✗ | ① 模型看不到对中间产物的反馈;② 要更新权重;Self-Refine 两者皆非 |
| Augmenter / Re3(Peng 2023;Yang 2022) | 外部 KB / 训练的 critic | 部分 | ✓ | 部分 | Re3 与本文最像,但只一个域(故事生成)+ 训练的 critic;Self-Refine 跨域 + 无训练 |
[!TIP] 什么是 Reflexion?(本文最重要的并发对照) Reflexion(Shinn et al. 2023)是与 Self-Refine 同期的自我改进 Agent:它在 ReAct(推理+行动交替)框架里,让 Agent 对"上一次尝试哪里错了"写一段自由形式的语言反思、存进记忆,供下一次尝试参考——本质是"言语强化学习"。与 Self-Refine 的分工:Reflexion 面向需要与环境交互、试错、规划的任务(找到下一个更好的动作序列);Self-Refine 面向改进单个生成产物的质量(把一段文本/代码改得更好),反馈更结构化、多维、带数值分数,因此覆盖更多非规划类的 NLG 任务(尤其开放对话)。两者是同一时期"推理时自我改进"浪潮的两个互补方向。
[!TIP] ④ 非修订类的 RL 方法(作为对照) 另一条融入反馈的路子是优化标量奖励(如 RL:Stiennon et al. 2020;Lu et al. 2022)。它与 Self-Refine 的两点根本差异:① RL 模型无法访问对某个中间生成的反馈(只见最终标量);② RL 要更新模型权重。Self-Refine 则是推理时、不动权重、看得到具体中间反馈——这也是它"轻、通用、即插即用"的来源。
5 局限与讨论
- 基座能力门槛(最主要局限):Self-Refine 要求基座有足够的 few-shot 建模 / 指令遵循能力,才能在 in-context 下学会写反馈、做修订——否则(如 Vicuna-13B)连格式都跟不上。
- 闭源依赖:实验全在 GPT-3.5/ChatGPT/GPT-4/CODEX 这些闭源、非免费模型上,其预训练语料 / 规模 / 偏见都不透明;作者开源了代码和输出以保可复现。
- 仅英文:只在英文数据集上验证,其他语言下现有模型未必给出同样收益。
- 潜在滥用:坏行为者可能用类似 prompting 技巧引导模型生成更有毒/有害的文本;本方法未显式防范。
- 一个隐含的深层局限(结合 §3.2 数学负结果):Self-Refine 的天花板是模型的自我评判能力——在模型察觉不到自己错误的任务上,自我改进近乎无效。这不是实现缺陷,而是"用同一个模型当评委"的结构性限制。
结论:Self-Refine 是一个新颖、简单、易用的方法,让 LLM 在单个模型内、无需额外训练数据或 RL 的前提下迭代地自我反馈、自我修订,跨广泛任务把输出质量拉高,目标是"降低现实世界里人类创作过程的成本"。
个人思考
在本项目坐标系里的定位——"推理时自我改进"的奠基石
Self-Refine(2023-03)是这一整条"自评自改"谱系里最早、最简、被复现最多的工作之一。它的价值不在复杂,而在用三个 prompt 就把"生成-评判-修订"这个原语立起来了,后续几乎所有更复杂的方法都可以看成对它某个环节的加强:
| 后续工作 | 强化了 Self-Refine 的哪一环 | 关键差别 |
|---|---|---|
| [[ref05_self-rewarding-language-models]] | feedback(评判) | Self-Refine 靠现成模型 few-shot 当评委、且不训练;Self-Rewarding 把"当评委(LLM-as-Judge)"的能力训进模型自身,用它给自己的输出打分、生成偏好对做 DPO——把推理时的自评变成训练时的自我奖励 |
| [[ref17_self-harness]] | feedback 的可靠性 + 准入 | Self-Refine 的反馈是软的、可能错(§3.7);Self-Harness 用确定性 verifier 锚定失败、按"症状+机制"聚类,且改动要过回归门才接受——把"自我改进"工程化成可测可逆 |
| [[ref09_meta-harness]] | 历史信息的保真度 | Self-Refine 已经在式 (4) 里"保留全历史反馈";Meta-Harness 把这条推到极致——"不要压缩反馈,把原始 trace(而非摘要/标量)喂给优化器",并证明摘要≈只给分数 |
| [[ref19_gepa]] | iterative refinement 的搜索化 | Self-Refine 是线性、单条的修订链;GEPA 把"反思式修订"变成进化式 prompt 搜索(多候选、Pareto、跨样本反思),是 Self-Refine 的"训练时/搜索式"后继 |
| [[ref07_ace-agentic-context-engineering]] | 反馈的累积载体 | Self-Refine 的历史只活在当前 prompt 里、任务结束就没了;ACE 把有用经验沉淀进一份持续增删改的上下文,跨样本累积 |
我的判断:如果说 [[ref09_meta-harness]]/[[ref17_self-harness]] 是"harness 层"的自我改进,Self-Refine 是"输出层"的自我改进——它改的是"这一次的答案",不是"生成答案的那套代码/协议"。但它埋下的那句"模型评判自己的能力才是天花板"(数学负结果 + Oracle 反馈验证),是整条谱系共同的母题:Self-Rewarding 去训练这个能力、Self-Harness 去用外部 verifier 绕过这个能力的不可靠、Meta-Harness 去给优化器最全的诊断信息以便更好地评判。读懂 Self-Refine 的那个负结果,就读懂了后面一半论文的动机。
方法论启示(可迁移的通用思路)
- "生成 ≠ 评判"是一条硬约束,值得永远记住:一个系统能生成 X,不代表它能判断"这个 X 好不好"。Self-Refine 在能自评的任务上狂涨、在不能自评的任务(数学)上归零——这提醒我们:任何"让系统改自己"的设计,先问"它有没有可靠的评判信号"。没有的话,就得像 Self-Harness 那样引入外部 verifier,或像 Self-Rewarding 那样专门训练评判能力。
- 把"反馈"从标量升级到"具体+可执行的自然语言":Table 2 是很干净的证据——泛化反馈("提升效率")几乎没用,具体反馈("避免循环里重复计算")才有效。这条对任何"自动反馈"系统都成立:反馈的可执行性 = 改进的杠杆。
- 保留历史 vs 压缩历史:式 (4) 选择把全历史拼回 prompt("别重复犯错")。这与 Meta-Harness 的"不压缩反馈"一脉相承——在上下文预算允许时,原始历史 > 摘要。
- 能力可解耦:mixed-refine(弱模型生成 + 强模型反馈修订)说明"生成"和"反馈+修订"可以拆到不同模型上——这是一个便宜的工程 trick,也提示了"评判"是更吃能力的那一环。
在我的工作中能怎么用
- 我们这个
pdf-paper-readerskill 本身就能套 Self-Refine:生成一版笔记 → 让模型对照 SKILL.md 的深度清单(4 项深度、per-figure 解读、符号表…)给自己写具体反馈("§3 缺少符号表"、"Fig 4 只贴图没逐面板解读")→ 据反馈修订。事实上这次修 Fig 3/Fig 4 被误裁的过程(渲染→肉眼验证→发现只裁到 caption→定位 bbox→补渲染→再验证)几乎就是一次手动的 generate-feedback-refine 循环——只不过"反馈"来自我的视觉检查而非模型自评。 - 但要警惕"数学式盲区":笔记里最需要自我改进的地方(如"这个公式解读对不对""这个 related 链接得准不准")恰恰是模型最难自评的——正如 Self-Refine 在数学上失效。所以关键处仍需外部锚点(对照原文 PDF、对照已有笔记的 slug),相当于给 skill 引入"Oracle 反馈"。
开放问题 / 疑问
- 自我反馈的"确认偏误":模型给自己的产物写反馈,会不会系统性地"手下留情"?数学里 94% 的"everything looks good"就是极端例子。有没有办法在不引入外部 verifier 的前提下,让模型对自己更严格(如强制生成 \(N\) 条批评、或用不同 persona 反馈)?
- 停止条件的可靠性:\(stop\) 依赖模型自判"无需再改"——但模型判断自己已达标的能力,本质上又是一种自我评判,同样受天花板限制。多方面任务靠数值分数选最优(Table 10)算是一个补丁,但通用停止仍是开放问题。
- 迭代收益 vs 成本:每轮都要把全历史拼进 prompt(式 4),上下文随迭代线性增长、成本上升,而收益边际递减(Fig 4)。在长文本任务上,"保留全历史"是否可持续?(Meta-Harness 用文件系统 + Agent 主动检索来破这个上下文瓶颈,是一个方向。)
局限性(对本文的批判)
- 7 个任务偏"改写/优化"类,且都相对短程;Self-Refine 在长时程、需真实环境交互的 agentic 任务上如何(这正是 Reflexion/Self-Harness 的主场),本文未覆盖。
- "平均 +20%"是跨任务平均,但方差巨大(对话 +49 vs 数学 +0)——单看均值会高估方法在"难自评任务"上的价值。
- 闭源模型 + 英文 + temperature 0.7 的单一设定,泛化到开源模型、其他语言、其他解码策略的稳健性未验证(作者已在局限里坦承)。