harness_evolve/notes/ref14_self-refine.md

Self-Refine: Iterative Refinement with Self-Feedback

一句话总结:让同一个固定的 LLM扮演三种角色——先生成初稿、再给自己写反馈、然后据反馈修订——如此迭代,不需要任何监督数据、额外训练或强化学习;仅靠 few-shot prompting,就能在测试时把 7 个不同任务的输出质量平均绝对提升约 20%,连 GPT-4 这样的最强模型也能被进一步提升。


TL;DR 速览

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 能生成连贯的输出,但常常达不到复杂要求。作者点了两类典型场景:

在这些场景里,现代 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:一个在两个生成步骤 FEEDBACKREFINE 之间交替的迭代算法。给定 \(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:Self-Refine 的高层循环

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\)

\[ y_0 = M\!\left(p_{gen}\,\|\,x\right) \tag{1} \]

其中 \(\|\) 表示拼接,\(p_{gen}\) 是任务专用的 few-shot prompt(内含若干 \(\langle x^{(k)}, y^{(k)}\rangle\) 示范)。

Step 2 — FEEDBACK。用同一个 \(M\)、配一个专用反馈 prompt \(p_{fb}\),对自己的输出 \(y_t\) 写反馈:

\[ fb_t = M\!\left(p_{fb}\,\|\,x\,\|\,y_t\right) \tag{2} \]

\(p_{fb}\) 里放的是"输入-输出-反馈"三元组 \(\langle x^{(k)}, y^{(k)}, fb^{(k)}\rangle\),用来教模型写出可执行(actionable)具体(specific)的反馈。反馈可以覆盖多个方面(如代码的效率、可读性、整体质量)。

Step 3 — REFINE。用 \(M\) 根据自己的反馈修订最近一版输出:

\[ y_{t+1} = M\!\left(p_{refine}\,\|\,x\,\|\,y_t\,\|\,fb_t\right) \tag{3} \]

\(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+1} = M\!\left(p_{refine}\,\|\,x\,\|\,y_0\,\|\,fb_0\,\|\,\ldots\,\|\,y_t\,\|\,fb_t\right) \tag{4} \]

最后用最后一版修订 \(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:Self-Refine 算法(Algorithm 1)

Figure 3 / Algorithm 1 逐行解读(这是方法的可执行骨架): - Require:输入 \(x\)、模型 \(M\)、三个 prompt \(\{p_{gen}, p_{fb}, p_{refine}\}\)、停止条件 \(stop(\cdot)\)。 - 行 1\(y_0 = M(p_{gen}\|x)\) —— 初始生成(式 1)。 - 行 2for iteration t ∈ 0, 1, ... do —— 进入 FEEDBACK-REFINE 主循环。 - 行 3\(fb_t = M(p_{fb}\|x\|y_t)\) —— 对当前输出写反馈(式 2)。 - 行 4–5if stop(fb_t, t) then break —— 先判停,若反馈里的停止指示器触发(或到步数上限)就退出。 - 行 6–7else \(y_{t+1} = M(p_{refine}\|x\|y_0\|fb_0\|...\|y_t\|fb_t)\) —— 否则据全历史修订(式 4)。 - 行 10return y_t —— 返回最后一版(多方面任务里会按分数选最优,见 §3.4)。

[!NOTE] 注意 Figure 2 与 Algorithm 一致stop 判断放在 refine 之前——意味着当模型"觉得没啥可改了"时,会保留当前版本、不做无谓修订。这个"模型自己决定何时停"的机制,把"迭代几次"这个超参从人手里部分下放给了模型自己。

Figure 2:对话与代码优化两个 Self-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 实验设置

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:迭代次数分析——分数随迭代提升但边际递减

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:代码优化案例——brute force 变 DP

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 是一个新颖、简单、易用的方法,让 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 的那个负结果,就读懂了后面一半论文的动机。

方法论启示(可迁移的通用思路)

  1. "生成 ≠ 评判"是一条硬约束,值得永远记住:一个系统能生成 X,不代表它能判断"这个 X 好不好"。Self-Refine 在能自评的任务上狂涨、在不能自评的任务(数学)上归零——这提醒我们:任何"让系统改自己"的设计,先问"它有没有可靠的评判信号"。没有的话,就得像 Self-Harness 那样引入外部 verifier,或像 Self-Rewarding 那样专门训练评判能力。
  2. 把"反馈"从标量升级到"具体+可执行的自然语言":Table 2 是很干净的证据——泛化反馈("提升效率")几乎没用,具体反馈("避免循环里重复计算")才有效。这条对任何"自动反馈"系统都成立:反馈的可执行性 = 改进的杠杆
  3. 保留历史 vs 压缩历史:式 (4) 选择把全历史拼回 prompt("别重复犯错")。这与 Meta-Harness 的"不压缩反馈"一脉相承——在上下文预算允许时,原始历史 > 摘要
  4. 能力可解耦:mixed-refine(弱模型生成 + 强模型反馈修订)说明"生成"和"反馈+修订"可以拆到不同模型上——这是一个便宜的工程 trick,也提示了"评判"是更吃能力的那一环。

在我的工作中能怎么用

开放问题 / 疑问

局限性(对本文的批判)