从零构建AI智能体:200行代码实现天气查询与建议助手
你是不是也刷到过各种“AI智能体”的教程,感觉概念满天飞,但真到自己动手,却发现连个能跑起来的“Hello World”都搞不定?从“智能体框架”到“Agent编排”,各种新名词让人眼花缭乱,但核心问题始终没变: 如何用最低的成本、最清晰的路径,亲手搭建一个能理解指令、执行任务、并给出反馈的智能体?
这篇文章不空谈趋势,也不堆砌晦涩的论文术语。我们将从一个最朴素的需求出发: “帮我查一下北京的天气,并建议我今天是否适合出门跑步。” 我们将手把手,从零开始,用不到200行代码,构建一个能完成这个任务的智能体。你会看到,所谓的“智能体”开发,核心并非高深的算法,而是一套清晰的 任务分解、工具调用与决策循环 的工程化思想。
通过本文,你将彻底搞懂:
- 智能体(Agent)到底是什么? 它和普通程序、ChatGPT对话有什么区别?
- 构建智能体的最小核心组件 有哪些?我们如何用代码实现它们?
- 从想法到可运行程序 的完整路径是怎样的?环境如何搭建?代码如何组织?
- 运行中会遇到哪些“坑”?如何调试一个“发呆”或“报错”的智能体?
- 如何将这个简单的智能体,扩展成更强大的自动化助手?
本文假设你具备基础的Python编程知识,并对大语言模型(LLM)有初步了解。我们将使用当前最易获取的OpenAI API(或兼容API)作为“大脑”,但整个架构是模型无关的,你可以轻松替换为其他模型。
1. 智能体开发:解决的核心问题是什么?
在开始写代码之前,我们必须先统一认知:我们为什么要造“智能体”?它解决了什么传统编程解决不了的问题?
传统程序的困境 :对于一个“查天气并给建议”的需求,传统做法需要你:
- 手动调用天气API,解析返回的JSON数据。
- 自己编写一套逻辑规则来判断是否适合跑步(例如:温度在15-25度、无雨、PM2.5低于50)。
- 将结果拼接成一段人类可读的文字。
这个过程 高度确定 ,但也 极其僵化 。如果需求变成“查天气并建议是否适合晾被子”,你就得重写判断逻辑。每增加一个场景,就要增加一段硬编码。
智能体的优势 :智能体将“做什么”(目标)和“怎么做”(逻辑)解耦了。
- 你只需要告诉它目标 :“查北京天气,建议是否适合跑步”。
- 它自己决定步骤 :它知道自己需要先“获取天气工具”,然后“分析天气数据”,最后“生成建议”。
- 它具备泛化能力 :同样的架构,稍加训练或提示,它就能处理“晾被子”、“洗车”、“出游”等多种建议场景。
所以,智能体解决的核心问题是: 在开放、动态的环境下,将复杂的人类目标,自动分解为一系列可执行的操作序列,并自主完成。 这本质上是将一部分程序逻辑的“设计权”交给了AI。
对于我们开发者而言,构建智能体的核心工作就从“编写所有业务逻辑”,转变为:
- 定义任务目标 (用自然语言描述)。
- 提供工具集 (告诉智能体它能调用哪些API或函数)。
- 设计决策循环 (让智能体学会何时、如何使用这些工具)。
接下来,我们就围绕这三个核心,开始搭建。
2. 核心概念与架构:理解智能体的“五脏六腑”
一个最简单的智能体,通常包含以下核心组件,我们可以用一个“侦探破案”的类比来理解:
| 组件 | 技术定义 | 类比解释 | 在我们的项目中的角色 |
|---|---|---|---|
| 智能体(Agent) | 具备感知、规划、决策、执行能力的自治系统。 | 侦探本人 。他接收案件(目标),思考破案步骤(规划),决定去查什么线索(决策),并亲自或派人去执行(行动)。 | 整个程序的核心调度中枢。 |
| 大语言模型(LLM) | 智能体的“大脑”,负责理解、推理和生成。 | 侦探的推理能力和经验 。他根据已有信息分析案情,做出下一步该做什么的判断。 | 我们使用OpenAI的 gpt-3.5-turbo 等模型作为推理引擎。 |
| 工具(Tools) | 智能体可以调用的外部函数或API,用于与环境交互。 | 侦探可用的调查手段 。如询问证人(调用知识库)、查看监控(调用图像识别)、化验物证(调用科学分析API)。 | 我们将创建一个 get_weather 函数作为工具。 |
| 提示词(Prompt) | 引导LLM行为的指令和上下文信息。 | 给侦探的办案手册和当前案件简报 。手册告诉他办案的基本原则和流程,简报告诉他当前已知信息。 | 我们将编写一个 system_prompt 来定义智能体的角色和行为规范。 |
| 记忆(Memory) | 智能体存储和回忆历史交互信息的能力。 | 侦探的笔记本 。记录了他已经问过谁、查过哪里,避免重复劳动,也能串联线索。 | 本文为简化,使用单轮对话记忆(即每次只处理当前query)。复杂智能体会引入对话历史。 |
| 执行循环(Execution Loop) | 智能体“思考-行动-观察”的重复过程。 | 侦探的破案流程 :分析线索 -> 决定调查行动 -> 执行行动 -> 获得新线索 -> 继续分析...直到破案。 | 我们将用 while 循环实现一个简单的ReAct模式。 |
我们的项目架构图(简化版):
用户输入:“查北京天气,建议跑步吗?”
|
v
[智能体核心] (包含LLM和Prompt)
|-- 思考:用户需要天气和跑步建议。我需要天气数据。
|-- 决策:调用 `get_weather` 工具。
|
v
[工具执行] -> 调用天气API,获取结构化数据(温度、天气、风速...)
|
v
[智能体核心] (接收工具返回结果)
|-- 思考:已获得天气数据。现在需要根据这些数据判断是否适合跑步。
|-- 决策:无需再调用工具,直接生成最终答案。
|
v
输出:“北京当前晴,气温22度,风力3级,空气质量优。非常适合跑步!”
理解了这些概念,我们就可以开始准备开发环境了。
3. 环境准备与项目初始化
我们将创建一个干净的Python项目。请确保你的Python版本在3.8以上。
3.1 创建项目目录与虚拟环境
打开终端(命令行),执行以下步骤:
# 1. 创建项目目录并进入
mkdir weather_agent && cd weather_agent
# 2. 创建虚拟环境(推荐,避免包冲突)
python -m venv venv
# 3. 激活虚拟环境
# 在 macOS/Linux 上:
source venv/bin/activate
# 在 Windows 上:
# venv\Scripts\activate
# 激活后,命令行提示符前通常会出现 (venv) 标识
3.2 安装核心依赖
我们需要安装两个核心库:
-
openai:用于调用OpenAI的LLM API。 -
requests:用于我们的自定义工具(调用天气API)。
在激活的虚拟环境中,运行:
pip install openai requests
3.3 获取并配置API密钥
OpenAI API Key :访问 OpenAI平台 创建并复制你的API密钥。
天气API Key :我们将使用一个免费的天气API,例如 OpenWeatherMap 。注册后,在“My API keys”中获取你的Key。
安全提醒 :API密钥是敏感信息, 绝对不要 直接硬编码在代码中或提交到GitHub。我们将使用环境变量来管理。
在项目根目录下创建一个名为 .env 的文件:
# .env 文件内容
OPENAI_API_KEY=你的_openai_api_key_在这里
WEATHER_API_KEY=你的_openweathermap_api_key_在这里
然后,我们需要安装 python-dotenv 库来读取这个文件:
pip install python-dotenv
至此,环境准备完毕。你的项目目录结构目前应该是:
weather_agent/
├── venv/ # 虚拟环境目录(通常被.gitignore忽略)
├── .env # 环境变量文件(务必加入.gitignore!)
└── (后续创建的.py文件)
4. 核心模块拆解与实现
我们将把智能体拆分成几个独立的模块,这样代码更清晰,也易于维护和扩展。
4.1 第一步:构建工具(Tool)—— get_weather
工具是智能体的“手和脚”。我们先实现一个最基础的天气查询工具。
在项目根目录创建 tools.py 文件:
# tools.py
import os
import requests
from dotenv import load_dotenv
# 加载 .env 文件中的环境变量
load_dotenv()
def get_weather(city: str) -> str:
"""
根据城市名称查询实时天气信息。
参数:
city (str): 城市名称,例如 "Beijing" 或 "北京"。
返回:
str: 结构化的天气信息字符串。如果查询失败,返回错误信息。
"""
api_key = os.getenv("WEATHER_API_KEY")
if not api_key:
return "错误:未配置 WEATHER_API_KEY。请在 .env 文件中设置。"
# 这里以OpenWeatherMap的Current Weather API为例
# 注意:免费版API需要将城市名转换为英文,这里做简单处理。实际项目可能需要更完善的地理编码。
base_url = "http://api.openweathermap.org/data/2.5/weather"
# 一个简单的城市名映射,实际应用建议使用更专业的API或本地映射表
city_mapping = {
"北京": "Beijing",
"上海": "Shanghai",
"广州": "Guangzhou",
"深圳": "Shenzhen",
# 可以继续添加
}
query_city = city_mapping.get(city, city) # 如果映射里没有,就用原名称
params = {
"q": query_city,
"appid": api_key,
"units": "metric", # 使用摄氏度
"lang": "zh_cn" # 返回中文描述
}
try:
response = requests.get(base_url, params=params, timeout=10)
response.raise_for_status() # 如果状态码不是200,抛出HTTPError异常
data = response.json()
# 解析返回的JSON数据
city_name = data.get('name', '未知城市')
weather_desc = data['weather'][0]['description'] if data.get('weather') else '未知'
temp = data['main'].get('temp', '未知')
humidity = data['main'].get('humidity', '未知')
wind_speed = data['wind'].get('speed', '未知')
weather_info = (
f"城市:{city_name}\n"
f"天气状况:{weather_desc}\n"
f"温度:{temp}°C\n"
f"湿度:{humidity}%\n"
f"风速:{wind_speed} m/s"
)
return weather_info
except requests.exceptions.RequestException as e:
return f"网络请求失败,无法获取天气信息:{e}"
except (KeyError, IndexError) as e:
return f"解析天气API返回数据时出错:{e}"
except Exception as e:
return f"获取天气信息时发生未知错误:{e}"
# 本地测试这个工具
if __name__ == "__main__":
# 测试前请确保 .env 文件中的 WEATHER_API_KEY 已正确设置
test_result = get_weather("北京")
print("工具测试结果:")
print(test_result)
关键点解析 :
- 安全 :通过
load_dotenv()从.env文件安全读取密钥。 - 健壮性 :使用了
try...except捕获网络请求和数据处理中可能出现的异常。 - 清晰的返回 :工具返回一个结构化的字符串,便于后续的LLM理解。
- 可测试 :文件底部有简单的测试代码,方便单独验证工具是否工作。
运行 python tools.py ,如果配置正确,你应该能看到北京的天气信息输出。
4.2 第二步:设计提示词(Prompt)与Agent角色
提示词是智能体的“灵魂”,它定义了智能体的身份、能力和行为规范。我们创建一个 prompts.py 文件来管理提示词。
# prompts.py
# 系统提示词,定义了智能体的基本角色和行为准则
SYSTEM_PROMPT = """你是一个天气与生活建议助手。你的核心能力是调用工具获取实时天气信息,并基于此给出合理的生活建议(如出行、运动、穿衣等)。
## 你的工作流程:
1. **理解用户请求**:判断用户是否需要天气信息或基于天气的建议。
2. **调用工具**:如果需要天气数据,你必须调用 `get_weather` 工具,并提供**城市名称**作为参数。城市名称应从用户请求中提取,如果未明确,应主动询问。
3. **分析与建议**:获得天气数据后,结合用户的具体问题(如“适合跑步吗?”“要带伞吗?”),进行分析并给出友好、详细的建议。
4. **最终回答**:将天气信息和建议整合成一段流畅、自然的回复。
## 重要规则:
- 你**必须**在需要天气数据时调用工具,不能凭空编造天气。
- 工具返回的是原始数据,你需要将其转化为易懂的描述。
- 如果工具调用失败,如实告知用户,并尝试提供通用建议或询问其他城市。
- 你的回答应简洁、有用、充满关怀。
"""
# 工具的描述,用于在请求LLM时告诉它有什么工具可用
TOOL_DESCRIPTIONS = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "根据城市名称查询该城市的实时天气信息,包括天气状况、温度、湿度和风速。",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "需要查询天气的城市名称,例如:北京、Shanghai、New York。",
}
},
"required": ["city"],
},
},
}
]
为什么这样设计提示词?
- 角色清晰 :让模型明确知道“我是谁”。
- 流程明确 :给出了 step-by-step 的思考框架,符合 ReAct(Reasoning and Acting)模式。
- 规则具体 :强调了必须调用工具、不能编造、处理失败情况等,减少了模型“胡言乱语”的可能。
- 工具描述标准化 :
TOOL_DESCRIPTIONS的格式遵循了 OpenAI 的 Function Calling 规范,这是让LLM理解并决定调用哪个工具的关键。
4.3 第三步:实现智能体核心(Agent Core)与执行循环
这是最核心的部分,我们将实现一个简单的 Agent 类,它负责与LLM对话、管理工具调用和执行循环。
创建 agent_core.py 文件:
# agent_core.py
import os
import json
from openai import OpenAI
from dotenv import load_dotenv
from tools import get_weather
from prompts import SYSTEM_PROMPT, TOOL_DESCRIPTIONS
# 加载环境变量
load_dotenv()
class WeatherAgent:
"""一个简单的天气查询与建议智能体。"""
def __init__(self, model="gpt-3.5-turbo"):
"""
初始化智能体。
参数:
model (str): 使用的OpenAI模型名称。
"""
self.client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
self.model = model
self.messages = [{"role": "system", "content": SYSTEM_PROMPT}]
self.available_tools = {
"get_weather": get_weather,
}
def _call_llm(self, messages, tools=None):
"""调用OpenAI API,支持工具调用。"""
try:
kwargs = {
"model": self.model,
"messages": messages,
"temperature": 0.1, # 低温度,使输出更确定、更专注于工具调用
}
if tools:
kwargs["tools"] = tools
kwargs["tool_choice"] = "auto" # 让模型自行决定是否调用工具
response = self.client.chat.completions.create(**kwargs)
return response.choices[0].message
except Exception as e:
print(f"调用LLM API时出错:{e}")
return None
def _execute_tool(self, tool_call):
"""执行被LLM选中的工具调用。"""
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f"[Agent 正在执行工具] {function_name},参数:{function_args}")
if function_name in self.available_tools:
tool_function = self.available_tools[function_name]
try:
# 根据工具函数的参数名传递参数
# 例如:get_weather(city="北京")
result = tool_function(**function_args)
return result
except Exception as e:
return f"工具 {function_name} 执行过程中出错:{e}"
else:
return f"错误:未知的工具 '{function_name}'。"
def run(self, user_input: str):
"""
运行智能体,处理一次用户输入。
参数:
user_input (str): 用户的自然语言指令。
返回:
str: 智能体的最终回复。
"""
print(f"\n[用户输入] {user_input}")
# 1. 将用户输入添加到对话历史
self.messages.append({"role": "user", "content": user_input})
# 2. 开始执行循环(这里简化为单轮工具调用循环,复杂场景可能需要多轮)
max_steps = 5 # 防止无限循环
final_response = None
for step in range(max_steps):
print(f"\n--- 思考步骤 {step + 1} ---")
# 3. 调用LLM,传入当前对话历史和工具描述
llm_message = self._call_llm(self.messages, TOOL_DESCRIPTIONS)
if llm_message is None:
return "抱歉,思考过程出现错误。"
# 4. 将LLM的回复添加到对话历史
self.messages.append(llm_message.to_dict()) # 注意:OpenAI SDK返回的是对象,需转换
# 5. 检查LLM是否想要调用工具
if llm_message.tool_calls:
# 6. 执行所有被请求的工具
tool_responses = []
for tool_call in llm_message.tool_calls:
tool_result = self._execute_tool(tool_call)
tool_responses.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": tool_call.function.name,
"content": str(tool_result), # 结果必须是字符串
})
print(f"[工具返回] {tool_result[:100]}...") # 打印前100字符
# 7. 将工具执行结果作为消息追加,让LLM继续分析
self.messages.extend(tool_responses)
# 继续循环,让LLM基于工具结果进行下一步思考
continue
else:
# 8. LLM没有调用工具,生成了最终回复
final_response = llm_message.content
print(f"[Agent 最终回复] {final_response}")
break
if final_response is None:
final_response = "经过多次尝试,未能完成您的问题。请尝试更清晰的指令。"
# 9. 将最终回复也加入历史(为后续可能的对话扩展做准备)
self.messages.append({"role": "assistant", "content": final_response})
return final_response
# 提供一个简单的运行示例
if __name__ == "__main__":
agent = WeatherAgent()
test_queries = [
"北京天气怎么样?",
"上海今天适合跑步吗?",
"帮我看看广州的天气,我要去出差。",
]
for query in test_queries:
print("\n" + "="*50)
response = agent.run(query)
print("="*50)
核心逻辑拆解 :
- 初始化 :加载API Key,设置系统提示词,定义可用工具映射。
-
_call_llm方法 :封装了对OpenAI API的调用。关键参数tools和tool_choice告诉模型有哪些工具可用,并授权它自行决定调用。 -
_execute_tool方法 :根据LLM返回的工具调用请求,找到本地对应的Python函数并执行,传入解析好的参数。 -
run方法(执行循环) :- 步骤3-4 :LLM根据当前对话历史和工具描述进行“思考”。
- 步骤5-7 :如果LLM决定调用工具(
tool_calls不为空),则执行工具,并将结果以特定格式(role: tool)追加回对话历史。然后 跳回步骤3 ,让LLM基于新信息继续思考。这就是“思考-行动-观察”的循环。 - 步骤8 :如果LLM不调用工具了,说明它认为已经可以生成最终答案,循环结束。
- 保护机制 :设置了
max_steps防止因逻辑错误导致无限循环。
5. 运行与效果验证
现在,让我们将所有的模块组合起来,运行我们的智能体。
在项目根目录创建一个主入口文件 main.py :
# main.py
from agent_core import WeatherAgent
def main():
print("天气助手智能体启动...")
print("输入 'quit' 或 'exit' 退出程序。")
print("-" * 40)
agent = WeatherAgent()
while True:
try:
user_input = input("\n请输入您的问题:").strip()
if user_input.lower() in ['quit', 'exit', 'q']:
print("再见!")
break
if not user_input:
continue
response = agent.run(user_input)
# 主程序里可以只打印最终回复,详细过程在agent.run中已打印
# print(f"\n助手:{response}")
except KeyboardInterrupt:
print("\n\n程序被用户中断。")
break
except Exception as e:
print(f"\n程序运行出现未知错误:{e}")
if __name__ == "__main__":
main()
运行程序 : 在终端中,确保虚拟环境已激活,然后运行:
python main.py
预期成功输出示例 :
天气助手智能体启动...
输入 'quit' 或 'exit' 退出程序。
----------------------------------------
请输入您的问题:北京今天适合跑步吗?
[用户输入] 北京今天适合跑步吗?
--- 思考步骤 1 ---
[Agent 正在执行工具] get_weather,参数:{'city': '北京'}
[工具返回] 城市:Beijing\n天气状况:晴\n温度:22.5°C\n湿度:45%\n风速:2.5 m/s...
--- 思考步骤 2 ---
[Agent 最终回复] 北京当前天气晴朗,气温22.5°C,湿度45%,风速2.5m/s。这种天气条件非常适合跑步:气温适宜,空气湿度适中,风力较小。建议您做好热身,享受跑步的乐趣!
验证要点 :
- 工具调用 :观察控制台是否打印了
[Agent 正在执行工具]和[工具返回],这证明智能体成功决定并执行了工具调用。 - 最终回复 :最终回复是否 结合了工具返回的原始数据 (22.5°C,晴)和 你的问题 (适合跑步吗?)进行了推理和建议。
- 循环控制 :对于简单问题,应该在2个步骤内完成(一步调用工具,一步生成回复)。对于更复杂的问题,可能会触发更多轮思考。
你可以尝试不同的问法:
- “上海和北京的天气对比一下。”
- “我明天想去广州,需要带伞吗?”
- “深圳的湿度是多少?”
观察智能体如何理解你的意图,并做出相应的工具调用和回答。
6. 常见问题与排查思路
在搭建和运行过程中,你几乎一定会遇到下面这些问题。这里提供了详细的排查指南。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
ModuleNotFoundError: No module named 'openai' | 依赖未安装或虚拟环境未激活。 | 1. 检查命令行前缀是否有 (venv) 。 2. 运行 pip list 查看已安装包。 | 1. 激活虚拟环境: source venv/bin/activate (Mac/Linux) 或 venv\Scripts\activate (Win)。 2. 安装依赖: pip install openai requests python-dotenv 。 |
openai.AuthenticationError | OpenAI API Key 错误或未设置。 | 1. 检查 .env 文件是否存在,且与代码在同一目录。 2. 检查 .env 文件中 OPENAI_API_KEY 的值是否正确, 前后不能有空格 。 3. 在代码中临时 print(os.getenv(“OPENAI_API_KEY”)) 看是否成功读取。 | 1. 确保 .env 文件格式正确: KEY=value ,每行一个。 2. 到 OpenAI 平台确认 API Key 有效且未过期。 3. 重启你的终端或IDE。 |
| 智能体不调用工具,直接回答“北京天气是…”(编造) | 1. 提示词(SYSTEM_PROMPT)未强调必须调用工具。 2. 工具描述(TOOL_DESCRIPTIONS)格式错误或未传入。 3. 模型温度(temperature)设置过高,导致“想象力”太丰富。 | 1. 检查 agent_core.py 中初始化时 self.messages 是否包含了 SYSTEM_PROMPT 。 2. 检查 _call_llm 函数调用时是否传入了 tools=TOOL_DESCRIPTIONS 。 3. 查看LLM返回的完整消息,确认是否有 tool_calls 字段。 | 1. 强化 SYSTEM_PROMPT 中的规则,如“你必须调用工具获取数据”。 2. 确保 TOOL_DESCRIPTIONS 是包含字典的列表,且格式符合OpenAI规范。 3. 将 temperature 参数调低(如0.1),增加确定性。 |
| 工具调用失败,返回网络或解析错误 | 1. 天气 API Key 错误或未设置。 2. 网络问题或API服务不可用。 3. 城市名称无法被天气API识别。 | 1. 单独运行 python tools.py 测试工具函数。 2. 检查 .env 中的 WEATHER_API_KEY 。 3. 在 tools.py 的 get_weather 函数中打印完整的请求URL和响应,进行调试。 | 1. 注册并获取正确的天气API Key。 2. 在工具函数中添加更完善的错误处理和日志。 3. 考虑使用更健壮的地理编码服务将中文城市名转换为API接受的格式。 |
| 程序陷入无限循环,不断调用工具 | 执行循环的退出条件有问题,或者LLM在得到工具结果后,仍然认为需要继续调用工具。 | 1. 检查 max_steps 是否设置(如5)。 2. 打印每一步的 llm_message ,观察LLM在获得天气数据后,为何还决定调用工具。 | 1. 确保 max_steps 已设置并生效。 2. 优化提示词,明确告知“获得天气数据后,应直接生成最终建议”。 3. 检查工具返回的结果格式是否清晰,便于LLM理解。 |
错误: AttributeError: ‘ChatCompletionMessage’ object has no attribute ‘to_dict’ | OpenAI Python SDK 版本更新,API 返回的对象结构可能发生变化。 | 查看 openai 库的版本 ( pip show openai ),并查阅其官方文档中 ChatCompletionMessage 对象的属性。 | 新版本可能直接使用 .model_dump() 或属性访问。将 llm_message.to_dict() 改为 llm_message.model_dump() 或 llm_message.dict() ,具体取决于你的SDK版本。 |
7. 最佳实践与进阶扩展方向
现在,你已经拥有了一个可工作的智能体雏形。如何将它变得更好、更实用?以下是一些关键的最佳实践和扩展思路。
7.1 工程化最佳实践
- 配置管理 :将模型名称、温度、最大循环次数等参数提取到配置文件(如
config.yaml或.env)中,避免硬编码。 - 日志记录 :不要只使用
print。集成logging模块,将智能体的思考过程、工具调用、API请求和错误信息记录到文件,便于调试和监控。 - 错误处理与重试 :在
_call_llm和_execute_tool中增加更细致的异常捕获和重试机制(例如,网络超时重试3次)。 - 超时控制 :为LLM API调用和工具执行设置超时,防止某个环节卡死导致整个服务无响应。
- 输入验证与清洗 :在
run方法中,对user_input进行基础检查,如长度限制、敏感词过滤等。
7.2 功能扩展方向
-
增加更多工具 :智能体的能力取决于工具集。你可以轻松添加新工具:
-
search_web: 调用搜索API获取实时信息。 -
calculate_distance: 计算两地距离。 -
send_email: 发送邮件通知。 -
query_database: 查询内部数据库。 只需在tools.py中定义函数,并在agent_core.py的self.available_tools和prompts.py的TOOL_DESCRIPTIONS中注册即可。
-
-
实现多轮对话记忆(Memory) :目前的Agent是“失忆”的,每次对话独立。要实现记忆,需要:
- 维护一个不断增长的
self.messages列表。 - 注意上下文长度限制,当对话过长时,需要采用“摘要记忆”或“向量存储记忆”等策略进行压缩。
- 在
run方法开始时,将历史对话也加载到self.messages中。
- 维护一个不断增长的
-
引入规划(Planning)能力 :对于复杂任务(如“规划一个北京三日游”),智能体需要先制定一个高级计划,再逐步执行。这可以通过在提示词中引入“Chain of Thought”或使用专门的规划模块来实现。
-
使用更强大的Agent框架 :当项目复杂后,手动管理循环、工具和记忆会变得繁琐。可以考虑迁移到成熟的框架,如:
- LangChain : 生态丰富,组件齐全,学习曲线稍陡。
- LlamaIndex : 专注于数据检索和RAG(检索增强生成)。
- Semantic Kernel (微软): 与.NET生态结合紧密。
- Dify / Coze 等低代码平台 :如果你更关注快速构建应用而非底层代码。
7.3 生产环境部署考虑
- API成本与限流 :监控OpenAI API的调用量和费用。为智能体设置预算和速率限制。
- 异步处理 :对于耗时较长的工具调用(如爬虫),使用
asyncio进行异步处理,避免阻塞主线程。 - 构建Web服务 :使用
FastAPI或Flask将你的智能体封装成HTTP API,供前端或其他服务调用。 - 可观测性 :除了日志,接入监控系统(如Prometheus),跟踪请求延迟、工具调用成功率、Token消耗等关键指标。
8. 总结:从项目到认知
回顾我们搭建的这个“天气助手智能体”,代码虽短,却完整演绎了智能体技术的核心范式: 感知(用户输入)- 规划(LLM思考)- 行动(调用工具)- 观察(获取结果)- 再规划(生成回答) 。
这个项目的价值不在于它本身的功能有多强大,而在于它像一张清晰的 地图 ,为你揭示了智能体开发的全景:
- 起点是明确的用户需求 ,而不是酷炫的技术。
- 核心是LLM与工具(函数)的可靠交互 ,这需要清晰的提示词和规范的接口定义。
- 难点在于稳定、可控的执行循环 ,要处理各种边界情况和错误。
- 进阶之路在于工程化 :记忆、规划、多智能体协作、成本控制、监控告警。
不要再被“Agent”、“智能体框架”、“编排”这些大词吓住。它们背后都是一些你可以逐步理解和掌握的工程组件。下一步,你可以尝试用这个模式,为你自己的工作流创建一个智能体,比如自动整理会议纪要、监控系统日志并报警、或者辅助代码评审。
动手去改,去加新工具,去处理更复杂的任务。在调试和解决问题的过程中,你对智能体的理解才会真正深入骨髓。
更多推荐



所有评论(0)