Agent学习之补充my_plan_solve_agent

1. 原地址

https://github.com/datawhalechina/hello-agents/blob/main/docs/chapter7/%E7%AC%AC%E4%B8%83%E7%AB%A0%20%E6%9E%84%E5%BB%BA%E4%BD%A0%E7%9A%84Agent%E6%A1%86%E6%9E%B6.md

2. 补充代码

python 复制代码
# my_plan_solve_agent.py
"""重写的 Plan-and-Solve Agent - 分解规划与逐步执行"""

import ast
import re
from typing import Optional, Dict, List

from hello_agents import PlanAndSolveAgent, HelloAgentsLLM, Config, Message
from hello_agents.agents.plan_solve_agent import (
    DEFAULT_PLANNER_PROMPT,
    DEFAULT_EXECUTOR_PROMPT,
)


class MyPlanner:
    """规划器 - 将复杂问题分解为可执行步骤"""

    def __init__(
        self,
        llm: HelloAgentsLLM,
        prompt_template: Optional[str] = None,
        system_prompt: Optional[str] = None,
    ):
        self.llm = llm
        self.prompt_template = prompt_template or DEFAULT_PLANNER_PROMPT
        self.system_prompt = system_prompt

    def plan(self, question: str, **kwargs) -> List[str]:
        prompt = self.prompt_template.format(question=question)
        print(f"prompt:{prompt}")
        messages = self._build_messages(prompt)
        print("--- 正在生成计划 ---")
        response_text = self.llm.invoke(messages, **kwargs) or ""
        print(f"✅ 计划已生成:\n{response_text}")

        plan = self._parse_plan(response_text)
        if not plan:
            print("❌ 解析计划失败,无法提取有效步骤列表")
        return plan

    def _build_messages(self, prompt: str) -> list:
        messages = []
        if self.system_prompt:
            messages.append({"role": "system", "content": self.system_prompt})
        messages.append({"role": "user", "content": prompt})
        return messages

    def _parse_plan(self, response_text: str) -> List[str]:
        """从 LLM 响应中解析 Python 列表格式的计划"""
        # 优先解析 ```python ... ``` 代码块
        if "```python" in 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"❌ 解析 python 代码块时出错: {e}")

        # 回退:解析任意 ``` ... ``` 代码块
        code_blocks = re.findall(r"```(?:python)?\s*([\s\S]*?)```", response_text)
        for block in code_blocks:
            try:
                plan = ast.literal_eval(block.strip())
                if isinstance(plan, list) and plan:
                    return plan
            except (ValueError, SyntaxError):
                continue

        # 回退:匹配响应中的 [...] 列表
        list_match = re.search(r"\[[\s\S]*?\]", response_text)
        if list_match:
            try:
                plan = ast.literal_eval(list_match.group())
                return plan if isinstance(plan, list) else []
            except (ValueError, SyntaxError) as e:
                print(f"❌ 解析列表字面量时出错: {e}")

        print(f"原始响应: {response_text}")
        return []


class MyExecutor:
    """执行器 - 按计划逐步执行"""

    def __init__(
        self,
        llm: HelloAgentsLLM,
        prompt_template: Optional[str] = None,
        system_prompt: Optional[str] = None,
    ):
        self.llm = llm
        self.prompt_template = prompt_template or DEFAULT_EXECUTOR_PROMPT
        self.system_prompt = system_prompt

    def execute(self, question: str, plan: List[str], **kwargs) -> str:
        history = ""
        final_answer = ""

        print("\n--- 正在执行计划 ---")
        for i, step in enumerate(plan, 1):
            print(f"\n-> 正在执行步骤 {i}/{len(plan)}: {step}")
            prompt = self.prompt_template.format(
                question=question,
                plan=plan,
                history=history if history else "无",
                current_step=step,
            )
            messages = self._build_messages(prompt)
            response_text = self.llm.invoke(messages, **kwargs) or ""

            history += f"步骤 {i}: {step}\n结果: {response_text}\n\n"
            final_answer = response_text
            print(f"✅ 步骤 {i} 已完成,结果: {final_answer}")

        return final_answer

    def _build_messages(self, prompt: str) -> list:
        messages = []
        if self.system_prompt:
            messages.append({"role": "system", "content": self.system_prompt})
        messages.append({"role": "user", "content": prompt})
        return messages


