Plan-and-Solve在我们掌握了 ReAct 这种反应式的、步进决策的智能体范式后接下来将探讨一种风格迥异但同样强大的方法Plan-and-Solve。顾名思义这种范式将任务处理明确地分为两个阶段先规划 (Plan)后执行 (Solve)。如果说 ReAct 像一个经验丰富的侦探根据现场的蛛丝马迹Observation一步步推理随时调整自己的调查方向那么 Plan-and-Solve 则更像一位建筑师在动工之前必须先绘制出完整的蓝图Plan然后严格按照蓝图来施工Solve。事实上我们现在用的很多大模型工具的Agent模式都融入了这种设计模式。4.3.1 Plan-and-Solve 的工作原理Plan-and-Solve Prompting 由 Lei Wang 在2023年提出[2]。其核心动机是为了解决思维链在处理多步骤、复杂问题时容易“偏离轨道”的问题。与 ReAct 将思考和行动融合在每一步不同Plan-and-Solve 将整个流程解耦为两个核心阶段如图4.2所示规划阶段 (Planning Phase) 首先智能体会接收用户的完整问题。它的第一个任务不是直接去解决问题或调用工具而是将问题分解并制定出一个清晰、分步骤的行动计划。这个计划本身就是一次大语言模型的调用产物。执行阶段 (Solving Phase) 在获得完整的计划后智能体进入执行阶段。它会严格按照计划中的步骤逐一执行。每一步的执行都可能是一次独立的 LLM 调用或者是对上一步结果的加工处理直到计划中的所有步骤都完成最终得出答案。import os import ast from agent_client import HelloAgentsLLM from dotenv import load_dotenv from typing import List, Dict # 加载 .env 文件中的环境变量处理文件不存在异常 try: load_dotenv() except FileNotFoundError: print(警告未找到 .env 文件将使用系统环境变量。) except Exception as e: print(f警告加载 .env 文件时出错: {e}) # --- 1. LLM客户端定义 --- # 假设你已经有llm_client.py文件里面定义了HelloAgentsLLM类 # --- 2. 规划器 (Planner) 定义 --- PLANNER_PROMPT_TEMPLATE 你是一个顶级的AI规划专家。你的任务是将用户提出的复杂问题分解成一个由多个简单步骤组成的行动计划。 请确保计划中的每个步骤都是一个独立的、可执行的子任务并且严格按照逻辑顺序排列。 你的输出必须是一个Python列表其中每个元素都是一个描述子任务的字符串。 问题: {question} 请严格按照以下格式输出你的计划python与作为前后缀是必要的: python [步骤1, 步骤2, 步骤3, ...] class Planner: def __init__(self, llm_client: HelloAgentsLLM): self.llm_client llm_client def plan(self, question: str) - list[str]: prompt PLANNER_PROMPT_TEMPLATE.format(questionquestion) messages [{role: user, content: prompt}] print(--- 正在生成计划 ---) response_text self.llm_client.think(messagesmessages) or print(f✅ 计划已生成:\n{response_text}) try: plan_str response_text.split(python)[1].split()[0].strip() plan ast.literal_eval(plan_str) return plan if isinstance(plan, list) else [] except (ValueError, SyntaxError, IndexError) as e: print(f❌ 解析计划时出错: {e}) print(f原始响应: {response_text}) return [] except Exception as e: print(f❌ 解析计划时发生未知错误: {e}) return [] # --- 3. 执行器 (Executor) 定义 --- EXECUTOR_PROMPT_TEMPLATE 你是一位顶级的AI执行专家。你的任务是严格按照给定的计划一步步地解决问题。 你将收到原始问题、完整的计划、以及到目前为止已经完成的步骤和结果。 请你专注于解决“当前步骤”并仅输出该步骤的最终答案不要输出任何额外的解释或对话。 # 原始问题: {question} # 完整计划: {plan} # 历史步骤与结果: {history} # 当前步骤: {current_step} 请仅输出针对“当前步骤”的回答: class Executor: def __init__(self, llm_client: HelloAgentsLLM): self.llm_client llm_client def execute(self, question: str, plan: list[str]) - str: history final_answer print(\n--- 正在执行计划 ---) for i, step in enumerate(plan, 1): print(f\n- 正在执行步骤 {i}/{len(plan)}: {step}) prompt EXECUTOR_PROMPT_TEMPLATE.format( questionquestion, planplan, historyhistory if history else 无, current_stepstep ) messages [{role: user, content: prompt}] response_text self.llm_client.think(messagesmessages) or history f步骤 {i}: {step}\n结果: {response_text}\n\n final_answer response_text print(f✅ 步骤 {i} 已完成结果: {final_answer}) return final_answer # --- 4. 智能体 (Agent) 整合 --- class PlanAndSolveAgent: def __init__(self, llm_client: HelloAgentsLLM): self.llm_client llm_client self.planner Planner(self.llm_client) self.executor Executor(self.llm_client) def run(self, question: str): print(f\n--- 开始处理问题 ---\n问题: {question}) plan self.planner.plan(question) if not plan: print(\n--- 任务终止 --- \n无法生成有效的行动计划。) return final_answer self.executor.execute(question, plan) print(f\n--- 任务完成 ---\n最终答案: {final_answer}) # --- 5. 主函数入口 --- if __name__ __main__: try: llm_client HelloAgentsLLM() agent PlanAndSolveAgent(llm_client) question 一个水果店周一卖出了15个苹果。周二卖出的苹果数量是周一的两倍。周三卖出的数量比周二少了5个。请问这三天总共卖出了多少个苹果 agent.run(question) except ValueError as e: print(e)终端输出内容(.venv) MacBook-Air section4 % python Plan_and_Solve.py --- 开始处理问题 --- 问题: 一个水果店周一卖出了15个苹果。周二卖出的苹果数量是周一的两倍。周三卖出的数量比周二少了5个。请问这三天总共卖出了多少个苹果 --- 正在生成计划 --- 正在调用 coding-glm-5-free 模型... ✅ 大语言模型响应成功: python [从问题中提取周一卖出的苹果数量, 根据周一的数量计算周二卖出的苹果数量周一数量乘以2, 根据周二的数量计算周三卖出的苹果数量周二数量减去5, 将周一、周二和周三的销量相加以计算总数] ✅ 计划已生成: python [从问题中提取周一卖出的苹果数量, 根据周一的数量计算周二卖出的苹果数量周一数量乘以2, 根据周二的数量计算周三卖出的苹果数量周二数量减去5, 将周一、周二和周三的销量相加以计算总数] --- 正在执行计划 --- - 正在执行步骤 1/4: 从问题中提取周一卖出的苹果数量 正在调用 coding-glm-5-free 模型... ✅ 大语言模型响应成功: 15 ✅ 步骤 1 已完成结果: 15 - 正在执行步骤 2/4: 根据周一的数量计算周二卖出的苹果数量周一数量乘以2 正在调用 coding-glm-5-free 模型... ✅ 大语言模型响应成功: 30 ✅ 步骤 2 已完成结果: 30 - 正在执行步骤 3/4: 根据周二的数量计算周三卖出的苹果数量周二数量减去5 正在调用 coding-glm-5-free 模型... ✅ 大语言模型响应成功: 25 ✅ 步骤 3 已完成结果: 25 - 正在执行步骤 4/4: 将周一、周二和周三的销量相加以计算总数 正在调用 coding-glm-5-free 模型... ✅ 大语言模型响应成功: 70 ✅ 步骤 4 已完成结果: 70 --- 任务完成 --- 最终答案: 70