你是不是也刷到过各种“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 requests3.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”、“智能体框架”、“编排”这些大词吓住。它们背后都是一些你可以逐步理解和掌握的工程组件。下一步,你可以尝试用这个模式,为你自己的工作流创建一个智能体,比如自动整理会议纪要、监控系统日志并报警、或者辅助代码评审。
动手去改,去加新工具,去处理更复杂的任务。在调试和解决问题的过程中,你对智能体的理解才会真正深入骨髓。