当前位置: 首页 > news >正文

智能体设计范式:Plan-and-Solve

智能体设计范式:Plan-and-Solve 范式

1 核心思想

Plan-and-Solve(先规划后执行)认为直接单步推理容易遗漏或出错,更好的做法是先让模型生成一个完成任务的步骤计划,然后逐步执行该计划,每步可以调用工具,最后汇总结果得到最终答案。

2 工作原理

  1. 规划阶段:给模型一个问题,要求其输出一个分步计划(例如1. 搜索2022世界杯冠军\n2. 搜索该冠军的主教练\n3. 综合信息给出答案)。
  2. 执行阶段:遍历计划中的每一步,将步骤指令作为提示,允许模型调用工具(类似 ReAct 单步),获得该步骤的结果。
  3. 综合阶段:将所有步骤的中间结果提供给模型,让它生成最终答案。

3 使用场景

  • 复杂的多跳推理问题,需要分解为多个子任务。
  • 数学应用题、需要多步查询的知识问题。
  • 需要遵循固定流程的任务(如旅行规划、报告生成)。

4 优缺点

优点

  • 全局规划减少盲目试探,提高效率。
  • 任务步骤清晰,便于调试和人工干预。
  • 可并行执行无依赖的步骤(高级实现)。

缺点

  • 计划可能不完善或错误,导致执行偏差。
  • 依赖模型规划能力,对简单问题反而增加步骤数。
  • 缺乏动态调整能力(静态计划难以应对意外情况)。

5 Python 实现

importreimportrequestsfromtypingimportListclassAliYunLLM:...# 定义与前文相同# ---------- 工具集 ----------defsearch(query:str)->str:"""真实搜索:使用 DuckDuckGo 免费 API"""try:url=f"https://api.duckduckgo.com/?q={requests.utils.quote(query)}&format=json"resp=requests.get(url,timeout=5)data=resp.json()# 优先返回“AbstractText”摘要abstract=data.get("AbstractText","")ifabstract:returnabstract# 如果没有摘要,尝试取第一个关联主题的文本related=data.get("RelatedTopics",[])ifrelatedand"Text"inrelated[0]:returnrelated[0]["Text"]returnf"未找到关于'{query}'的信息。"exceptExceptionase:returnf"搜索出错:{e}"defcalculator(expression:str)->str:try:ifre.match(r'^[\d\+\-\*/\(\)\.\s]+$',expression):returnstr(eval(expression))else:return"非法表达式"exceptExceptionase:returnf"计算错误:{e}"TOOLS={"search":search,"calculator":calculator}# ---------- Plan-and-Solve Agent ----------classPlanAndSolveAgent:def__init__(self,llm:AliYunLLM):self.llm=llmdef_make_plan(self,question:str)->List[str]:system_prompt=("你是一个规划助手。请将用户的问题分解为详细的步骤计划,每步应简单明确,可单独执行。\n""输出格式:每行一个步骤,以数字加点开头,如:\n""1. 搜索X的信息\n""2. 计算Y的值\n""3. 结合信息得到最终答案\n""请只输出步骤,不要其他内容。")plan_text=self.llm.generate(question,system_prompt=system_prompt)print(f"生成计划:\n{plan_text}")# 解析步骤,提取每行数字开头的文本steps=re.findall(r"\d+\.\s*(.*)",plan_text)returnstepsdef_execute_step(self,step_description:str,context:str="")->str:"""执行单个步骤,允许调用工具"""tool_descriptions=("- search(query: str): 搜索互联网。\n""- calculator(expression: str): 计算表达式。")system_prompt=("你是一个执行助手。你需要完成一个子任务。你可以使用以下工具:\n"f"{tool_descriptions}\n\n""输出格式:如果需要使用工具,请严格按照以下格式:\n""Action: 工具名\n""Action Input: 输入参数\n""然后你会收到 Observation,之后再给出该步骤的最终结果。\n""如果你已经可以得出该步骤的结果,请直接输出:\n""Step Result: 结果内容\n")prompt=f"当前任务:{step_description}\n"ifcontext:prompt+=f"已知上下文信息:{context}\n"prompt+="请完成这个子任务。"# 单步骤内部允许最多2次工具调用for_inrange(2):response=self.llm.generate(prompt,system_prompt=system_prompt)print(f"步骤执行输出:{response}")if"Step Result:"inresponse:result=response.split("Step Result:")[-1].strip()returnresult# 尝试解析 Actionaction_match=re.search(r"Action:\s*(.*)",response)input_match=re.search(r"Action Input:\s*(.*)",response)ifaction_matchandinput_match:action=action_match.group(1).strip()action_input=input_match.group(1).strip()ifactioninTOOLS:obs=TOOLS[action](action_input)prompt+=f"{response}\nObservation:{obs}\n"continue# 无法解析则直接返回模型的回复作为步骤结果returnresponse.strip()returnresponse.strip()defrun(self,question:str)->str:# 阶段1:生成计划steps=self._make_plan(question)ifnotsteps:return"无法生成计划。"# 阶段2:逐步执行step_results=[]context=""fori,stepinenumerate(steps,1):print(f"\n执行步骤{i}:{step}")result=self._execute_step(step,context)step_results.append(f"步骤{i}结果:{result}")context+=f"步骤{i}结果:{result}\n"print(f"步骤{i}结果:{result}")# 阶段3:综合最终答案summary_prompt=(f"问题:{question}\n"f"以下是各步骤的执行结果:\n"+"\n".join(step_results)+"\n请结合这些信息,给出最终的完整答案。")final_answer=self.llm.generate(summary_prompt,system_prompt="你是一个总结助手,请直接给出最终答案。")returnfinal_answer# ---------- 示例运行 ----------if__name__=="__main__":llm=AliYunLLM(api_key="your-api-key",base_url="https://dashscope.aliyuncs.com/api/v1",model="qwen-plus")agent=PlanAndSolveAgent(llm)question="2022年世界杯冠军的现任主教练是谁?"answer=agent.run(question)print(f"\n最终答案:{answer}")
http://www.gsyq.cn/news/1618213.html

