英文原地址:Chapter 4: Reflection
概述
在前面的章节中,我们探讨了基础的智能体模式:用于顺序执行的链式(Chaining)、用于动态路径选择的路由(Routing),以及用于并发任务执行的并行化(Parallelization)。这些模式使智能体能够更高效、更灵活地执行复杂任务。然而,即使拥有复杂的工作流,智能体的初始输出或计划也可能并不最佳、准确或完整。这正是反思(Reflection)模式发挥作用的地方。
反思模式涉及智能体评估其自身的工作、输出或内部状态,并利用这一评估来提升其表现或优化其回应。这是一种自我纠正或自我改进的形式,使智能体能够基于反馈、内部批判或与期望标准的对比,迭代地完善其输出或调整其方法。反思有时也可以由一个独立的智能体来协助,其特定角色是分析初始智能体的输出
与简单的顺序链(输出直接传递到下一步)或选择路径的路由不同,反思引入了反馈循环。智能体不只是产生一个输出;它随后还会审视该输出(或生成它的过程),识别潜在问题或可改进之处,并利用这些见解生成更佳版本或调整其未来行动。
该过程通常包括:
- 执行: 智能体执行任务或生成初始输出。
- 评估/批评: 智能体(通常使用另一次 LLM 调用或一组规则)分析前一步的结果。此评估可能检查事实准确性、连贯性、风格、完整性、对指令的遵循程度或其他相关标准。
- 反思/优化: 基于评估意见,智能体确定如何改进。这可能包括生成优化后的输出、为后续步骤调整参数,甚至修改整体计划。
- 迭代(可选但常见): 随后可以执行优化后的输出或调整后的方法,并重复反思过程,直至获得满意结果或满足停止条件。 ⠀ 反思模式的一种关键且高效的实现方式是将流程划分为两个不同的逻辑角色:生产者和评估者。这通常被称为“生产者-批评者”或“生产者-审阅者”模型。尽管单个智能体可以进行自我反思,但使用两个专门的智能体(或使用两个具有不同系统提示的独立 LLM 调用)通常能产生更稳健且更少偏见的结果。
1. 生产者(Producer Agent): 该智能体的首要职责是执行任务的初始步骤。它专注于内容生成,无论是编写代码、起草博客文章,还是制定计划。它接收初始提示并产出第一版输出。
2. 评估者(Critic Agent): 该智能体的唯一目的在于评估由生产者生成的输出。它会接收一套不同的指令,通常具备一个独立的人设(例如:“你是一名资深软件工程师”、“你是一位一丝不苟的事实核查员”)。评估者的指令引导其依据特定标准分析生产者的工作,例如事实准确性、代码质量、文体要求或完整性。它的设计目标是发现缺陷、提出改进建议,并提供结构化反馈。
这种关注点的分离之所以强大,是因为它避免了智能体审阅自身工作时的“认知偏见”。评估者以全新的视角审视输出,专注于发现错误和改进空间。评估者的反馈随后会回传给生产者,作为其生成新的、更加精炼版本输出的指导。所提供的 LangChain 和 ADK 代码示例均实现了这种双智能体模型:LangChain 示例使用特定的“reflector_prompt”来创建批评者人设,而 ADK 示例则明确地定义了一个生产者和一个评估者。
实现反思通常需要对智能体的工作流程进行结构化,以纳入这些反馈回路。这可以通过代码中的迭代循环实现,或使用支持状态管理并能根据评估结果进行条件转换的框架来实现。尽管在 LangChain/LangGraph、ADK 或 Crew.AI 链中都可以实现单步的评估与改进,但真正的迭代式反思通常需要更复杂的编排。
反思模式对于构建能够产出高质量输出、处理细微任务、并展现一定自我意识与适应性的智能体至关重要。它能使智能超越简单执行指令,迈向更为复杂的问题解决与内容生成方式。
反思与目标设定和监控(参见第 11 章)的交叉点值得注意。目标为智能体的自我评估提供最终基准,而监控则跟踪其进展。在许多实际场景中,反思可以充当纠偏引擎,利用监控到的反馈分析偏差并调整其策略。这种协同作用将智能体从被动的执行者转变为有目的性的系统,使其自适应地努力实现目标。
此外,当 LLM 保留对话记忆(参见第 8 章)时,反思模式的有效性会显著增强。该对话历史为评估阶段提供关键上下文,使智能体不仅能将其输出单独评估,还能在先前交互、用户反馈和不断演进的目标背景下进行考量。它使智能体能够从过去的批评中学习,避免重复错误。没有记忆时,每次反思都是一个自成一体的事件;有了记忆,反思成为一个累积的过程,每个循环都建立在前一次的基础上,带来更智能且具有上下文意识的改进。
实际应用与使用场景
当输出质量、准确性或对复杂约束的遵循至关重要时,反思模式具有重要价值:
1. 创意写作与内容生成
打磨生成的文本、故事、诗歌或营销文案。
- 用例: 一个正在撰写博客文章的智能体。
- 反思: 先生成草稿,评估其流畅性、语气和清晰度,然后根据评估结果重写。重复这一过程,直到文章达到质量标准。
- 好处: 产出更加精炼且更有效的内容。
2. 代码生成与调试
编写代码、识别错误并修复它们。
- 用例: 一个正在编写 Python 函数的智能体。
- 反思: 编写初始代码,运行测试或静态分析,识别错误或低效之处,然后根据发现修改代码。
- 好处: 生成更健壮、功能更完善的代码。
3. 复杂问题求解
在多步推理任务中评估中间步骤或拟议的解决方案。
- 用例: 一个正在解决逻辑谜题的智能体。
- 反思: 提出一个步骤,评估它是否使我们更接近解决方案或引入矛盾,必要时回溯或选择不同的步骤。
- 好处: 提升智能体在复杂问题空间中导航的能力。
4. 总结与信息综合
对摘要进行优化,以确保准确、完整且简洁。
- 用例: 一个正在总结一篇长文档的智能体。
- 反思: 先生成初始摘要,与原文的关键点进行对照,完善摘要以补充遗漏信息或提升准确性。
- 好处: 生成更准确且更全面的摘要。
5. 规划与策略
评估一项提议的计划,并识别潜在的缺陷或改进点。
- 用例: 一个智能体规划一系列行动以达成目标。
- 反思: 制定一个计划,模拟其执行或根据约束评估其可行性,并根据评估结果修订计划。
- 好处: 制定更有效且更现实的计划。
6. 会话智能体
回顾会话中的先前轮次以保持上下文、纠正误解或提升回复质量。
- 用例: 客服聊天机器人。
- 反思: 在用户回复之后,回顾对话历史和上一次生成的消息,以确保连贯性并准确回应用户的最新输入。
- 好处: 带来更自然且更有效的对话。
反思为智能体系统增加了元认知层,使其能够从自身的输出与过程里学习,从而带来更智能、更可靠和更高质量的结果。
实战代码示例(LangChain)
要实现一个完整的、迭代的反思流程,需要具备状态管理和循环执行的机制。尽管这些在如 LangGraph 等基于图的框架中是原生处理的,或者可通过自定义过程式代码来实现,但单次反思循环的基本原理可以通过 LCEL(LangChain Expression Language)的组合式语法有效展示。
此示例使用 Langchain 库和 OpenAI 的 GPT-4o 模型实现了一个反思循环,用于迭代生成并完善一个计算整数阶乘的 Python 函数。流程从任务提示开始,生成初始代码,然后在每次迭代中基于模拟的高级软件工程师角色的批评意见对代码进行反思与改进,直到批评阶段判断代码已完美或达到最大迭代次数为止。最后,它会打印出最终优化后的代码。
首先,确保已安装所需的库:
pip install langchain langchain-community langchain-openai
你还需要使用所选语言模型的 API 密钥(例如 OpenAI、Google Gemini、Anthropic)来配置你的运行环境。
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage
# --- Configuration ---
# Load environment variables from .env file (for OPENAI_API_KEY)
load_dotenv()
# Check if the API key is set
if not os.getenv("OPENAI_API_KEY"):
raise ValueError("OPENAI_API_KEY not found in .env file. Please add it.")
# Initialize the Chat LLM. We use gpt-4o for better reasoning.
# A lower temperature is used for more deterministic outputs.
llm = ChatOpenAI(model="gpt-4o", temperature=0.1)
def run_reflection_loop():
"""
Demonstrates a multi-step AI reflection loop to progressively improve a Python function.
"""
# --- The Core Task ---
task_prompt = """
Your task is to create a Python function named `calculate_factorial`.
This function should do the following:
1. Accept a single integer `n` as input.
2. Calculate its factorial (n!).
3. Include a clear docstring explaining what the function does.
4. Handle edge cases: The factorial of 0 is 1.
5. Handle invalid input: Raise a ValueError if the input is a negative number.
"""
# --- The Reflection Loop ---
max_iterations = 3
current_code = ""
# We will build a conversation history to provide context in each step.
message_history = [HumanMessage(content=task_prompt)]
for i in range(max_iterations):
print("\n" + "="*25 + f" REFLECTION LOOP: ITERATION {i + 1} " + "="*25)
# --- 1. GENERATE / REFINE STAGE ---
# In the first iteration, it generates. In subsequent iterations, it refines.
if i == 0:
print("\n>>> STAGE 1: GENERATING initial code...")
# The first message is just the task prompt.
response = llm.invoke(message_history)
current_code = response.content
else:
print("\n>>> STAGE 1: REFINING code based on previous critique...")
# The message history now contains the task,
# the last code, and the last critique.
# We instruct the model to apply the critiques.
message_history.append(HumanMessage(content="Please refine the code using the critiques provided."))
response = llm.invoke(message_history)
current_code = response.content
print("\n--- Generated Code (v" + str(i + 1) + ") ---\n" + current_code)
message_history.append(response) # Add the generated code to history
# --- 2. REFLECT STAGE ---
print("\n>>> STAGE 2: REFLECTING on the generated code...")
# Create a specific prompt for the reflector agent.
# This asks the model to act as a senior code reviewer.
reflector_prompt = [
SystemMessage(content="""
You are a senior software engineer and an expert
in Python.
Your role is to perform a meticulous code review.
Critically evaluate the provided Python code based
on the original task requirements.
Look for bugs, style issues, missing edge cases,
and areas for improvement.
If the code is perfect and meets all requirements,
respond with the single phrase 'CODE_IS_PERFECT'.
Otherwise, provide a bulleted list of your critiques.
"""),
HumanMessage(content=f"Original Task:\n{task_prompt}\n\nCode to Review:\n{current_code}")
]
critique_response = llm.invoke(reflector_prompt)
critique = critique_response.content
# --- 3. STOPPING CONDITION ---
if "CODE_IS_PERFECT" in critique:
print("\n--- Critique ---\nNo further critiques found. The code is satisfactory.")
break
print("\n--- Critique ---\n" + critique)
# Add the critique to the history for the next refinement loop.
message_history.append(HumanMessage(content=f"Critique of the previous code:\n{critique}"))
print("\n" + "="*30 + " FINAL RESULT " + "="*30)
print("\nFinal refined code after the reflection process:\n")
print(current_code)
if __name__ == "__main__":
run_reflection_loop()
代码首先通过设置环境、加载 API 密钥,并以低温度初始化如 GPT-4o 这类强大的语言模型,以获得更聚焦的输出。核心任务由一个提示定义:请求编写一个用于计算数字阶乘的 Python 函数,包含对文档字符串的具体要求、对边界情况(0 的阶乘)的处理,以及对负数输入的错误处理。run_reflection_loop 函数负责协调迭代式的改进过程。在循环中,第一轮由语言模型根据任务提示生成初始代码;在随后的迭代中,它会基于上一步的评审意见对代码进行改进。一个独立的“反思者”角色(同样由语言模型扮演,但使用不同的系统提示)作为高级软件工程师,从原始任务要求出发审查生成的代码。该审查以项目符号列表的形式给出问题,或者在没有问题时返回短语“CODE_IS_PERFECT”。循环将持续,直到审查表明代码完美,或达到最大迭代次数为止。 对话历史会在每一步被保留并传递给语言模型,为生成/改进阶段和反思阶段提供上下文。最后,脚本在循环结束后打印最后生成的代码版本。
实战代码示例(ADK)
现在让我们看看一个使用 Google ADK 实现的概念性代码示例。具体来说,代码通过采用 Generator-Critic 结构来展示这一点,其中一个组件(Generator)生成初始结果或计划,另一个组件(Critic)提供关键性反馈或评审,引导 Generator 得到更精炼或更准确的最终输出。
from google.adk.agents import SequentialAgent, LlmAgent
# The first agent generates the initial draft.
generator = LlmAgent(
name="DraftWriter",
description="Generates initial draft content on a given subject.",
instruction="Write a short, informative paragraph about the user's subject.",
output_key="draft_text" # The output is saved to this state key.
)
# The second agent critiques the draft from the first agent.
reviewer = LlmAgent(
name="FactChecker",
description="Reviews a given text for factual accuracy and provides a structured critique.",
instruction="""
You are a meticulous fact-checker.
1. Read the text provided in the state key 'draft_text'.
2. Carefully verify the factual accuracy of all claims.
3. Your final output must be a dictionary containing two keys:
- "status": A string, either "ACCURATE" or "INACCURATE".
- "reasoning": A string providing a clear explanation for your status, citing specific issues if any are found.
""",
output_key="review_output" # The structured dictionary is saved here.
)
# The SequentialAgent ensures the generator runs before the reviewer.
review_pipeline = SequentialAgent(
name="WriteAndReview_Pipeline",
sub_agents=[generator, reviewer]
)
# Execution Flow:
# 1. generator runs -> saves its paragraph to state['draft_text'].
# 2. reviewer runs -> reads state['draft_text'] and saves its dictionary output to state['review_output'].
此代码演示了在 Google ADK 中使用顺序智能体流水线进行文本生成与审阅。它定义了两个 LlmAgent 实例:generator 和 reviewer。generator 智能体用于围绕给定主题创建初稿段落。它被指示写一篇简短且信息丰富的文本,并将其输出保存到状态键 draft_text。reviewer 智能体作为对 generator 生成文本的事实核查者。它被指示从 draft_text 读取文本并验证其事实准确性。reviewer 的输出是一个包含两个键的结构化字典:status 和 reasoning。status 表示文本是“ACCURATE”还是“INACCURATE”,而 reasoning 提供该结论的解释。该字典被保存到状态键 review_output。一个名为 review_pipeline 的 SequentialAgent 被创建以管理两个智能体的执行顺序。它确保先运行 generator,然后是 reviewer。整体执行流程是 generator 生成文本,随后将其保存到状态中。 随后,审阅者会从状态中读取这段文本,对其进行事实核查,并将其发现(状态和推理)保存回状态中。该流程允许使用独立的智能体来进行结构化的内容创作与审阅。注意:对于感兴趣的用户,也提供了一个使用 ADK 的 LoopAgent 的替代实现。
在结束之前,重要的是要考虑到,尽管反思模式显著提升了输出质量,但它也存在重要的权衡。该迭代过程虽然强大,却可能导致更高的成本和延迟,因为每一次改进循环都可能需要一次新的 LLM 调用,这使其不太适合对时间敏感的应用。此外,该模式对内存的消耗很大;随着每次迭代,会话历史会不断扩张,包括初始输出、批评意见以及后续的改进内容。
概览
是什么(What)
智能体的初始输出往往并不理想,可能存在不准确、不完整,或无法满足复杂需求的问题。基础的智能体工作流缺乏让智能体识别并修正自身错误的内置机制。通过让智能体评估自己的工作,或更稳健地引入一个独立的逻辑智能体作为评估者,可以解决这一问题,从而无论初始响应质量如何,都不会将其作为最终答案。
为什么(Why)
反思(Reflection)模式通过引入自我纠错与精炼的机制提供了解决方案。它建立了一个反馈循环:由“生产者”智能体生成输出,然后由“评估者”智能体(或生产者自身)依据预设标准进行评估。随后利用该评估来生成改进版本。这个生成—评估—精炼的迭代过程会逐步提升最终结果的质量,使结果更准确、连贯且更可靠。
经验法则(Rule of Thumb)
当最终输出的质量、准确性和细节比速度和成本更重要时,使用“反思”模式。它对生成精心打磨的长篇内容、编写与调试代码以及制定详细计划等任务尤其有效。当任务需要高度客观性或专业化评估,而通用的生成智能体可能忽略关键点时,应引入独立的评估智能体。
反射设计模式-自我反思
反思设计模式-生产者与评估者
关键点
- “反思”模式的主要优势在于它能够迭代地自我纠错和打磨输出,从而显著提升质量、准确性,并更好地遵循复杂指令。
- 它包含执行、评估/批评与改进的反馈循环。对于需要高质量、高准确性或细腻表达的任务,“反思”至关重要。
- 一种强大的实现是“生产者-评估者”模型,其中一个单独的智能体(或通过提示指定的角色)对初始输出进行评估。这种关注点分离提升了客观性,并允许更专业、结构化的反馈。
- 然而,这些优势的代价是增加的延迟和计算开销,同时也更容易超出模型的上下文窗口,或被 API 服务限流。
- 尽管完整的迭代反思通常需要有状态的工作流(如 LangGraph),但可以在 LangChain 中使用 LCEL 通过单次反思步骤,将输出传递用于评估并进行后续改进。
- Google ADK 可以通过顺序化的工作流来促进反思:一个智能体的输出由另一个智能体进行评析,从而允许后续的优化步骤。
- 这种模式使智能体能够进行自我纠正,并随着时间的推移提升其性能。
总结
反思模式为智能体的工作流提供了一种关键的自我纠正机制,使其能够超越单次执行进行迭代改进。其实现方式是创建一个循环:系统生成输出,根据特定标准对其进行评估,然后利用该评估产出更为精炼的结果。该评估可以由智能体自身完成(自我反思),或者更常见、更有效地由一个独立的评审智能体完成,这构成了该模式中的一个关键架构选择。
虽然一个完全自主的多步反思过程需要强大的状态管理架构,但其核心原理可以通过单次“生成—评估—优化”的循环有效地展现。作为一种控制结构,反思可以与其他基础模式相结合,以构建更稳健、功能更复杂的智能体系统。
参考资料
- Training Language Models to Self-Correct via Reinforcement Learning, arxiv.org/abs/2409.12…
- LangChain Expression Language (LCEL) Documentation: python.langchain.com/docs/introd…
- LangGraph Documentation:www.langchain.com/langgraph
- Google Agent Developer Kit (ADK) Documentation (Multi-Agent Systems): google.github.io/adk-docs/ag…