跳到主要内容

后退式提示

定义

后退式提示(Step-back Prompting)是由 Zheng 等人(2023)在谷歌 DeepMind 提出的两步提示词技术。其核心思想看似简单:在要求模型回答一个具体的、可能很难的问题之前,先问它同一问题的更抽象、更高层次的版本——然后将模型对该抽象问题的回答作为背景,来回答原始问题。该技术基于一个观察:大型语言模型在具体事实或推理问题上的失败,往往不是因为缺乏相关知识,而是因为问题的具体性在模型内部表征中激活了错误的"检索上下文"。后退到更高的抽象层次激活了更广泛、更可靠的知识,从而支撑最终答案。

后退式提示的洞察源于专家处理难题的方式。一位物理学家被问到"在恒定体积下,气体温度升高时压力会发生什么变化?"时,可能会先回想理想气体定律(PV = nRT)作为一般背景,然后将其应用于具体情况——而非直接跳到答案,冒着混淆变量的风险。后退式提示指示模型做同样的事情:生成支撑具体问题的一般原理或概念,然后从该原理出发推导出答案。这有效地增加了一个概念性脚手架步骤,减少了表面模式匹配导致错误答案的可能性。

在原始论文中,后退式提示通过少样本示例来演示,这些示例教会模型如何针对给定领域适当地"后退"。对于物理问题,抽象问题通常要求相关的物理定律或原理。对于历史问题,它要求更广泛的历史背景。对于医学问题,它要求相关的生理学知识。该技术与模型无关,不需要微调——它纯粹是提示词层面的干预。在 MMLU 和 TimeQA 基准上,后退式提示在困难的、知识密集型问题上优于标准思维链和检索增强基准。

工作原理

步骤 1 — 生成抽象问题

第一步是提示模型识别一个包含原始问题的更高层次问题。这通常通过包含领域特定(具体问题、抽象问题)对示例的少样本提示词来完成。例如,如果原始问题是"砷化镓的熔点是多少?",抽象问题可能是"III-V 族半导体的热力学和晶体学特性是什么?"抽象问题应足够宽泛以激活广泛的相关知识,但又不能过于宽泛而缺乏信息量。找到正确的抽象层次是主要的提示词工程挑战,少样本示例对于引导模型到特定领域适当抽象层次至关重要。

步骤 2 — 回答抽象问题

生成抽象问题后,模型回答它。该答案通常采用一般原理、定义、物理定律或相关背景上下文摘要的形式。这一步的关键特性是,抽象问题通常比原始具体问题更容易让模型可靠地回答——它激活了经过充分学习的、基于事实的表征,而非更容易产生幻觉的边缘案例或具体数值事实。抽象问题的答案成为约束和指导最终推理步骤的上下文块。

步骤 3 — 使用抽象作为上下文回答原始问题

最后一步将抽象原理与原始具体问题合并在一个提示词中:"给定此背景:[抽象答案],回答具体问题:[原始问题]。"模型现在从坚实的概念基础出发进行推理,而不是试图直接检索具体事实。这降低了知识密集型问题中幻觉的风险,并提高了多步推理的逻辑一致性。在原始论文中,这最后一步也使用了思维链,使后退式提示可以与 CoT 组合:抽象步骤奠定推理基础,CoT 使其明确。

何时使用 / 何时不适用

适合使用不适合使用
问题需要模型容易产生幻觉的具体事实知识直接提示已经可靠工作的简单问题
领域有从一般原理到具体实例的清晰层次(物理、化学、历史)难以定义抽象问题——没有自然的一般/具体区分的任务
模型在具体问题上回答不一致,但在一般原理上可靠延迟至关重要——两次大型语言模型调用使响应时间加倍
你想在不使用 RAG 的情况下减少知识密集型基准上的幻觉问题纯粹是数学或符号性的——仅 CoT 通常就足够了
领域的少样本示例可用于教模型如何后退令牌预算紧张——抽象答案会向最终提示词添加令牌

对比

