🌟 LangChain 30 天保姆级教程 · Day 24|Plan-and-Execute Agent!让 AI 先“写计划”再“干活”,搞定复杂任务!

系列目标 :30 天从 LangChain 入门到企业级部署
今日任务:理解 Plan-and-Execute 架构 → 实现自定义 Planner/Executor → 构建"自动写周报"智能体!


🧠 一、为什么需要 Plan-and-Execute?

ReAct Agent(Day 23)虽强,但面对复杂任务仍显不足:

用户问:"帮我写一份上周的工作周报,包含项目进展、遇到的问题和下周计划。"

ReAct 可能:

  • ❌ 直接编造内容(无真实数据)
  • ❌ 顺序混乱(先写计划再查进展?)
  • ❌ 遗漏关键步骤

根本问题 :缺乏全局规划能力

解决方案

Plan-and-Execute Agent ------ 将任务拆解为 Plan(计划) + Execute(执行) 两阶段!
💡 今天,我们就用 LangChain 的 PlanAndExecute 框架,打造一个会"先列大纲,再填内容"的 AI 助手!


🏗️ 二、Plan-and-Execute 架构原理

css 复制代码
用户输入
   ↓
[Planner] → 生成结构化任务列表(如:1. 查项目A进度;2. 查Bug列表;3. 生成周报)
   ↓
[Executor] → 逐项调用 Tool 执行,并汇总结果
   ↓
最终输出

优势:

  • ✅ 任务分解清晰,避免遗漏
  • ✅ 支持并行/串行混合执行(未来扩展)
  • ✅ 可审查中间计划(提升可控性)

🔑 核心组件:

  • Plan:由 LLM 生成的 List[Step]
  • StepExecutor:执行单个步骤的 Agent(可复用 Day 23 的 ReAct)

🛠️ 三、动手实践:构建"自动写周报"Agent

步骤 1:准备模拟数据源(Tool)

python 复制代码
# day24_plan_and_execute.py
from langchain_core.tools import tool

@tool
def get_project_status(project_name: str) -> str:
    """获取项目最新进展"""
    return {
        "AI平台": "完成RAG模块开发,准确率提升至92%",
        "数据中台": "ETL流程优化,延迟降低40%"
    }.get(project_name, "项目未找到")

@tool
def get_recent_bugs() -> str:
    """获取最近3天的高优先级Bug"""
    return "1. 用户登录偶发500错误;2. PDF导出格式错乱"

@tool
def get_upcoming_tasks() -> str:
    """获取下周计划任务"""
    return "1. 上线RAG问答系统;2. 修复PDF导出问题"

步骤 2:初始化基础 LLM 和 ReAct Executor

ini 复制代码
from langchain_ollama import ChatOllama
from langchain.agents import create_react_agent, AgentExecutor
from langchain import hub

llm = ChatOllama(model="qwen:7b", temperature=0)

# 创建底层执行器(用于执行每个步骤)
react_prompt = hub.pull("hwchase17/react")
react_agent = create_react_agent(llm, [get_project_status, get_recent_bugs, get_upcoming_tasks], react_prompt)
step_executor = AgentExecutor(agent=react_agent, tools=[...], verbose=False)

步骤 3:定义 Planner(计划生成器)

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

planner_prompt = ChatPromptTemplate.from_template(
    """
你是一个任务规划专家。请将以下目标拆解为一系列具体的、可执行的步骤。
每个步骤应明确调用哪个工具(如 get_project_status),并指定参数。
仅输出步骤列表,每行以数字开头,不要解释。

目标:{input}
步骤:
"""
)

planner_chain = planner_prompt | llm | StrOutputParser()

✅ 输出示例:

scss 复制代码
1. 调用 get_project_status(project_name="AI平台")
2. 调用 get_project_status(project_name="数据中台")
3. 调用 get_recent_bugs()
4. 调用 get_upcoming_tasks()

步骤 4:实现 Plan-and-Execute 主逻辑

python 复制代码
import re

def parse_plan(plan_text: str):
    """解析计划文本为步骤列表"""
    steps = []
    for line in plan_text.strip().split("\n"):
        if line.strip().startswith(("1.", "2.", "3.", "4.", "5.")):
            steps.append(line.split(". ", 1)[1])
    return steps

def execute_plan(steps: list) -> dict:
    """执行计划,返回每步结果"""
    results = {}
    for i, step in enumerate(steps):
        try:
            # 提取工具名和参数(简化版,生产可用 AST 解析)
            if "get_project_status" in step:
                proj = re.search(r'project_name="([^"]+)"', step).group(1)
                res = get_project_status(proj)
            elif "get_recent_bugs" in step:
                res = get_recent_bugs()
            elif "get_upcoming_tasks" in step:
                res = get_upcoming_tasks()
            else:
                res = "未知步骤"
            results[f"step_{i+1}"] = res
        except Exception as e:
            results[f"step_{i+1}"] = f"执行失败: {str(e)}"
    return results

