概述

计划执行智能体(Plan and Execute Agent)是一种采用"先规划,后执行"策略的智能体模型。它将复杂任务分解为两个主要阶段:首先使用语言模型制定详细计划,然后逐步执行这些计划步骤。这种方法特别适合处理需要多步骤推理和工具使用的复杂问题,使整个过程更加结构化和可控。

计划执行智能体的核心思想是将任务分解为更小、更易管理的步骤,然后针对每个步骤使用最适合的工具或方法来解决。这种方法模拟了人类解决复杂问题的方式,先制定策略,再逐步实施。

工作原理

计划执行智能体的工作流程如下:

  1. 计划阶段: 智能体分析任务并生成详细的步骤计划

  2. 执行阶段: 智能体逐步执行计划中的每个步骤

  3. 监控与调整: 在执行过程中监控进度,必要时调整计划

  4. 整合结果: 将各步骤的结果整合为最终输出

优势

  • 结构化问题解决: 将复杂问题分解为可管理的步骤

  • 更好的任务分解: 明确区分计划和执行阶段,使每个阶段更专注

  • 减少迭代次数: 通过预先规划减少执行阶段的试错

  • 适应长期任务: 能够处理需要多个步骤才能完成的长期任务

  • 提高可解释性: 通过明确的计划使推理过程更透明

基本用法示例

以下是创建和使用基本计划执行智能体的完整示例:

from langchain_openai import ChatOpenAI
from langchain.agents import load_tools
from langchain.agents.plan_and_execute.agent import PlanAndExecute
from langchain.agents.plan_and_execute.planners.chat_planner import load_chat_planner
from langchain.agents.plan_and_execute.executors.agent_executor import load_agent_executor

# 初始化LLM
model = ChatOpenAI(temperature=0)

# 加载工具
tools = load_tools(["serpapi", "llm-math"], llm=model)

# 加载计划器和执行器
planner = load_chat_planner(model)
executor = load_agent_executor(model, tools, verbose=True)

# 创建计划执行智能体
agent = PlanAndExecute(planner=planner, executor=executor, verbose=True)

# 执行复杂查询
result = agent.invoke({
    "input": "今天的日期是多少?2020年美国GDP是多少?如果将美国GDP除以当年人口,人均GDP是多少?"
})

print("最终回答:", result["output"])

高级用法

自定义计划器

from langchain.prompts import PromptTemplate
from langchain.agents.plan_and_execute.planners.base import BasePlanner
from typing import List, Dict, Any

# 自定义计划提示模板
custom_planning_template = """你是一个任务规划专家。给定一个目标,你的任务是制定详细的步骤计划来完成目标。

目标: {input}

请提供一个详细的步骤计划,包括:
1. 每个步骤应该具体且可执行
2. 明确每个步骤可能需要的工具或信息
3. 确保步骤之间有逻辑顺序
4. 计划应该全面,覆盖实现目标的所有必要环节

你的计划:"""

custom_prompt = PromptTemplate.from_template(custom_planning_template)

# 创建自定义计划器类
class CustomPlanner(BasePlanner):
    def plan(self, inputs: Dict[str, Any]) -> List[str]:
        user_input = inputs["input"]
        planning_llm = ChatOpenAI(model="gpt-4", temperature=0)  # 使用强大的模型进行规划
        
        # 获取计划
        plan_result = planning_llm.predict(custom_prompt.format(input=user_input))
        
        # 将计划分解为步骤列表
        steps = []
        for line in plan_result.split("\n"):
            line = line.strip()
            # 过滤出实际步骤(通常以数字开头)
            if line and (line[0].isdigit() or line.startswith("- ") or line.startswith("* ")):
                # 移除步骤编号或列表符号
                cleaned_step = line
                for prefix in ["- ", "* ", ". "]:
                    if ".") > 0:
                        cleaned_step = line[line.find(".")+1:].strip()
                        break
                    elif prefix in line:
                        cleaned_step = line[line.find(prefix)+len(prefix):].strip()
                        break
                
                if cleaned_step:
                    steps.append(cleaned_step)
        
        return steps

# 使用自定义计划器
custom_planner = CustomPlanner()

# 创建带自定义计划器的智能体
custom_plan_agent = PlanAndExecute(
    planner=custom_planner,
    executor=executor,
    verbose=True
)

# 执行复杂查询
result = custom_plan_agent.invoke({
    "input": "我需要为一个家庭四口规划为期三天的巴黎旅行,包括景点安排和餐厅推荐。"
})

print("最终回答:", result["output"])

自定义执行器

from langchain.agents import create_react_agent, AgentExecutor
from langchain.agents.plan_and_execute.executors.base import BaseExecutor
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

