Agent 核心机制解析:基于 ReAct 模式的智能旅行助手实战
一、概述
本文以 chapter1_agent_demo.py 为实战案例,深入剖析 Agent 的核心工作机制。这是一个智能旅行助手的简化实现,通过模拟工具 + 真实 LLM 调用,展示了一个完整 Agent 的 Thought-Action-Observation 循环。
学习目标
- 理解 Agent 的 ReAct 工作流程
- 掌握 LLM 配置 与上下文累积的原理
- 区分系统提示词 与用户提示词的作用
- 熟悉外部工具的引入与调用流程
- 理解循环执行的意义与实现
二、ReAct 工作流程详解
2.1 什么是 ReAct?
ReAct = Reasoning + Acting
这是一种让大模型能够「思考」并「行动」的模式,核心思想是:
用户请求 → 思考(Reason) → 行动(Action) → 观察(Observation) → 思考(Reason) → ...
不断循环,直到任务完成。
2.2 完整工作流程图
┌─────────────────────────────────────────────────────────────┐
│ ReAct 循环流程 │
└─────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ 用户请求输入 │
└────────┬─────────┘
▼
┌──────────────────┐
│ 构建完整上下文 │ ← prompt_history 累积历史
│ (系统提示词+ │
│ 用户请求+ │
│ 历史对话) │
└────────┬─────────┘
▼
┌──────────────────┐
│ 调用 LLM │ ← 获取 Thought + Action
│ OpenAI API │
└────────┬─────────┘
▼
┌──────────────────┐
│ 解析 Action │
│ 正则提取工具名 │
│ 和参数 │
└────────┬─────────┘
▼
┌──────────────────┐
│ 判断: 工具调用 │────Yes────► 调用工具 ──► 获取 Observation
│ 还是结束? │ │
└────────┬─────────┘ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ 输出最终答案 │◄────────│ 返回循环继续思考 │
│ Finish[答案] │ └──────────────────┘
└──────────────────┘
```
### 2.3 代码中的循环实现
```python
for i in range(5): # 最多循环5次,防止无限循环
# 1. 构建上下文
full_prompt = "\n".join(prompt_history)
# 2. 调用 LLM
llm_output = llm_client.generate(full_prompt, system_prompt=AGENT_SYSTEM_PROMPT)
# 3. 解析 Action
action_match = re.search(r"Action: (.*)", llm_output, re.DOTALL)
# 4. 判断结束还是继续
if action_str.startswith("Finish"):
break # 任务完成,退出循环
else:
# 调用工具,获取 Observation,继续循环
三、LLM 配置
3.1 为什么要 LLM 配置?
LLM 是 Agent 的「大脑」,负责:
- 理解用户意图
- 制定执行计划
- 决定下一步行动
- 生成最终回答
3.2 代码中的 LLM 配置
python
from openai import OpenAI
class OpenAICompatibleClient:
def __init__(self, model: str, api_key: str, base_url: str):
self.model = model # 模型标识
self.client = OpenAI( # API 客户端
api_key=api_key,
base_url=base_url
)
def generate(self, prompt: str, system_prompt: str) -> str:
messages = [
{'role': 'system', 'content': system_prompt}, # 系统提示词
{'role': 'user', 'content': prompt} # 用户输入
]
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
stream=False
)
return response.choices[0].message.content
3.3 关键配置参数
| 参数 | 作用 | 示例值 |
|---|---|---|
model |
指定使用的模型 | "deepseek-chat" |
api_key |
API 认证密钥 | "sk-xxxxx" |
base_url |
API 服务地址 | "" |
3.4 调用方式
python
# 实例化客户端
llm = OpenAICompatibleClient(
model="",
api_key="",
base_url=""
)
# 调用生成
llm_output = llm.generate(
prompt="用户的问题",
system_prompt="系统提示词"
)
四、上下文累积机制
4.1 什么是上下文?
上下文 = 让 LLM 知道「之前发生了什么」
LLM 本身没有记忆 ,每次调用都是独立的。通过 prompt_history,我们为 LLM 构建了一个「会话记忆」。
4.2 prompt_history 的结构
python
prompt_history = [f"用户请求: {user_prompt}"] # 第1项:初始请求
# 循环中不断追加
for i in range(5):
# ... LLM 调用 ...
prompt_history.append(llm_output) # 第2、4、6...项:LLM 的输出
# ... 工具调用 ...
prompt_history.append(f"Observation: {observation}") # 第3、5、7...项:工具结果
4.3 完整的 prompt_history 示例
假设用户问「北京天气和景点」:
[
"用户请求: 你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。",
"Thought: 用户想知道北京天气,然后根据天气推荐景点。我应该先查询天气。
Action: get_weather(city=\"北京\")",
"Observation: 北京当前天气:晴天,26摄氏度",
"Thought: 北京是晴天,适合去故宫或长城。我需要调用景点推荐工具。
Action: get_attraction(city=\"北京\", weather=\"晴天\")",
"Observation: 根据您的情况,为您推荐:推荐故宫(明清皇宫,门票60元)和长城(世界奇迹,建议提前预约)",
"Thought: 已经获取到天气和景点信息,可以给用户最终回答了。
Action: Finish[北京今天天气晴朗,26摄氏度。建议您去故宫和长城游玩...]"
]
4.4 为什么同时追加 llm_output 和 observation?
| 追加内容 | 作用 | 目的 |
|---|---|---|
llm_output |
LLM 的 Thought + Action | 让下次 LLM 看到自己的推理过程,实现自我修正 |
observation |
工具执行结果 | 让 LLM 知道真实世界的状态 |
类比:就像人类解决问题时,会同时记住「我怎么想的」和「实际发生了什么」。
4.5 上下文累积的代码实现
python
full_prompt = "\n".join(prompt_history) # 拼接所有历史为单个字符串
llm_output = llm_client.generate(
full_prompt, # 累积的上下文
system_prompt=AGENT_SYSTEM_PROMPT # 系统提示词
)
五、系统提示词与用户提示词
5.1 两者的本质区别
| 对比项 | 系统提示词 (System Prompt) | 用户提示词 (User Prompt) |
|---|---|---|
| 定义 | 给 LLM 的「角色说明」和「行为规范」 | 用户实际的「问题或请求」 |
| 位置 | messages[0],固定不变 |
messages[1],每次变化 |
| 作用 | 告诉 LLM 「你是谁,该怎么做」 | 告诉 LLM 「要做什么」 |
| 变化频率 | 通常固定 | 每次对话都可能不同 |
5.2 代码中的实现
python
messages = [
{'role': 'system', 'content': system_prompt}, # 固定角色
{'role': 'user', 'content': prompt} # 变化的问题
]
5.3 系统提示词的设计
python
AGENT_SYSTEM_PROMPT = """
你是一个智能旅行助手。你的任务是分析用户的请求,并使用可用工具一步步地解决问题。
# 可用工具:
- `get_weather(city: str)`: 查询指定城市的天气。
- `get_attraction(city: str, weather: str)`: 根据城市和天气推荐旅游景点。
# 输出格式要求:
你的每次回复必须严格遵循以下格式,包含一对Thought和Action:
Thought: [你的思考过程和下一步计划]
Action: [你要执行的具体行动]
Action的格式必须是以下之一:
1. 调用工具:function_name(arg_name="arg_value")
2. 结束任务:Finish[最终答案]
# 重要提示:
- 每次只输出一对Thought-Action
- Action必须在同一行,不要换行
- 当收集到足够信息可以回答用户问题时,必须使用 Action: Finish[最终答案] 格式结束
"""
5.4 系统提示词的组成
┌─────────────────────────────────────────────────────────┐
│ 系统提示词结构 │
├─────────────────────────────────────────────────────────┤
│ 1. 角色定义 │
│ "你是一个智能旅行助手" │
│ │
│ 2. 工具说明 │
│ "可用工具: get_weather, get_attraction" │
│ │
│ 3. 输出格式规范 │
│ "Thought: ... \n Action: ..."
│ 4. 约束条件 │
│ "每次只输出一对Thought-Action" │
│ "Action必须在同一行" │
│ "使用Finish[答案]结束"
└─────────────────────────────────────────────────────────┘
5.5 用户提示词的作用
用户提示词是驱动整个流程的动力:
python
user_prompt = "你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。"
它决定了:
- LLM 第一次思考的方向
- 需要调用哪些工具
- 何时可以结束任务
六、LLM 输出的处理
6.1 为什么需要处理 LLM 输出?
LLM 返回的是自然语言文本,但程序需要:
- 知道下一步要执行什么动作
- 提取工具名 和参数
- 判断任务是否完成
6.2 正则表达式解析
python
# 1. 提取 Action 部分
action_match = re.search(r"Action: (.*)", llm_output, re.DOTALL)
# re.DOTALL 让 . 能匹配换行符
# 2. 判断是 Finish 还是工具调用
if action_str.startswith("Finish"):
# 提取最终答案
final_answer = re.match(r"Finish\[(.*)\]", action_str).group(1)
else:
# 3. 提取工具名
tool_name = re.search(r"(\w+)\(", action_str).group(1)
# 例如: get_weather(city="北京") → 提取 "get_weather"
# 4. 提取参数
args_str = re.search(r"\((.*)\)", action_str).group
# 例如: city="北京" → 提取 'city="北京"'
kwargs = dict(re.findall(r'(\w+)="([^"]*)"', args_str))
# 解析为字典: {"city": "北京"}
6.3 解析流程图
LLM 输出:
┌────────────────────────────────────────────────────────┐
│ Thought: 我需要查询北京的天气 │
│ Action: get_weather(city="北京") │
└────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ 正则提取 Action │
│ action_match.group(1) = "get_weather(city=\"北京\")" │
└────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ 工具名提取: tool_name = "get_weather" │
│ 参数提取: kwargs = {"city": "北京"} │
└────────────────────────────────────────────────────────┘
6.4 为什么只处理 Action,不处理 Thought?
| 部分 | 作用 | 处理方式 |
|---|---|---|
Thought |
给人看的,理解 LLM 思考过程 | 只作为文本追加到历史 |
Action |
给程序执行的,决定下一步行动 | 正则解析,程序化执行 |
设计思想:Thought 是透明化 AI 思考过程,Action 是实际执行的接口。
七、外部工具的引入与调用
7.1 为什么要引入外部工具?
LLM 的局限:
- 不知道实时信息(天气、股票、新闻等)
- 无法执行操作(查数据库、发邮件等)
工具的作用:为 LLM 补全信息 + 赋予行动能力
7.2 工具的定义方式
python
# 方式1:模拟工具(写死数据,方便测试)
def get_weather(city: str) -> str:
weather_data = {
"北京": "晴天,26摄氏度",
"上海": "小雨,22摄氏度",
# ...
}
return f"{city}当前天气:{weather_data[city]}"
# 方式2:注册到工具字典
available_tools = {
"get_weather": get_weather,
"get_attraction": get_attraction,
}
7.3 工具调用的完整流程
1. LLM 输出 "Action: get_weather(city="北京")"
2. 代码解析:
tool_name = "get_weather"
kwargs = {"city": "北京"}
3. 检查工具是否存在:
if tool_name in available_tools: # True
4. 调用工具:
observation = available_tools[tool_name](**kwargs)
# 即: get_weather(city="北京")
5. 获取结果:
observation = "北京当前天气:晴天,26摄氏度"
6. 追加到历史:
prompt_history.append(f"Observation: {observation}")
7.4 工具调用的代码实现
python
if tool_name in available_tools:
observation = available_tools[tool_name](**kwargs) # 解包参数调用
else:
observation = f"错误: 未定义的工具 '{tool_name}'"
7.5 工具返回值的处理
工具返回值会作为 Observation 追加到历史,供下一次 LLM 调用:
python
Observation: 北京当前天气:晴天,26摄氏度
LLM 会根据这个「观察结果」决定下一步行动。
八、循环执行机制
8.1 为什么需要循环?
因为复杂任务无法一步完成:
用户:我想去北京旅游
│
├── 步骤1:查天气 ──→ 晴天
│
├── 步骤2:推荐景点 ──→ 故宫、长城
│
└── 步骤3:给出建议 ──→ 完成
8.2 循环控制
python
for i in range(5): # 最多执行5次,防止无限循环
# ... 思考、行动、观察 ...
if action_str.startswith("Finish"):
break # 任务完成,主动退出
8.3 循环终止条件
| 条件 | 说明 |
|---|---|
Action: Finish[答案] |
正常完成,LLM 认为任务已达成 |
| 循环次数达到上限 | i >= 5,防止死循环 |
| Action 解析失败 | 加入错误观察,继续尝试 |
8.4 循环的作用
- 多次推理:复杂问题分解为多个简单步骤
- 自我修正:如果某步错误,后续步骤可以纠正
- 信息累积:每次循环获取新信息,逐步接近答案
九、完整执行流程
9.1 场景:查询北京天气和景点
用户输入: "你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。"
9.2 第一轮循环
┌─────────────────────────────────────────────────────────┐
│ 循环 1 │
├─────────────────────────────────────────────────────────┤
│ 输入: 用户请求 │
│ │
│ LLM 输出: │
│ Thought: 用户想了解北京天气和景点推荐。我应该先查询天气。 │
│ Action: get_weather(city="北京") │
│ │
│ 工具调用: get_weather(city="北京") │
│ 工具返回: 北京当前天气:晴天,26摄氏度 │
│ │
│ Observation: 北京当前天气:晴天,26摄氏度 │
└─────────────────────────────────────────────────────────┘
9.3 第二轮循环
┌─────────────────────────────────────────────────────────┐
│ 循环 2 │
├─────────────────────────────────────────────────────────┤
│ 输入: 用户请求 + LLM输出 + Observation │
│ │
│ LLM 输出: │
│ Thought: 北京是晴天,适合去故宫或长城。我需要调用景点推荐。│
│ Action: get_attraction(city="北京", weather="晴天") │
│ 工具调用: get_attraction(city="北京", weather="晴天") │
│ 工具返回: 根据您的情况,为您推荐:故宫和长城 │
│ │
│ Observation: 根据您的情况,为您推荐:故宫和长城 │
└─────────────────────────────────────────────────────────┘
9.4 第三轮循环
┌─────────────────────────────────────────────────────────┐
│ 循环 3 │
├─────────────────────────────────────────────────────────┤
│ 输入: 完整历史 │
│ │
│ LLM 输出: │
│ Thought: 已获取天气和景点信息,可以给用户最终回答了。 │
│ Action: Finish[北京今天天气晴朗,26摄氏度。建议您去故宫 │
│ 和长城游玩。故宫门票60元,长城建议提前预约。] │
│ │
│ ✓ 任务完成,退出循环 │
└─────────────────────────────────────────────────────────┘
十、核心设计思想总结
10.1 架构概览
┌─────────────────────────────────────────────────────────────┐
│ 用户请求 │
└──────────────────────────┬──── │
▼
┌─────────────────────────────────────────────────────────────┐
│ LLM (大脑) │
│ - 理解任务 │
│ - 制定计划 │
│ - 决策行动 │
└──────────────────────────┬──────────────────────────────────┘──────────────────────────────┘ │
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ 工具1 │ │ 工具2 │ │ 工具3 │
│ get_weather│ │ get_attraction│ │ ... │
└──────────┘ └──────────────┘ └──────────┘
│ │ │
└────────────────┼────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Observation (反馈) │
│ "天气是晴天" "推荐故宫和长城" │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────┐
│ 继续思考 or 结束任务 │
└─────────────────────────┘
10.2 关键知识点
| 知识点 | 核心要点 |
|---|---|
| ReAct 模式 | Thought-Action-Observation 循环 |
| LLM 配置 | model、api_key、base_url 三要素 |
| 上下文累积 | prompt_history 保存完整对话历史 |
| 系统提示词 | 固定的角色定义和行为规范 |
| 用户提示词 | 变化的任务输入 |
| 输出解析 | 正则提取 Action,执行工具或结束任务 |
| 工具调用 | 字典注册 + 动态调用 + 结果反馈 |
| 循环执行 | 分解复杂任务,支持自我修正 |
10.3 设计原则
- 职责分离:Thought 给人看,Action 给机器执行
- 信息透明:完整的 prompt_history 让 LLM 拥有记忆
- 反馈闭环:每次工具调用都生成 Observation 供 LLM 参考
- 安全防护:循环次数限制防止无限执行
十一、附录
11.1 完整代码结构
chapter1_agent_demo.py
├── AGENT_SYSTEM_PROMPT # 系统提示词
├── get_weather() # 天气工具(Mock)
├── get_attraction() # 景点工具(Mock)
├── available_tools # 工具注册表
├── OpenAICompatibleClient # LLM 客户端
└── run_agent() # 主循环
12.2 关键正则表达式
| 正则 | 作用 | 示例 |
|---|---|---|
r"Action: (.*)" |
提取 Action 行 | Action: get_weather(city="北京") |
r"(\w+)\(" |
提取工具名 | get_weather |
r"\((.*)\)" |
提取参数部分 | city="北京" |
r'(\w+)="([^"]*)"' |
解析参数 | {"city": "北京"} |
r"Finish\[(.*)\]" |
提取最终答案 | Finish[北京天气晴朗...] |
chapter1_agent_demo.py
AGENT_SYSTEM_PROMPT = """
你是一个智能旅行助手。你的任务是分析用户的请求,并使用可用工具一步步地解决问题。
# 可用工具:
- `get_weather(city: str)`: 查询指定城市的天气。
- `get_attraction(city: str, weather: str)`: 根据城市和天气推荐旅游景点。
# 输出格式要求:
你的每次回复必须严格遵循以下格式,包含一对Thought和Action:
Thought: [你的思考过程和下一步计划]
Action: [你要执行的具体行动]
Action的格式必须是以下之一:
1. 调用工具:function_name(arg_name="arg_value")
2. 结束任务:Finish[最终答案]
# 重要提示:
- 每次只输出一对Thought-Action
- Action必须在同一行,不要换行
- 当收集到足够信息可以回答用户问题时,必须使用 Action: Finish[最终答案] 格式结束
请开始吧!
"""
def get_weather(city: str) -> str:
"""
获取天气的模拟函数(写死数据,方便测试)
"""
weather_data = {
"北京": "晴天,26摄氏度",
"上海": "小雨,22摄氏度",
"广州": "多云,28摄氏度",
"深圳": "晴天,30摄氏度",
"成都": "阴天,20摄氏度",
"杭州": "小雨,24摄氏度",
}
if city in weather_data:
return f"{city}当前天气:{weather_data[city]}"
return f"{city}当前天气:晴天,25摄氏度(默认)"
def get_attraction(city: str, weather: str) -> str:
"""
获取景点的模拟函数(写死数据,方便测试)
"""
attractions = {
"北京": {
"晴天": "推荐故宫(明清皇宫,门票60元)和长城(世界奇迹,建议提前预约)",
"小雨": "推荐国家博物馆(免费,周一闭馆)和798艺术区(室内文艺打卡地)",
"阴天": "推荐颐和园(皇家园林,湖光山色)和天坛(古代祭天建筑)",
"多云": "推荐故宫和颐和园",
"默认": "推荐故宫和长城",
},
"上海": {
"晴天": "推荐外滩(万国建筑博览)和东方明珠(浦东地标)",
"小雨": "推荐上海博物馆(免费,周一闭馆)和田子坊(老上海风情)",
"阴天": "推荐豫园(古典园林)和南京路步行街",
"多云": "推荐外滩和豫园",
"默认": "推荐外滩和东方明珠",
},
"广州": {
"晴天": "推荐广州塔(小蛮腰,夜景超美)和白云山(羊城第一高峰)",
"小雨": "推荐陈家祠(岭南建筑艺术)和北京路步行街(千年古道)",
"阴天": "推荐沙面岛(欧陆风情建筑群)和珠江夜游",
"多云": "推荐广州塔和沙面岛",
"默认": "推荐广州塔和白云山",
},
"深圳": {
"晴天": "推荐世界之窗(不出国门的环球旅行)和东部华侨城(生态旅游)",
"小雨": "推荐深圳博物馆(免费)和华强北商业街(科技产品)",
"阴天": "推荐欢乐谷(大型主题乐园)和东门老街(深圳商业起源地)",
"多云": "推荐世界之窗和东部华侨城",
"默认": "推荐世界之窗和东部华侨城",
},
"成都": {
"晴天": "推荐大熊猫繁育研究基地(国宝家园)和宽窄巷子(老成都生活)",
"小雨": "推荐武侯祠(三国文化)和锦里古街(夜景超美)",
"阴天": "推荐杜甫草堂(诗圣故居)和春熙路(时尚购物)",
"多云": "推荐大熊猫基地和宽窄巷子",
"默认": "推荐大熊猫基地和宽窄巷子",
},
"杭州": {
"晴天": "推荐西湖(人间天堂,十景各异)和灵隐寺(千年古刹)",
"小雨": "推荐宋城(千古情演出)和河坊街(老杭州风情)",
"阴天": "推荐西溪湿地(城市绿肺)和雷峰塔(西湖最佳观景点)",
"多云": "推荐西湖和灵隐寺",
"默认": "推荐西湖和灵隐寺",
},
}
"杭州": {
"晴天": "推荐西湖(人间天堂,十景各异)和灵隐寺(千年古刹)",
"小雨": "推荐宋城(千古情演出)和河坊街(老杭州风情)",
"阴天": "推荐西溪湿地(城市绿肺)和雷峰塔(西湖最佳观景点)",
"多云": "推荐西湖和灵隐寺",
"默认": "推荐西湖和灵隐寺",
},
}
city_attractions = attractions.get(city, attractions["北京"])
weather_key = weather if weather in city_attractions else "默认"
return f"根据您的情况,为您推荐:{city_attractions.get(weather_key, city_attractions['默认'])}"
available_tools = {
"get_weather": get_weather,
"get_attraction": get_attraction,
}
from openai import OpenAI
class OpenAICompatibleClient:
"""
调用真实大模型(需配置 API)
"""
def __init__(self, model: str, api_key: str, base_url: str):
self.model = model
self.client = OpenAI(api_key=api_key, base_url=base_url)
def generate(self, prompt: str, system_prompt: str) -> str:
"""调用大模型 API"""
print("[OpenAICompatibleClient] 正在调用大模型...")
try:
messages = [
{'role': 'system', 'content': system_prompt},
{'role': 'user', 'content': prompt}
]
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
stream=False
)
answer = response.choices[0].message.content
print("[OpenAICompatibleClient] 大模型响应成功")
return answer
except Exception as e:
print(f"[OpenAICompatibleClient] 调用失败: {e}")
return f"错误:调用语言模型服务时出错。"
import re
def run_agent(user_prompt: str, llm_client):
"""
运行 Agent 的主循环
"""
print("=" * 60)
print("* 智能旅行助手 Agent(工具Mock + LLM真实调用)")
print("=" * 60)
print(f"\n> 用户请求: {user_prompt}\n")
prompt_history = [f"用户请求: {user_prompt}"]
for i in range(5):
print(f"\n{'-'*60}")
print(f"循环 {i+1}")
print(f"{'-'*60}")
full_prompt = "\n".join(prompt_history)
llm_output = llm_client.generate(full_prompt, system_prompt=AGENT_SYSTEM_PROMPT)
print(f"\n[LLM 输出]")
print(llm_output)
prompt_history.append(llm_output)
action_match = re.search(r"Action: (.*)", llm_output, re.DOTALL)
if not action_match:
observation = "错误: 未能解析到 Action 字段"
print(f"\n[观察] {observation}")
prompt_history.append(f"Observation: {observation}")
continue
action_str = action_match.group(1).strip()
if action_str.startswith("Finish"):
final_answer = re.match(r"Finish\[(.*)\]", action_str).group(1)
print(f"\n*** 任务完成!")
print(f"最终答案: {final_answer}")
break
tool_name = re.search(r"(\w+)\(", action_str).group(1)
args_str = re.search(r"\((.*)\)", action_str).group(1)
kwargs = dict(re.findall(r'(\w+)="([^"]*)"', args_str))
print(f"\n[调用工具] {tool_name}")
print(f"[参数] {kwargs}")
if tool_name in available_tools:
observation = available_tools[tool_name](**kwargs)
else:
observation = f"错误: 未定义的工具 '{tool_name}'"
print(f"\n[工具返回] {observation}")
prompt_history.append(f"Observation: {observation}")
print("\n" + "=" * 60)
print("对话历史:")
print("=" * 60)
for i, msg in enumerate(prompt_history, 1):
print(f"\n[{i}] {msg}")
return prompt_history
if __name__ == "__main__":
print("\n" + "~" * 50)
print("\n开始测试 Agent...\n")
API_KEY = ""
BASE_URL = ""
MODEL_ID = "t"
llm = OpenAICompatibleClient(
model=MODEL_ID,
api_key=API_KEY,
base_url=BASE_URL
)
user_prompt = "你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。"
run_agent(user_prompt, llm)
print("\n" + "~" * 50)
print("\n测试完成!\n")