class MyPlanAndSolveAgent(PlanAndSolveAgent):
    """
    重写的 Plan-and-Solve Agent
    基于框架 PlanAndSolveAgent,实现「规划 → 逐步执行」流程
    """

    def __init__(
        self,
        name: str,
        llm: HelloAgentsLLM,
        system_prompt: Optional[str] = None,
        config: Optional[Config] = None,
        custom_prompts: Optional[Dict[str, str]] = None,
    ):
        super().__init__(
            name=name,
            llm=llm,
            system_prompt=system_prompt,
            config=config,
            custom_prompts=custom_prompts,
        )

        planner_prompt = (custom_prompts or {}).get("planner")
        executor_prompt = (custom_prompts or {}).get("executor")

        self.planner = MyPlanner(llm, planner_prompt, system_prompt)
        self.executor = MyExecutor(llm, executor_prompt, system_prompt)

        prompt_type = "自定义" if custom_prompts else "默认"
        print(f"✅ {name} 初始化完成,提示词: {prompt_type}")

    def run(self, input_text: str, **kwargs) -> str:
        """运行 Plan-and-Solve Agent"""
        print(f"\n🤖 {self.name} 开始处理问题: {input_text}")

        plan = self.planner.plan(input_text, **kwargs)
        if not plan:
            final_answer = "无法生成有效的行动计划,任务终止。"
            print(f"\n--- 任务终止 ---\n{final_answer}")
            self.add_message(Message(input_text, "user"))
            self.add_message(Message(final_answer, "assistant"))
            return final_answer

        final_answer = self.executor.execute(input_text, plan, **kwargs)
        print(f"\n--- 任务完成 ---\n最终答案: {final_answer}")

        self.add_message(Message(input_text, "user"))
        self.add_message(Message(final_answer, "assistant"))

        return final_answer

3. 测试结果

python 复制代码
# python test_plan_solve_agent.py 
✅ 我的规划执行助手 初始化完成,提示词: 默认

🤖 我的规划执行助手 开始处理问题: 一个水果店周一卖出了15个苹果。周二卖出的苹果数量是周一的两倍。周三卖出的数量比周二少了5个。请问这三天总共卖出了多少个苹果?
prompt:
你是一个顶级的AI规划专家。你的任务是将用户提出的复杂问题分解成一个由多个简单步骤组成的行动计划。
请确保计划中的每个步骤都是一个独立的、可执行的子任务,并且严格按照逻辑顺序排列。
你的输出必须是一个Python列表,其中每个元素都是一个描述子任务的字符串。

问题: 一个水果店周一卖出了15个苹果。周二卖出的苹果数量是周一的两倍。周三卖出的数量比周二少了5个。请问这三天总共卖出了多少个苹果?

请严格按照以下格式输出你的计划:
```python
["步骤1", "步骤2", "步骤3", ...]
```

--- 正在生成计划 ---
✅ 计划已生成:
```python
[
    "确定周一卖出的苹果数量(已知为15个)",
    "计算周二卖出的苹果数量(周一的两倍,即15*2)",
    "计算周三卖出的苹果数量(周二数量减去5个)",
    "将周一、周二和周三卖出的苹果数量相加,得到三天总共卖出的苹果数量"
]
```

--- 正在执行计划 ---

-> 正在执行步骤 1/4: 确定周一卖出的苹果数量(已知为15个)
✅ 步骤 1 已完成,结果: 15

-> 正在执行步骤 2/4: 计算周二卖出的苹果数量(周一的两倍,即15*2)
✅ 步骤 2 已完成,结果: 30

-> 正在执行步骤 3/4: 计算周三卖出的苹果数量(周二数量减去5个)
✅ 步骤 3 已完成,结果: 25

-> 正在执行步骤 4/4: 将周一、周二和周三卖出的苹果数量相加,得到三天总共卖出的苹果数量
✅ 步骤 4 已完成,结果: 70

--- 任务完成 ---
最终答案: 70
相关推荐
想你依然心痛1 小时前
HarmonyOS 6(API 23)实战:打造“光码智学舱“——AI编程学习新范式
学习·ar·ai编程·harmonyos·智能体
一口吃俩胖子3 小时前
【脉宽调制DCDC功率变换学习笔记023】渐进分析法
笔记·学习
m0_377108143 小时前
pid学习
学习
爱喝水的鱼丶3 小时前
SAP-ABAP:SAP基础数据校验工具开发系列博客(共5篇)第三篇:SAP接口对接开发:实现数据的实时/批量校验交互
运维·数据库·学习·性能优化·sap·abap·经验交流
TE-茶叶蛋4 小时前
学习GitNexus中优雅的自动滚动:useAutoScroll Hook 实现
学习
小陈phd4 小时前
多模态大模型学习笔记(四十八)——从自然语言到 SQL:大模型时代结构化数据查询的技术革命与落地实践
笔记·sql·学习
星夜夏空995 小时前
FreeRTOS学习(12)——任务通知
学习·性能优化
AOwhisky5 小时前
学习自测(MySQL系列第一期、第二期)
linux·运维·数据库·学习·mysql·云计算
星夜夏空996 小时前
FreeRTOS学习(10)——消息队列
学习