Files
SmartVoyage/demo/agent/planning_agent.py
liangfangxing 0b087df55e feat: mcp
2026-03-20 11:26:44 +08:00

129 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.agents import AgentExecutor, create_react_agent
from conf import settings
# 创建模型
llm = ChatOpenAI(
base_url=settings.base_url,
api_key=settings.api_key,
model=settings.model_name,
temperature=0.1
)
# 2.定义工具
@tool
def multiply(numbers_str: str) -> int:
"""用于计算两个整数的乘积。
参数:
numbers_str (str): 包含两个整数的字符串,用逗号分隔,例如:"100,25"
返回:
int: 两个整数的乘积。
"""
print(f"正在执行乘法: {numbers_str}")
try:
a_str, b_str = numbers_str.split(',')
a = int(a_str.strip())
b = int(b_str.strip())
return a * b
except ValueError:
return "输入的格式不正确,请确保是两个用逗号分隔的整数,例如:'100,25'"
@tool
def search_weather(city: str) -> str:
"""用于查询指定城市的实时天气。"""
print(f"正在查询天气: {city}")
if "北京" in city:
return "北京今天是晴天气温25摄氏度。"
elif "上海" in city:
return "上海今天是阴天有小雨气温22摄氏度。"
else:
return f"抱歉,我没有'{city}'的天气信息。"
# 将工具列表放入一个变量
tools = [multiply, search_weather]
# 3.定义规划器 (Planner) 和执行者 (Executor) 的 Prompt
# 3.1 规划器的 Prompt
# 规划器的职责是分析用户任务,并将其分解成一系列简单的、可执行的子任务。
planner_prompt = ChatPromptTemplate.from_template(
"""你是一个任务规划师,你的工作是将用户提出的一个复杂任务分解成一系列清晰、可执行的步骤。
你的输出应该是一个简单的任务列表,每行一个任务。
例子:
用户任务: "请先查上海的天气然后计算20乘以30。"
任务列表:
- 查找上海的天气
- 计算20乘以30的结果
用户任务: {user_input}
任务列表:
"""
)
# 规划器链,它只负责生成文本化的任务列表
planner_chain = planner_prompt | llm | StrOutputParser()
# 3.2 执行者的 Prompt
# 执行者的职责是执行单个任务。在这里,我们使用 ReAct 模式作为执行者,因为它能根据任务描述选择并调用正确的工具。
# 注意:我们使用一个简化版的 ReAct Prompt因为它只需要处理单个任务。
executor_react_prompt_template = """你是一个专业的工具执行者,可以访问以下工具:
{tools}
根据你的思考Thought决定下一步的行动Action。你的行动必须遵循以下格式
Thought: 我需要思考如何完成任务。
Action: [工具名称]
Action Input: [工具的输入参数对于multiply工具请使用'100,25'这样的格式]
可用的工具名称有: {tool_names}
当你获取了所有必要信息并可以给出最终答案时,请以以下格式结束:
Thought: 我已经有了最终答案。
Final Answer: [最终答案]
请执行以下任务:
{input}
{agent_scratchpad}
"""
executor_prompt = ChatPromptTemplate.from_template(executor_react_prompt_template)
# 4.创建 ReAct Agent 作为执行者
executor_agent = create_react_agent(llm, tools, executor_prompt)
executor_executor = AgentExecutor(
agent=executor_agent,
tools=tools,
verbose=True,
handle_parsing_errors=True # 启用错误处理,自动重试解析错误
)
# 5.定义并运行规划模式的工作流
def execute_planning_pattern(query: str):
print("--- 启动规划模式 ---")
# 规划器分解任务
print("\n规划器正在分解任务...")
plan = planner_chain.invoke({"user_input": query})
tasks = [task.strip() for task in plan.split('\n') if task.strip()]
print("规划器生成的任务列表:")
for i, task in enumerate(tasks):
print(f" {i + 1}. {task}")
# 执行者逐一执行任务
print("\n执行者正在逐一执行任务...")
for i, task in enumerate(tasks):
print(f"\n--- 执行任务 {i + 1}: {task} ---")
executor_executor.invoke({"input": task})
print("\n--- 所有任务执行完毕!---")
if __name__ == "__main__":
test_query = "请先计算 50 乘以 60 的结果,然后告诉我上海的天气怎么样?"
execute_planning_pattern(test_query)