第四章 智能体经典范式构建
第四章 智能体经典范式构建
我们遵循“是什么、为什么 、怎么办”的 思路,对ReAct、Plan-and-Slove、Reflaction三种常见的范式进行分析
ReAct
ReAct是什么
ReAct(Reason+Act)是第一个,也是最经典的智能体范式.其核心是模仿人类 解决问题的方式,将推理reasoning与行动Acting显式地结合起来,形成一个思考-行动-观察的循环.推理使得行动 更具目的性,而行动为推理提供了事实依据
为什么需要ReAct
解决此前纯思考或纯行动的缺陷,既避免了因无法与外部交互而产生事实幻觉,又具有执行和规划纠错的能力.
ReAct的适用场景
- 需要外部知识的任务
- 需要精确计算的任务
- 需要与API交互的任务
ReAct的编码实现
-
系统提示词设计
包含角色定义/工具清单/格式规约/动态上下文
-
核心循环的实现
-
输出解析器的实现
-
工具执行与调用
-
观测结果的整合
-
运行实例与分析
提示词模版如下:
# ReAct 提示词模板
REACT_PROMPT_TEMPLATE = """
请注意,你是一个有能力调用外部工具的智能助手。
可用工具如下:
{tools}
请严格按照以下格式进行回应:
Thought: 你的思考过程,用于分析问题、拆解任务和规划下一步行动。
Action: 你决定采取的行动,必须是以下格式之一:
- `{{tool_name}}[{{tool_input}}]`:调用一个可用工具。
- `Finish[最终答案]`:当你认为已经获得最终答案时。
- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在Action:字段后使用 finish(answer="...") 来输出最终答案。
现在,请开始解决以下问题:
Question: {question}
History: {history}
"""
ReAct的特点 /局限性/调试技巧
ReAct的主要特点
- 高可解释性
- 动态规划与纠错能力
- 工具协同能力
ReAct的固有局限性
- 对LLM自身能力的强依赖
- 执行效率问题
- 提示词的脆弱性
- 可能陷入局部最优解
调试技巧
- 检查完整的提示词
- 分析原始输出
- 验证工具的输入与输出
- 调整提示词中的示例(Few-shot Prompting)
Plan-and-Slove
Plan-and-Slove是什么
Plan-and-Slove将任务分成两个阶段-先计划,后执行
- 规划阶段:首先,智能体会接受用户的完整问题.第一个任务不是直接去解决问题或调用工具,而是将问题分解,并制定出一个清晰,分步骤的行动计划.这个计划本身就是一次大语言模型的调用产物
- 执行阶段:在获得完整的计划后,智能体进入执行阶段.它会严格按照计划中的步骤,逐一执行.每一步执行都可能是一次独立的LLM调用,或是对上一步结果的加工处理,直到计划中所有步骤都完成,最终得出答案.
为什么需要Plan-and-Solve
思维链在处理多步骤,复杂问题时容易偏离轨道;Plan-and-Solve这种"谋定而后动的策略",使得智能体在处理需要长远规划的复杂任务时,能够保持更高的目标一致性,避免在中间步骤中迷失方向.
Plan-and-Solve的适用场景
尤其适用于那些结构性强/可以被清晰分解的复杂任务,例如
- 多步数学应用题
- 需要整合多个信息源的报告撰写
- 代码生成任务
plan-and-Solve的工作流程
规划阶段
此阶段的目标是让大语言模型接收原始问题,并输出一个清晰/分步骤的行动计划.这个计划必须是结构化的,以便我们的代码可以轻松解析并逐一执行.
因此,我们设计的提示词需要明确地告诉模型它的角色和任务,并给出一个输出格式的范例.提示词依旧包含以下部分
- 角色设定
- 任务描述
- 格式约束
然后,将这个提示词逻辑封装成一个类,也就是我们的规划器
PLANNER_PROMPT_TEMPLATE = """
你是一个顶级的AI规划专家。你的任务是将用户提出的复杂问题分解成一个由多个简单步骤组成的行动计划。
请确保计划中的每个步骤都是一个独立的、可执行的子任务,并且严格按照逻辑顺序排列。
你的输出必须是一个Python列表,其中每个元素都是一个描述子任务的字符串。
问题: {question}
请严格按照以下格式输出你的计划,```python与```作为前后缀是必要的:
```python
["步骤1", "步骤2", "步骤3", ...]
```
"""
执行阶段
在规划器生成行动计划后,需要执行器来逐一完成计划中的任务.
执行器不仅负责调用大语言模型来解决子问题,还包含一个至关重要的角色--状态管理.它必须记录每一步的执行结果,将其作为上下文提供给后续步骤,确保信息在整个任务链条中顺畅流动.
总的来说,规划器的目标是分解问题,执行器的目标是,在已有的上下文基础上,专注解决当前这一个步骤.
提示词需要包含以下关键信息:
- 原始问题
- 完整计划
- 历史步骤与结果
- 当前步骤
EXECUTOR_PROMPT_TEMPLATE = """
你是一位顶级的AI执行专家。你的任务是严格按照给定的计划,一步步地解决问题。
你将收到原始问题、完整的计划、以及到目前为止已经完成的步骤和结果。
请你专注于解决“当前步骤”,并仅输出该步骤的最终答案,不要输出任何额外的解释或对话。
# 原始问题:
{question}
# 完整计划:
{plan}
# 历史步骤与结果:
{history}
# 当前步骤:
{current_step}
请仅输出针对“当前步骤”的回答:
"""
Reflection
什么是Reflection
Reflection的灵感来源于人类的学习过程:执行-->反思-->优化.
- 执行:首先,智能体用已有的方法尝试完成任务,生成一个初步的解决方案或行动轨迹.
- 反思:调用一个独立的,或带有特殊提示词的大语言模型实例,来审视第一步的结果,并从多个维度进行评估,例如
- 事实性错误
- 逻辑漏洞
- 效率问题
- 遗漏信息
- 优化:最后,将第一次的生成结果和反馈作为新的上下文,再次调用模型,要求其根据反馈内容对第一次的生成结果进行修正,给出更完善的"修订稿"
为什么需要Reflection
在前两个范式中,智能体一旦完成任务,整个流程即结束,而结果可能存在谬误或不足.Reflection为智能体引入了一种事后的自我修正循环,进行迭代优化.
与前两种范式相比,Reflection 的价值在于:
- 它为智能体提供了一个内部纠错回路,使其不再完全依赖于外部工具的反馈(ReAct 的 Observation),从而能够修正更高层次的逻辑和策略错误。
- 它将一次性的任务执行,转变为一个持续优化的过程,显著提升了复杂任务的最终成功率和答案质量。
- 它为智能体构建了一个临时的“短期记忆”。整个“执行-反思-优化”的轨迹形成了一个宝贵的经验记录,智能体不仅知道最终答案,还记得自己是如何从有缺陷的初稿迭代到最终版本的。更进一步,这个记忆系统还可以是多模态的,允许智能体反思和修正文本以外的输出(如代码、图像等),为构建更强大的多模态智能体奠定了基础。
Reflection的适用场景
以代码生成和迭代优化问题为例
- 存在明确的优化路径:大语言模型初次生成的代码很可能是一个简单但效率低下的递归实现。
- 反思点清晰:可以通过反思发现其“时间复杂度过高”或“存在重复计算”的问题。
- 优化方向明确:可以根据反馈,将其优化为更高效的迭代版本或使用备忘录模式的版本。
Reflection的编码实现
-
提示词设计
-
初始执行提示词
INITIAL_PROMPT_TEMPLATE = """ 你是一位资深的Python程序员。请根据以下要求,编写一个Python函数。 你的代码必须包含完整的函数签名、文档字符串,并遵循PEP 8编码规范。 要求: {task} 请直接输出代码,不要包含任何额外的解释。 """ -
反思提示词
REFLECT_PROMPT_TEMPLATE = """ 你是一位极其严格的代码评审专家和资深算法工程师,对代码的性能有极致的要求。 你的任务是审查以下Python代码,并专注于找出其在<strong>算法效率</strong>上的主要瓶颈。 # 原始任务: {task} # 待审查的代码: ```python {code} ``` 请分析该代码的时间复杂度,并思考是否存在一种<strong>算法上更优</strong>的解决方案来显著提升性能。 如果存在,请清晰地指出当前算法的不足,并提出具体的、可行的改进算法建议(例如,使用筛法替代试除法)。 如果代码在算法层面已经达到最优,才能回答“无需改进”。 请直接输出你的反馈,不要包含任何额外的解释。 """ -
优化提示词
REFINE_PROMPT_TEMPLATE = """ 你是一位资深的Python程序员。你正在根据一位代码评审专家的反馈来优化你的代码。 # 原始任务: {task} # 你上一轮尝试的代码: {last_code_attempt} 评审员的反馈: {feedback} 请根据评审员的反馈,生成一个优化后的新版本代码。 你的代码必须包含完整的函数签名、文档字符串,并遵循PEP 8编码规范。 请直接输出优化后的代码,不要包含任何额外的解释。 """
-
-
智能体封装和实现
浙公网安备 33010602011771号