class CustomExecutor(BaseExecutor):
    """一个自定义的步骤执行器,使用ReAct智能体来执行每个步骤。"""
    
    def __init__(self, llm, tools, verbose=False):
        # 创建用于执行的ReAct智能体
        prompt = ChatPromptTemplate.from_messages([
            ("system", "你是一个执行专家,负责精确执行给定的任务步骤。\
             你有权访问以下工具来帮助完成任务:{tools}\
             专注于当前步骤,确保完全完成它,而不是考虑其他步骤。"),
            ("human", "需要执行的步骤: {step}\n当前状态: {context}"),
            MessagesPlaceholder(variable_name="agent_scratchpad")
        ])
        
        agent = create_react_agent(llm, tools, prompt)
        self.agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=verbose)
    
    def execute_step(self, step: str, context: list, **kwargs) -> str:
        # 将上下文转换为字符串
        context_str = "\n".join([f"- {s}: {r}" for s, r in context])
        if not context_str:
            context_str = "这是第一个步骤,尚无前序结果。"
        
        # 执行当前步骤
        result = self.agent_executor.invoke({
            "step": step,
            "context": context_str
        })
        
        return result["output"]

# 创建自定义执行器实例
custom_executor = CustomExecutor(
    llm=ChatOpenAI(model="gpt-3.5-turbo", temperature=0),
    tools=tools,
    verbose=True
)

# 创建带自定义执行器的智能体
custom_execution_agent = PlanAndExecute(
    planner=planner,
    executor=custom_executor,
    verbose=True
)

复杂任务处理

from langchain.tools import WikipediaQueryRun, YouTubeSearchTool
from langchain_community.utilities import WikipediaAPIWrapper

# 创建更多样的工具集
complex_tools = load_tools(["serpapi", "llm-math"], llm=model)
complex_tools.extend([
    WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper()),
    YouTubeSearchTool(),
])

# 创建用于复杂任务的智能体
complex_task_agent = PlanAndExecute(
    planner=load_chat_planner(ChatOpenAI(model="gpt-4", temperature=0)),  # 使用更强大的模型进行规划
    executor=load_agent_executor(
        ChatOpenAI(model="gpt-3.5-turbo-16k", temperature=0),  # 使用更大上下文窗口的模型执行
        complex_tools,
        verbose=True
    ),
    verbose=True
)

# 处理复杂研究任务
complex_task = """
我需要研究人工光合作用技术的最新进展,并撰写一份简短的研究摘要,要求:
1. 确定该领域最新的科学突破
2. 比较不同研究团队的方法
3. 分析其潜在的环境影响和能源应用
4. 计算如果这项技术达到自然光合作用30%的效率,每平方米每天可以产生多少能量(假设平均每平方米太阳辐射量为5kWh/天)
"""

result = complex_task_agent.invoke({"input": complex_task})
print("研究摘要:\n", result["output"])

实际应用场景

1. 旅行规划助手

from langchain.memory import ConversationBufferMemory
from langchain.agents.plan_and_execute.planners.chat_planner import load_chat_planner
from langchain.agents.plan_and_execute.executors.agent_executor import AgentExecutor
from langchain.tools import tool

# 创建旅行相关工具
@tool
def search_attractions(location: str) -> str:
    """搜索特定位置的旅游景点"""
    # 实际应用中连接到旅游API或搜索引擎
    return f"在{location}找到的热门景点:卢浮宫、埃菲尔铁塔、凯旋门、圣母院、蒙马特高地"

@tool
def search_restaurants(location: str, cuisine: str = "local") -> str:
    """在特定位置搜索餐厅,可以指定菜系"""
    # 实际应用中连接到餐厅数据库
    if cuisine == "local" or cuisine == "法国":
        return f"在{location}找到的法国餐厅:Le Jules Verne、L'Ambroisie、Le Cinq"
    else:
        return f"在{location}找到的{cuisine}餐厅:相关餐厅列表"

@tool
def check_weather(location: str, date: str) -> str:
    """查询特定位置特定日期的天气预报"""
    # 实际应用中连接到天气API
    return f"{location}在{date}的天气预报:晴朗,温度18-25°C")

@tool
def find_hotels(location: str, check_in: str, check_out: str, guests: int = 2) -> str:
    """在特定位置寻找酒店"""
    # 实际应用中连接到酒店预订系统
    return f"在{location}找到的酒店,入住日期{check_in},离店日期{check_out},{guests}位客人:
    - Grand Hotel Paris:4星级,¥1200/晚
    - Boutique Marais:3星级,¥800/晚
    - Luxury Seine View:5星级,¥2000/晚"

# 组合旅行工具
travel_tools = [search_attractions, search_restaurants, check_weather, find_hotels]

# 创建旅行规划智能体
travel_planner = PlanAndExecute(
    planner=load_chat_planner(ChatOpenAI(model="gpt-4", temperature=0.1)),
    executor=load_agent_executor(
        ChatOpenAI(model="gpt-3.5-turbo", temperature=0.2),
        travel_tools,
        verbose=True
    ),
    verbose=True
)

# 处理旅行规划请求
travel_request = "我计划下个月带家人去巴黎旅游3天,需要一个包括景点、酒店和餐厅的详细行程安排。我们是2个大人和2个孩子(7岁和10岁)。"

travel_plan = travel_planner.invoke({"input": travel_request})
print("旅行计划:\n", travel_plan["output"])

2. 研究与报告生成

from langchain.tools import tool
from datetime import datetime