标准后退式提示思维链(CoT)自一致性
大型语言模型调用次数2(抽象 + 最终)1N(通常 10-40)
核心机制抽象到接地到推理明确的逐步推理多条独立路径 + 多数投票
主要优势减少知识密集型问题中的幻觉提升多步逻辑推理减少推理结果中的方差
成本基准的 2 倍基准的 1 倍基准的 N 倍
需要少样本示例是——教授后退行为是——效果最佳时是——作为基础提示词的少样本 CoT
最佳任务类型知识密集型问答、科学、历史数学、逻辑、代码数学、符号推理、事实问答
可与 CoT 组合是——推荐同时使用N/A是——基础提示词使用 CoT
注意与自一致性互补;两者可叠加以获得进一步收益更简单的基准——先于后退式提示尝试更昂贵;当高准确率证明 N 倍成本合理时使用

代码示例

使用 OpenAI 的后退式提示——双调用实现

# Step-back prompting: abstraction-then-answer, two API calls
# pip install openai

import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

STEP_BACK_FEW_SHOT = """Help identify a broader abstract question underpinning a specific one.

Original: At what temperature does gallium arsenide melt?
Step-back: What are the thermodynamic properties of III-V semiconductors?

Original: What was the immediate cause of the US entering World War I?
Step-back: What geopolitical tensions shaped US foreign policy before WWI?

Original: Patient has peripheral edema, elevated JVP, orthopnea. Diagnosis?
Step-back: What are the hallmark signs of right-sided and left-sided heart failure?

Original: {question}
Step-back:"""

GROUNDED = """Using the background context below, answer the specific question step by step.

Background (general principles):
{background}

Specific question:
{question}

Let's think step by step:"""


def generate_step_back(question: str) -> str:
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": STEP_BACK_FEW_SHOT.format(question=question)}],
temperature=0, max_tokens=150,
)
return resp.choices[0].message.content.strip()


def answer_abstract(abstract_q: str) -> str:
resp = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "Answer with accurate background principles (3-5 sentences)."},
{"role": "user", "content": abstract_q},
],
temperature=0, max_tokens=300,
)
return resp.choices[0].message.content.strip()


def answer_with_step_back(question: str) -> str:
abstract_q = generate_step_back(question)
background = answer_abstract(abstract_q)
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": GROUNDED.format(
background=background, question=question)}],
temperature=0, max_tokens=500,
)
return resp.choices[0].message.content.strip()


if __name__ == "__main__":
q = "Why did Soviet collectivization in the early 1930s lead to famine in Ukraine?"
print(answer_with_step_back(q))

使用 Anthropic 的后退式提示——带结构化输出的单次调用

# Step-back prompting in one Anthropic call: structured three-part format
# pip install anthropic

import os
import anthropic

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

SYSTEM = """You are an expert reasoning assistant. For each question, respond in three parts:

## Abstract question:
A broader, general question capturing the underlying principle.

## Background context:
Answer the abstract question with relevant principles and definitions (3-5 sentences).

## Final answer:
Use the background to reason step-by-step to the specific answer."""

EXAMPLE = [
{"role": "user", "content": "Ideal gas: 2 mol, 300 K, 0.05 m^3. What is the pressure?"},
{"role": "assistant", "content": """## Abstract question:
What is the ideal gas law and how does it relate P, V, n, and T?

## Background context:
PV = nRT, where P is pressure (Pa), V is volume (m^3), n is moles, R = 8.314 J/mol/K, T is Kelvin. Rearranged: P = nRT / V.

## Final answer:
P = (2 x 8.314 x 300) / 0.05 = 99,768 Pa (about 0.985 atm)."""},
]


def step_back(question: str) -> str:
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=800,
system=SYSTEM,
messages=EXAMPLE + [{"role": "user", "content": question}],
)
return response.content[0].text


if __name__ == "__main__":
q = "A patient is given furosemide. How does it cause hypokalemia?"
print(step_back(q))

实用资源

另请参阅