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. 补充代码
# 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 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