@tool
def search_academic_papers(query: str, max_results: int = 5) -> str:
    """搜索学术论文"""
    # 实际应用中连接到学术数据库
    return f"关于'{query}'的论文搜索结果(最新5篇):\n各种论文标题和简短摘要"

@tool
def analyze_trends(topic: str) -> str:
    """分析特定主题的研究趋势"""
    # 实际应用中连接到趋势分析API
    return f"'{topic}'的研究趋势:该领域近年来发表论文数量增长了30%,主要关注点包括..."

@tool
def generate_chart(data_description: str) -> str:
    """根据描述生成图表(返回图表描述)"""
    # 实际应用中会生成实际图表或图表代码
    return f"已根据'{data_description}'生成图表,显示了主要趋势和数据分布"

# 创建研究工具集
research_tools = [search_academic_papers, analyze_trends, generate_chart]
research_tools.extend([WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())])

# 创建研究与报告智能体
research_agent = PlanAndExecute(
    planner=load_chat_planner(ChatOpenAI(model="gpt-4", temperature=0)),
    executor=load_agent_executor(
        ChatOpenAI(model="gpt-3.5-turbo-16k", temperature=0.1),
        research_tools,
        verbose=True
    ),
    verbose=True
)

# 处理研究请求
research_request = """为我准备一份关于量子计算近五年发展的简短研究报告,包括:
1. 主要技术突破
2. 领先研究机构
3. 潜在商业应用
4. 未来五年的发展趋势预测

请包含一个关于研究论文发表趋势的图表描述。
"""

research_report = research_agent.invoke({"input": research_request})
print(f"研究报告(生成于{datetime.now().strftime('%Y-%m-%d')}):\n", research_report["output"])

最佳实践

  1. 任务分解策略:指导智能体如何最有效地分解复杂任务。

    # 在计划提示中指导任务分解
    planning_template = """将复杂任务分解为以下几类步骤:
    1. 信息收集步骤:获取必要数据和上下文
    2. 分析步骤:处理和分析收集的信息
    3. 创建步骤:生成新内容或解决方案
    4. 验证步骤:检查结果是否满足要求
    
    任务: {input}
    
    详细步骤计划:"""
    
  2. 步骤依赖管理:确保步骤之间的逻辑顺序和依赖关系。

    # 为执行器提供上下文管理
    class ContextAwareExecutor(BaseExecutor):
        def execute_step(self, step: str, context: list, **kwargs) -> str:
            # 分析当前步骤需要哪些前序步骤的结果
            required_context = self._identify_dependencies(step, context)
            context_str = self._format_context(required_context)
            
            # 执行步骤并返回结果
            # ...
    
  3. 错误恢复机制:实现步骤失败后的恢复策略。

    # 在执行器中添加错误处理
    try:
        step_result = self.agent_executor.invoke({"step": step, "context": context_str})
        return step_result["output"]
    except Exception as e:
        # 尝试重新规划或采用备选方案
        recovery_result = self._handle_step_failure(step, context, e)
        return f"原始步骤执行失败,已采用替代方案。结果: {recovery_result}"
    
  4. 提供足够上下文:确保每个步骤都有足够的前序信息。

  5. 选择合适的模型:规划阶段使用强大的模型(如GPT-4),执行阶段可以使用更轻量级的模型。

  6. 限制步骤数量:将复杂任务分解为5-7个步骤,避免过度分解或步骤过少。

  7. 步骤结果验证:在执行阶段实现结果验证机制,确保每个步骤都产生有用输出。

与其他智能体类型的对比

特性

计划执行智能体

ReAct智能体

标准智能体

任务分解

明确的计划阶段

隐式分解

有限或没有

处理复杂任务

资源效率

可能较低(两阶段)

中等

可解释性

高(明确计划)

中(思考-行动循环)

错误恢复

可在步骤层面恢复

可能需要重新规划整个任务

有限

适用场景

复杂多步骤任务

中等复杂度任务

简单任务

常见问题与解决方案

  1. 计划过于笼统

    • 解决方案:改进计划提示,要求更具体的步骤

    • 实施计划评估机制,在执行前评估计划质量

  2. 执行偏离计划

    • 解决方案:加强执行器对计划的遵循

    • 实现计划-执行对齐检查

  3. 步骤间上下文丢失

    • 解决方案:改进上下文传递机制

    • 实现更完善的步骤依赖管理

  4. 处理计划失效

    • 解决方案:实现动态重新规划功能

    • 允许执行器在必要时请求计划修正

总结

计划执行智能体通过将复杂任务分解为计划和执行两个独立阶段,提供了一种结构化的问题解决方法。这种方法特别适合处理需要多步骤、多工具协作的复杂任务,如研究报告生成、旅行规划或项目管理。

计划执行智能体的主要优势在于其对任务的明确分解和结构化处理,使得即使是非常复杂的任务也能被分解为可管理的步骤。通过分离计划和执行阶段,这种智能体还提高了推理过程的透明度和可靠性。

对于需要处理复杂、多步骤任务的应用场景,计划执行智能体提供了比传统智能体更强大和可靠的解决方案。通过遵循本文档中的最佳实践和实施建议,开发者可以充分利用这种智能体模型的优势,构建高效、可靠的智能系统。