相关文章:

  • C++ 纳秒级交易系统设计
  • 毕业设计项目 基于深度学习的驾驶行为检测(玩手机)
  • 昇腾AI处理器上下文切换优化实践与性能提升
  • 报文发送非网络基本功能
  • 冻库低温环境下的机器人搬运技术测评
  • ASP.NET Core 之 Identity 入门(一)
  • 给阿嬤一封来自云端的信(上)
  • Python装饰器开发实践
  • 终极Win11系统优化指南:免费工具让你的Windows 11运行如飞
  • 游戏编程十年总结(下)
  • 第5章 Function Call 与工具调用框架《AI Agent 开发平台资深技术专家 AI Agent 应用架构师 CTO 面试题库详解》
  • 【安全】Sql注入漏洞的危害和防御
  • GPU监控与进程管理:科研必备的nvidia-smi详解
  • 实测 Claude Sonnet 5 vs Claude Sonnet 4.6:别只看发布公告,API 跑起来才知道差距
  • 打包带在高温环境下会变形吗?
  • Python代码重构最佳实践
  • 简述交换机
  • 从百万行代码库中拯救编译速度:IDEA 2023.3+ Clean Import Pipeline实战(含Gradle/Maven双模自动化校验模板)
  • console.log不可用解决
  • 2026 新版多盘对比命理工具榜:玄易为何更适合高频看盘与合盘场景
  • 【JAVA毕设源码分享】基于Web的社交媒体平台的设计与实现(程序+文档+代码讲解+一条龙定制)
  • AI编曲工具实战:从入门到专业音乐制作
  • 最后的并行查询加载模块BatchQueryLoader直接就是调用上面的异步并行查询执行器BatchQueryExecutor,完成不同数据源的数据并行异步加载,代码如下
  • URL 使用规范
  • Pikachu靶场从入门到精通(五):RCE、XXE、SSRF与反序列化漏洞实战
  • 硬件学习笔记
  • Go escape逃逸分析
  • 孤能子视角:Karpathy LLM Wiki,一个人工观察符自动编织系统
  • 第4章 RAG 检索增强生成全链路架构《AI Agent 开发平台资深技术专家 AI Agent 应用架构师 CTO 面试题库详解》
  • 生成式引擎优化(GEO)在酒店民宿行业的落地实践:对抗 OTA 流量截流