这是一篇从零开始构建AI Agent框架的教程,通过五个步骤实现:1)构建大模型适配层;2)实现对话记忆系统;3)添加工具调用能力;4)标准化消息格式;5)整合形成完整ToolAgent。文章采用ReAct模式,让Agent能够推理并调用工具完成任务,适合编程新手跟随学习,最终实现具备Google搜索等功能的智能助手。
本教程将带你从零开始,一步步构建一个具备工具调用能力的简单 Agent 框架。即使你是编程新手,也能跟着教程完成并能成功运行代码。
📚 目录
- 什么是 Agent?
- 准备工作
- 第一步:构建"大脑"- 统一的大模型适配层
- 第二步:实现基础 Agent - 对话记忆系统
- 第三步:装备工具 - 让 Agent 能"做事"
- 第四步:消息标准化 - 统一通信格式
- 第五步:整合一切 - 完整的 ToolAgent
- 运行与测试
- 常见问题排查
- 总结与进阶
什么是 Agent?
🤖 概念理解
Agent(智能体)= 大模型(大脑)+ 记忆系统 + 工具调用能力 + 任务规划能力
比喻:
大模型
= 大脑(思考、理解、决策)
记忆系统
= 记忆(记住对话历史)
工具调用
= 手脚(执行实际任务,如搜索、计算)
任务规划
= 规划能力(分解复杂任务)
🎯 我们的实现目标
构建一个简单的 Agent,具备以下能力:
- ✅ 与用户对话并保持上下文记忆
- ✅ 调用 Google 搜索工具获取实时信息
- ✅ 自动决定何时调用工具
- ✅ 综合工具结果生成最终答案
准备工作
1 创建项目目录
# 在你的桌面创建项目目录cd ~/Desktopmkdir agentcd agent2 创建依赖管理文件
创建requirements.txt文件:
openai>=1.0.0python-dotenv>=1.0.0google-search-results>=2.4.23 安装依赖
pip3 install -r requirements.txt4 配置环境变量
创建.env文件(不要提交到 Git):
# 方案1:使用 DeepSeek(推荐,有免费额度)API_KEY=sk-your-deepseek-api-keyBASE_URL=xxxxxMODEL_NAME=deepseek-chat# 方案2:使用 OpenAI(需要 API Key)# API_KEY=sk-your-openai-api-key# BASE_URL=xxxxx# MODEL_NAME=gpt-3.5-turbo# Google 搜索 API(用于工具功能)SERPAPI_API_KEY=your-serpapi-key第一步:构建"大脑"- 统一的大模型适配层
🎯 目标
创建一个统一的大模型调用接口,屏蔽不同厂商的 API 差异。
📝 创建文件:llm.py
# llm.pyfrom openai import OpenAIimport osfrom dotenv import load_dotenvload_dotenv() # 加载环境变量class LLMClient: def __init__(self): # 通过环境变量配置,轻松切换不同厂商 self.client = OpenAI( api_key=os.getenv("API_KEY"), base_url=os.getenv("BASE_URL") ) self.model = os.getenv("MODEL_NAME", "gpt-4o") def chat(self, messages, tools=None): """ 统一的对话入口,屏蔽底层差异 参数: messages: 对话历史列表 tools: 工具定义列表(可选) 返回: OpenAI API 的响应对象 """ params = { "model": self.model, "messages": messages, } if tools: params["tools"] = tools # 这里为了演示简洁,暂不开启流式输出 return self.client.chat.completions.create(**params)💡 代码解释
核心设计思想:
1. 环境变量配置
api_key=os.getenv("API_KEY")base_url=os.getenv("BASE_URL")• 将敏感信息(API Key)放在.env文件中
• 避免硬编码在代码里,提高安全性
2. 统一接口
def chat(self, messages, tools=None): return self.client.chat.completions.create(**params)• 封装 OpenAI API 的调用细节
• 提供简单易用的chat()方法
• 支持tools参数,让 Agent 能调用工具
3. 易于切换厂商
• 只需修改.env中的BASE_URL和MODEL_NAME
• 代码完全不需要改动
🔍 为什么需要这个适配层?
❌ 没有适配层
# 硬编码,不安全,难以维护import openairesponse = openai.ChatCompletion.create( model="gpt-4o", messages=[...], api_key="sk-xxx" # 暴露在代码中)✅ 使用适配层
# 简洁、安全、易切换from llm import LLMClientllm = LLMClient()response = llm.chat([{"role": "user", "content": "你好"}])第二步:实现基础 Agent - 对话记忆系统
🎯 目标
创建一个能记住对话历史的 Agent,实现多轮对话。
📝 创建文件:agent.py
# agent.py (基础版)from llm import LLMClientclass SimpleAgent: def __init__(self): self.llm = LLMClient() # 初始化记忆,设定基础背景 self.messages = [{"role": "system", "content": "你是一个乐于助人的AI助手。"}] def chat(self, user_input): # 1. 接收:将用户输入存入记忆 self.messages.append({"role": "user", "content": user_input}) # 2. 思考:带着所有历史记录去请求 LLM response = self.llm.chat(self.messages) content = response.choices[0].message.content # 3. 闭环:将 AI 的回答也存入记忆 self.messages.append({"role": "assistant", "content": content}) return content💡 代码解释
核心概念:消息角色
# system: 设定 AI 的身份和行为规则{"role": "system", "content": "你是一个乐于助人的AI助手。"}# user: 用户的输入{"role": "user", "content": "我叫小明"}# assistant: AI 的回答{"role": "assistant", "content": "你好小明,很高兴认识你!"}工作流程(三步闭环):
📥 用户输入 → 💾 存入记忆 → 🧠 调用 LLM(带上完整历史)→ 📤 获取回答 → 💾 存入记忆 → ✅ 返回给用户
为什么需要记忆?
- 大模型本身是无状态的,每次调用都是独立的
- 通过传递历史消息,让 AI 理解上下文
- 实现多轮对话和连贯性
🧪 测试基础 Agent
创建测试文件test_agent.py:
# test_agent.pyfrom agent import SimpleAgentdef main(): agent = SimpleAgent() print("=== 简单的AI助手 ===") print("输入'quit'退出\n") while True: user_input = input("你: ") if user_input.lower() == 'quit': break response = agent.chat(user_input) print(f"Agent: {response}\n")if __name__ == "__main__": main()运行测试:
python3 test_agent.py示例对话:
=== 简单的AI助手 === 输入'quit'退出 你: 我叫susie Agent: 你好susie!我是SimpleAgent,有什么我可以帮助你的吗? 你: 你记得我叫什么吗? Agent: 当然记得,你叫susie! 你: quit第三步:装备工具 - 让 Agent 能"做事"
🎯 目标
实现工具注册和调用系统,让 Agent 能执行实际任务(如 Google 搜索)。
📝 创建文件:tools.py
# tools.pyimport inspectimport jsonimport osfrom functools import wrapsfrom google_search_results import GoogleSearchclass ToolRegistry: """工具注册中心:管理所有可用工具""" def __init__(self): self.tools = {} # 存函数实体 self.schemas = [] # 存函数说明书(JSON Schema) def register(self, func): """ 魔法装饰器:自动将 Python 函数转换为 OpenAI Tool Schema """ name = func.__name__ # 函数名 doc = func.__doc__ or "No description" # 函数文档字符串 # 解析函数签名 sig = inspect.signature(func) params = {"type": "object", "properties": {}, "required": []} # 遍历参数,生成 JSON Schema for param_name, param in sig.parameters.items(): params["properties"][param_name] = { "type": "string", "description": f"参数 {param_name}" } if param.default == inspect.Parameter.empty: params["required"].append(param_name) # 1. 生成说明书(给 LLM 看) self.schemas.append({ "type": "function", "function": { "name": name, "description": doc, "parameters": params } }) # 2. 存储函数(实际执行) self.tools[name] = func @wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper def execute(self, name, args_json): """执行器:根据 LLM 的指令运行代码""" if name in self.tools: try: args = json.loads(args_json) # 将 JSON 字符串转为字典 print(f"⚙️ [System] 正在调用工具: {name} 参数: {args}") return self.tools[name](**args) # 执行函数,解包参数 except Exception as e: return f"Error: {str(e)}" return "Tool not found"# 创建全局注册表registry = ToolRegistry()# ========== 定义工具 ==========@registry.registerdef google_search(query: str): """ 当用户询问当前事件、新闻、天气或不知道的信息时,使用此工具进行搜索。 """ try: search = GoogleSearch({ "q": query, "api_key": os.getenv("SERPAPI_API_KEY"), }) # 数据清洗:只提取前两条结果的标题和摘要,节省 Token results = search.get_dict().get("organic_results", [])[:2] return "\n".join([ f"- {r.get('title')}: {r.get('snippet')}" for r in results ]) except Exception as e: return f"搜索失败: {e}"💡 代码解释
核心设计:装饰器模式
@registry.registerdef google_search(query: str): """函数描述""" pass装饰器做了什么?
1. 提取函数信息
- 名称:
google_search - 描述:函数的文档字符串
- 参数:从类型注解
query: str中提取
2. 生成 JSON Schema(给 LLM 看的"说明书")
{ "type": "function", "function": { "name": "google_search", "description": "当用户询问当前事件、新闻、天气或不知道的信息时,使用此工具进行搜索。", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "参数 query" } }, "required": ["query"] } } }3. 存储函数(实际执行用的)
self.tools['google_search'] = google_search # 存储真实的 Python 函数为什么用装饰器?
没有装饰器时,需要手动写一遍函数,再写一遍 JSON Schema,容易出错。
使用装饰器后,只需写一次函数,自动生成说明书。
第四步:消息标准化 - 统一通信格式
🎯 目标
创建消息辅助函数,确保消息格式标准化,避免手动构造字典出错。
📝 创建文件:message.py
# message.pydef user_msg(content): """用户消息""" return {"role": "user", "content": content}def assistant_msg(content=None, tool_calls=None): """ 助手消息 - content: 文本回复(可选) - tool_calls: 工具调用请求(可选) """ msg = {"role": "assistant"} if content: msg["content"] = content if tool_calls: msg["tool_calls"] = tool_calls return msgdef tool_msg(tool_call_id, content): """ 工具消息 - tool_call_id: 工具调用 ID(关键!) - content: 工具返回结果 """ return { "role": "tool", "tool_call_id": tool_call_id, "content": str(content) }💡 代码解释
为什么需要标准化?
❌ 手动构造消息
# 容易出错messages.append({"role": "user", "content": "你好"})messages.append({"rol": "assistant", "content": "你好"}) # 拼写错误!messages.append({"role": "tool", "content": "结果"}) # 缺少 tool_call_id!✅ 使用辅助函数
# 标准化,不易出错messages.append(user_msg("你好"))messages.append(assistant_msg(content="你好"))messages.append(tool_msg("call_123", "搜索结果"))核心概念:tool_call_id(快递单号)
LLM: “帮我搜索北京天气” → 生成单号 call_abc123
↓
调用搜索工具
↓
工具返回结果,附上单号 call_abc123
↓
LLM 看到单号,知道这是北京天气的搜索结果
消息类型总结:
| 函数 | role | 必需字段 | 可选字段 | 用途 |
|---|---|---|---|---|
user_msg() | “user” | content | - | 用户输入 |
assistant_msg() | “assistant” | - | content, tool_calls | LLM 的回复(文本或工具调用) |
tool_msg() | “tool” | tool_call_id, content | - | 工具执行结果 |
第五步:整合一切 - 完整的 ToolAgent
🎯 目标
将前面所有组件整合,实现具备工具调用能力的完整 Agent。
📝 创建文件:tool_agent.py
# tool_agent.pyimport jsonfrom llm import LLMClientfrom tools import registry # 导入工具注册表from message import user_msg, assistant_msg, tool_msgclass ToolAgent: def __init__(self): self.llm = LLMClient() # 大脑 self.tools = registry # 工具箱 # self.messages 记忆系统 self.messages = [{ "role": "system", "content": "你是一个全能助手,可以调用工具获取实时信息。如果觉得已经足够回复用户了,就不用再调用工具了。" }] def chat(self, user_input): """ 支持工具调用的 ReAct 循环入口 注意:为了演示逻辑清晰,这里暂时使用非流式 """ # 1. 存入用户问题 self.messages.append(user_msg(user_input)) # 设置最大循环次数,防止 Agent 陷入死循环 max_turns = 5 turn_count = 0 while turn_count < max_turns: turn_count += 1 # 2. 调用 LLM(带上 tools 定义) print(f"\n🤖 [Thinking] 第 {turn_count} 轮思考...") response = self.llm.chat( messages=self.messages, tools=self.tools.schemas # 关键:把工具说明书发给 LLM ) response_msg = response.choices[0].message # 3. 判断 LLM 的意图 tool_calls = response_msg.tool_calls if tool_calls: # === 情况 A: LLM 想要调用工具 === # A1. 先把 LLM 的"调用指令"存入记忆(这步不能省!) ai_msg_dict = assistant_msg( content=response_msg.content, tool_calls=tool_calls ) self.messages.append(ai_msg_dict) # A2. 遍历所有工具调用请求(LLM 可能一次想调多个工具) for tool_call in tool_calls: func_name = tool_call.function.name func_args = tool_call.function.arguments call_id = tool_call.id print(f"✋ [Action] 正在调用工具: {func_name} ...") # A3. 执行真正的 Python 代码 tool_result = self.tools.execute(func_name, func_args) # A4. 构建 Tool Message(观察结果) # 关键:一定要带上 call_id,否则 LLM 不认账 tm = tool_msg(tool_call_id=call_id, content=tool_result) self.messages.append(tm) print(f"👀 [Observation] 工具返回: {tool_result[:50]}...") # A5. 循环继续 -> 回到 while 开头,把结果发给 LLM else: # === 情况 B: LLM 没调工具,直接回复 === content = response_msg.content self.messages.append(assistant_msg(content=content)) return content return "❌ 任务太复杂,超过最大循环次数。"# --- 演示代码 ---if __name__ == "__main__": # 确保 .env 里配置了 SERPAPI_API_KEY agent = ToolAgent() while True: try: user_input = input("\n👤 你:").strip() # 检查用户输入 if user_input.lower() in ['exit', 'q', '退出']: print("\n👏再见!") break # 如果用户输入为空,跳过 if not user_input: continue final_answer = agent.chat(user_input) print("\n" + "=" * 30) print(f"🤖 Final Answer:\n{final_answer}") print("=" * 30) except KeyboardInterrupt: print("\n\n 🙏 检测到中断,退出程序") break except Exception as e: print(f"\n❌ 发生错误: {e}") import traceback traceback.print_exc() # 打印详细的错误信息💡 代码解释
核心设计:ReAct 模式
ReAct = Reasoning + Acting(推理 + 行动)
用户:今天北京天气怎么样?
↓
LLM 思考:我需要查询天气信息
↓
LLM 行动:调用搜索工具
↓
观察结果:北京今天晴天,25度
↓
LLM 思考:现在我有了信息,可以回答用户了
↓
LLM 行动:生成最终回复
为什么需要循环?
一次对话可能需要多次工具调用:
用户:帮我规划北京一日游
↓
第1轮:LLM 决定先了解北京天气 → 调用搜索工具
↓
第2轮:LLM 得到天气信息,继续思考需要知道景点 → 再次调用搜索
↓
第3轮:LLM 得到景点信息,综合所有信息 → 生成完整旅游规划
关键设计点:
1. 存储调用指令(A1)
- 必须将 LLM 的工具调用请求存入记忆
- 否则下次调用时 LLM 会忘记
2. tool_call_id(A4)
- 必须带上调用 ID,让 LLM 知道结果对应哪个工具
3. 防止死循环
- 最多 5 轮工具调用,避免无限循环
运行与测试
🚀 运行 ToolAgent
python3 tool_agent.py📝 示例对话
场景1:询问天气(需要调用工具)
👤 你:今天北京天气怎么样? 🤖 [Thinking] 第 1 轮思考... ✋ [Action] 正在调用工具: google_search ... ⚙️ [System] 正在调用工具: google_search 参数: {'query': '北京天气'} 👀 [Observation] 工具返回: - 北京今天天气预报: 晴天,气温25°C... 🤖 [Thinking] 第 2 轮思考... ============================== 🤖 Final Answer: 根据搜索结果,北京今天是个好天气!晴天,气温25°C,非常适合外出活动。 ==============================场景2:简单对话(不需要工具)
👤 你:你好 🤖 [Thinking] 第 1 轮思考... ============================== 🤖 Final Answer: 你好!我是全能助手,有什么可以帮助你的吗? ==============================场景3:退出
👤 你:q 👏再见!或使用 Ctrl+C(Mac 上是 Cmd+C)
👤 你:^C 🙏 检测到中断,退出程序常见问题排查
❌ 问题1:ModuleNotFoundError
错误信息:
ModuleNotFoundError: No module named 'openai'解决方法:
pip3 install -r requirements.txt❌ 问题2:API Key 错误
错误信息:
Error code: 401 - Unauthorized解决方法:
- 检查
.env文件中的API_KEY是否正确 - 确认没有多余空格或引号
- 重启脚本
❌ 问题3:余额不足
错误信息:
Error code: 402 - Insufficient Balance解决方法:
- 充值 DeepSeek 账户
- 或切换到其他 API(如 Ollama 本地模型)
❌ 问题4:搜索失败
错误信息:
搜索失败: Invalid API Key解决方法:
- 在
.env文件中配置SERPAPI_API_KEY - 访问 SerpAPI 官网注册获取免费 Key
❌ 问题5:无法退出
现象:输入q后程序不退出
解决方法:
- 检查代码中是否有
break语句 - 确保保存了文件并重启脚本
- 使用
Ctrl+C强制退出
总结与进阶
🎯 我们实现了什么?
- ✅统一的大模型适配层- 轻松切换不同厂商
- ✅对话记忆系统- 实现多轮对话
- ✅工具注册和执行- 让 Agent 能"做事"
- ✅消息标准化- 确保通信规范
- ✅ReAct 循环- 推理+行动的智能决策
🚀 可以继续扩展的方向
1. 添加更多工具
@registry.registerdef get_weather(city: str): """获取天气信息""" pass@registry.registerdef calculate(expression: str): """计算数学表达式""" pass2. 记忆优化
- 实现记忆窗口(限制历史长度)
- 重要信息提取和总结
- 长期记忆存储(数据库)
3. 任务规划
- 分解复杂任务
- 多步骤执行
- 目标导向
4. 流式输出
- 实时显示 LLM 回复
- 提升用户体验
5. 多模态能力
- 图像处理
- 语音交互
- 文件操作
AI时代,未来的就业机会在哪里?
答案就藏在大模型的浪潮里。从ChatGPT、DeepSeek等日常工具,到自然语言处理、计算机视觉、多模态等核心领域,技术普惠化、应用垂直化与生态开源化正催生Prompt工程师、自然语言处理、计算机视觉工程师、大模型算法工程师、AI应用产品经理等AI岗位。
掌握大模型技能,就是把握高薪未来。
那么,普通人如何抓住大模型风口?
AI技术的普及对个人能力提出了新的要求,在AI时代,持续学习和适应新技术变得尤为重要。无论是企业还是个人,都需要不断更新知识体系,提升与AI协作的能力,以适应不断变化的工作环境。
因此,这里给大家整理了一份《2026最新大模型全套学习资源》,包括2026最新大模型学习路线、大模型书籍、视频教程、项目实战、最新行业报告、面试题、AI产品经理入门到精通等,带你从零基础入门到精通,快速掌握大模型技术!
由于篇幅有限,有需要的小伙伴可以扫码获取!
1. 成长路线图&学习规划
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。这里,我们为新手和想要进一步提升的专业人士准备了一份详细的学习成长路线图和规划。
2. 大模型经典PDF书籍
书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。(书籍含电子版PDF)
3. 大模型视频教程
对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识。
4. 大模型项目实战
学以致用,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。
5. 大模型行业报告
行业分析主要包括对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。
6. 大模型面试题
面试不仅是技术的较量,更需要充分的准备。
在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。
为什么大家都在学AI大模型?
随着AI技术的发展,企业对人才的需求从“单一技术”转向 “AI+行业”双背景。企业对人才的需求从“单一技术”转向 “AI+行业”双背景。金融+AI、制造+AI、医疗+AI等跨界岗位薪资涨幅达30%-50%。
同时很多人面临优化裁员,近期科技巨头英特尔裁员2万人,传统岗位不断缩减,因此转行AI势在必行!
这些资料有用吗?
这份资料由我们和鲁为民博士(北京清华大学学士和美国加州理工学院博士)共同整理,现任上海殷泊信息科技CEO,其创立的MoPaaS云平台获Forrester全球’强劲表现者’认证,服务航天科工、国家电网等1000+企业,以第一作者在IEEE Transactions发表论文50+篇,获NASA JPL火星探测系统强化学习专利等35项中美专利。本套AI大模型课程由清华大学-加州理工双料博士、吴文俊人工智能奖得主鲁为民教授领衔研发。
资料内容涵盖了从入门到进阶的各类视频教程和实战项目,无论你是小白还是有些技术基础的技术人员,这份资料都绝对能帮助你提升薪资待遇,转行大模型岗位。
大模型全套学习资料已整理打包,有需要的小伙伴可以
微信扫描下方CSDN官方认证二维码,免费领取【保证100%免费】