def generate_final_report(results: dict) -> str:
    """整合结果生成周报"""
    report = "【上周工作周报】\n\n"
    report += "一、项目进展\n"
    report += "- AI平台: " + results.get("step_1", "") + "\n"
    report += "- 数据中台: " + results.get("step_2", "") + "\n\n"
    report += "二、遇到的问题\n"
    report += results.get("step_3", "") + "\n\n"
    report += "三、下周计划\n"
    report += results.get("step_4", "")
    return report

步骤 5:端到端运行

ini 复制代码
def plan_and_execute(input_query: str) -> str:
    # 1. 生成计划
    plan_text = planner_chain.invoke({"input": input_query})
    print("📋 AI 制定的计划:\n", plan_text)
    
    # 2. 解析并执行
    steps = parse_plan(plan_text)
    results = execute_plan(steps)
    
    # 3. 生成最终报告
    return generate_final_report(results)

# 测试
query = "帮我写一份上周的工作周报,包含AI平台和数据中台的进展、最近的Bug、下周计划"
final_output = plan_and_execute(query)
print("\n📄 最终周报:\n", final_output)

▶️ 输出效果:

scss 复制代码
📋 AI 制定的计划:
1. 调用 get_project_status(project_name="AI平台")
2. 调用 get_project_status(project_name="数据中台")
3. 调用 get_recent_bugs()
4. 调用 get_upcoming_tasks()

📄 最终周报:
【上周工作周报】

一、项目进展
- AI平台: 完成RAG模块开发,准确率提升至92%
- 数据中台: ETL流程优化,延迟降低40%

二、遇到的问题
1. 用户登录偶发500错误;2. PDF导出格式错乱

三、下周计划
1. 上线RAG问答系统;2. 修复PDF导出问题

完美实现

  • 自动拆解复杂任务
  • 精准调用所需工具
  • 结构化输出专业文档

⚙️ 四、进阶:使用 LangChain 内置 PlanAndExecute(实验性)

LangChain 提供了实验性支持(需 langchain-experimental):

复制代码
pip install langchain-experimental
ini 复制代码
from langchain_experimental.plan_and_execute import (
    PlanAndExecute,
    load_agent_executor,
    load_chat_planner
)

planner = load_chat_planner(llm)
executor = load_agent_executor(llm, [tools], verbose=True)
agent = PlanAndExecute(planner=planner, executor=executor)

result = agent.run("写周报...")

⚠️ 注意:该模块仍在演进,自定义实现更可控(如上文)。


⚠️ 五、注意事项 & 最佳实践

表格

问题 建议
计划不完整 在 Planner Prompt 中提供示例(Few-shot)
步骤无法执行 Executor 加强错误处理;支持重试
结果整合生硬 用单独 LLM 调用生成最终报告(更自然)
Token 超限 对超长计划分批执行
安全风险 所有 Tool 调用需权限校验

💡 生产建议

  • 允许用户审核/修改 AI 生成的计划
  • 记录完整 Plan-Execute 日志用于复盘
  • 对高频任务模板化(如"周报""月报")

📦 六、配套代码结构

bash 复制代码
langchain-30-days/
└── day24/
    └── plan_and_execute_weekly_report.py  # 自动周报生成器

📝 七、今日小结

  • ✅ 理解了 Plan-and-Execute 的两阶段架构优势
  • ✅ 学会了自定义 Planner 生成结构化任务列表
  • ✅ 实现了步骤解析与工具调用的执行引擎
  • ✅ 构建了端到端的"自动写周报"智能体
  • ✅ 知道了如何平衡自动化与人工干预

🎯 明日预告:Day 25 ------ 向量数据库进阶!Milvus/PGVector 生产级部署与性能调优!

相关推荐
geBR OTTE2 小时前
Python中的简单爬虫
爬虫·python·信息可视化
m0_678485452 小时前
CSS如何使用Less的Merge功能合并多个属性值_通过逗号或空格组织css参数
jvm·数据库·python
小陈工2 小时前
python Web开发从入门到精通(二十七)微服务架构设计原则深度解析:告别拆分烦恼,掌握治理精髓(下)
后端·python·mysql
2401_897190552 小时前
团队版Navicat专属功能:如何共享数据库架构ER模型_核心机制解析
jvm·数据库·python
m0_640309302 小时前
如何利用 Block Tree 避免不必要的子组件重渲染?Vue3 编译黑科技
jvm·数据库·python
LiAo_1996_Y2 小时前
layui table数据表格分页 layui表格如何开启服务端分页
jvm·数据库·python
LiAo_1996_Y2 小时前
mysql如何获取最后插入的ID_使用LAST_INSERT_ID函数
jvm·数据库·python
justjinji2 小时前
告别FPM!Swoole如何让PHP性能飙升10倍?
jvm·数据库·python
起个名字总是说已存在2 小时前
解决智能体等部署cl100k_base.tiktoken报错问题
人工智能·python·ai编程