hello-agents 使用教程
本教程基于 Datawhale 社区开源项目《从零开始构建智能体》,系统讲解 AI Native 智能体的原理与实践。从基础概念到高级技术,涵盖经典范式、低代码平台、框架开发、记忆系统、上下文工程、通信协议、强化学习、性能评估及综合案例,帮助读者从 LLM 使用者成长为智能体构建者。
1. 项目简介与适用人群
第一章:项目简介与适用人群
欢迎来到《从零开始构建智能体》!在正式开始动手之前,我们得先搞清楚两件事:这个项目到底是干什么的?它适合谁看? 就像你拿到一本新书,总得先看看目录和前言,才知道值不值得花时间读下去,对吧?
这一章的目标很简单——让你在 10 分钟内搞清楚:
- 这个教程能帮你学到什么
- 你需要具备什么基础
- 学完之后你能做什么
- 以及,为什么你应该选择这个教程而不是其他资料
前置条件
读这一章不需要任何技术基础。你只需要:
- 对“智能体”或“AI Agent”这个概念有一点点好奇
- 愿意花几分钟了解这个项目的全貌
如果你已经迫不及待想敲代码了,可以直接跳到下一章。但如果你还在犹豫“我该不该学这个”,那这一章就是为你准备的。
这个项目是什么?
先说说背景。2024 年大家都在比谁家的模型更大、更强,但到了 2025 年,风向变了——大家开始关心:怎么用这些模型做出真正有用的东西? 这就是“智能体”(Agent)的舞台。
但问题来了:市面上关于智能体的教程,要么太理论(讲概念但没法动手),要么太零散(教你用某个工具但不懂原理)。Hello-Agents 项目就是来填补这个空白的。
简单说,这是一个系统性、重实践的智能体学习教程,由 Datawhale 社区发起和维护。它的核心理念是:最好的学习方式就是动手实践。
你可能听说过两种构建智能体的方式:
这个教程聚焦的是后者——真正的 AI Native Agent。我们会带你穿透各种框架的表象,从核心原理出发,理解智能体到底是怎么工作的,然后亲手把它造出来。
你能学到什么?
读完整个教程,你会经历一个从“使用者”到“构建者”的蜕变。具体来说:
基础篇(第一到三章)
- 理解智能体到底是什么——不只是“调用 API”,而是真正理解它的定义、类型和经典范式
- 了解智能体从符号主义到 LLM 驱动的演进历史
- 掌握大语言模型的基础知识:Transformer 架构、提示工程、主流模型及其局限
实战篇(第四到七章)
- 手把手实现经典范式:ReAct(思考-行动-观察循环)、Plan-and-Solve(先规划再执行)、Reflection(自我反思)
- 玩转低代码平台:了解 Coze、Dify、n8n 这些工具怎么用,快速搭建原型
- 掌握主流框架:AutoGen、AgentScope、LangGraph 等框架的实际应用
- 自研框架:基于 OpenAI 原生 API,从零构建你自己的智能体框架——这个项目叫 HelloAgents,是教程的配套框架
进阶篇(第八到十二章)
- 记忆与检索:让智能体记住对话历史,实现 RAG(检索增强生成)
- 上下文工程:处理长对话中的“情境理解”问题
- 通信协议:MCP、A2A、ANP 等协议解析
- Agentic-RL:从监督微调(SFT)到 GRPO 的全流程训练实战
- 性能评估:如何衡量一个智能体好不好用
综合案例篇(第十三到十五章)
- 智能旅行助手:MCP 与多智能体协作的真实应用
- 自动化深度研究智能体:复现 DeepResearch Agent
- 赛博小镇:Agent 与游戏的结合,模拟社会动态
毕业设计(第十六章)
- 构建属于你自己的完整多智能体应用
除此之外,社区还贡献了面试题总结、Dify 保姆级教程、上下文工程补充知识等额外内容。
这个教程适合谁?
说实话,这个教程的门槛不高,但天花板不低。我们来拆解一下:
如果你是以下人群,这个教程非常适合你:
1. LLM 使用者想进阶 你已经会用 ChatGPT、调用 API 了,但想知道“怎么让模型自己干活,而不是每次都要我手写提示词”。这个教程会带你从“调 API”升级到“构建智能体”。
2. 学生/研究人员 你想系统学习智能体的原理,而不是零散地看博客。教程从基础到高级,层层递进,适合作为学习路线图。
3. 开发者想转型 AI 应用 你已经是程序员,但还没接触过 AI 应用开发。教程会带你从环境搭建开始,一步步构建完整的智能体应用。
4. 求职者准备面试 社区贡献了专门的面试题总结和答案,覆盖 Agent 岗位的常见问题。
你需要什么基础?
- 编程基础:至少会 Python 基础语法(变量、函数、类)。如果你完全不会编程,建议先花一周学一下 Python 基础
- 基本命令行操作:知道怎么打开终端、运行命令
- 对 LLM 有基本了解:知道什么是提示词、什么是 API 调用。如果你完全没接触过,第三章会帮你补上
这个教程不适合谁?
- 只想看概念不想动手:教程强调实践,每章都有代码和实验。如果你只想读理论,可能会觉得“太累”
- 想找“一键部署”的解决方案:教程教的是原理和实现,不是给你一个开箱即用的产品
- 完全零编程基础:虽然门槛不高,但完全不会编程的话,建议先学 Python 基础
为什么选择这个教程?
你可能在想:“网上那么多教程,为什么偏偏选这个?”
1. 完全免费,开源社区驱动 Datawhale 社区维护,所有内容免费开放。你不仅可以学,还可以贡献——提 issue、提 PR,甚至成为贡献者。
2. 系统性强,不是零散文章 很多教程只讲某个框架怎么用,但你不理解为什么。这个教程从原理到实践,从基础到高级,是一条完整的学习路径。
3. 重实践,有配套框架 教程配套的 HelloAgents 框架 让你从零开始构建自己的智能体,而不是只会用别人的工具。
4. 覆盖面试和求职 社区贡献了面试题总结,学完可以直接去面试 Agent 相关岗位。
如何开始学习?
你有两种方式阅读这个教程:
方式一:在线阅读(推荐)
直接打开浏览器就能看,不需要下载任何东西。
方式二:本地阅读
如果你想在本地阅读或贡献内容,可以参考下一章的安装指南。
常见问题
Q:这个教程需要 GPU 吗? A:大部分内容不需要。你只需要有 OpenAI API 或其他 LLM API 的访问权限。只有第十一章 Agentic-RL 涉及模型训练,才需要 GPU。
Q:教程里的代码能直接跑吗? A:可以。每章的代码都是可运行的,但你需要配置好 API Key 和环境。
Q:学完这个教程能找到工作吗? A:教程覆盖了 Agent 岗位的核心知识,配合社区贡献的面试题,能帮你准备面试。但找工作还需要项目经验和综合能力。
Q:教程会更新吗? A:会的。Datawhale 社区持续维护,你可以在 GitHub 上关注项目更新。
好了,现在你已经知道这个项目是干什么的了。如果你觉得这正是你需要的,那就继续往下走吧——下一章我们会教你如何安装环境、配置 API,为动手实践做好准备。
2. 安装与环境准备
好的,我们开始吧。
第 2 章:安装与环境准备
在开始动手构建智能体之前,我们得先把“工具箱”准备好。想象一下,你要开始做一顿大餐,总得先把锅碗瓢盆、食材调料都备齐了,对吧?这一章的目标就是帮你把电脑环境配置好,让你能顺利运行本书后续所有的代码示例和项目。我们会一起完成三件事:安装 Python、配置一个干净的虚拟环境、以及获取调用大语言模型(LLM)所需的 API 密钥。
前置条件:
- 一台能正常上网的电脑(Windows、macOS 或 Linux 都可以)。
- 基本的电脑操作能力,比如打开终端(命令行)、下载文件、解压缩。
第一步:安装 Python
本书的所有代码都基于 Python 3.9 或更高版本。如果你不确定电脑上有没有 Python,或者版本太低,我们先来检查一下。
打开终端(命令行):
- Windows:按下
Win + R键,输入cmd,然后回车。 - macOS / Linux:打开“终端”(Terminal)应用。
- Windows:按下
检查 Python 版本:在终端里输入以下命令,然后回车:
python --version或者(在某些系统上):
python3 --version预期结果:你会看到类似
Python 3.9.x、Python 3.10.x或更高版本的信息。如果遇到问题:
- 提示“python 不是内部或外部命令”:这说明你的电脑还没安装 Python。
- 版本低于 3.9:比如显示
Python 2.7.x或Python 3.8.x,我们需要升级。
安装或升级 Python:
- 访问 Python 官方网站:https://www.python.org/downloads/
- 下载适合你操作系统的最新 Python 3.9+ 版本(比如 Python 3.12.x)。
- 重要:在 Windows 安装时,务必勾选 “Add Python to PATH” 这个选项,否则你之后在命令行里可能找不到
python命令。 - 安装完成后,重新打开一个终端,再次运行
python --version命令,确认安装成功。
第二步:创建虚拟环境
虚拟环境就像是一个独立的“小房间”,每个项目都有自己的房间,里面放着它需要的 Python 库。这样做的好处是,不同项目之间不会互相干扰。比如项目 A 需要 requests 库的 2.0 版本,项目 B 需要 3.0 版本,有了虚拟环境,它们就能和平共处。
我们使用 Python 自带的 venv 模块来创建虚拟环境。
选择一个目录:在你的电脑上找一个合适的位置,创建一个新文件夹,比如就叫
hello-agents。这个文件夹将用来存放本书的所有代码。打开终端并进入该目录:
cd 你的路径/hello-agents比如,如果你在桌面上创建了这个文件夹,在 macOS/Linux 上可能是
cd ~/Desktop/hello-agents,在 Windows 上可能是cd C:\Users\你的用户名\Desktop\hello-agents。创建虚拟环境:在终端里运行以下命令:
python -m venv venv- 第一个
venv是 Python 的模块名。 - 第二个
venv是你想给这个虚拟环境起的名字,通常就叫venv,方便记忆。
预期结果:命令执行后,你的
hello-agents文件夹里会多出一个名为venv的子文件夹,里面就是独立的 Python 环境。- 第一个
激活虚拟环境:
- Windows:
.\venv\Scripts\activate - macOS / Linux:
source venv/bin/activate
预期结果:激活后,你会看到终端命令行的最前面多了一个
(venv)的提示,像这样:(venv) C:\Users\你的用户名\Desktop\hello-agents>或者
(venv) yourname@yourcomputer hello-agents %看到
(venv)就说明你已经成功进入虚拟环境了。之后你安装的所有 Python 库,都会被装在这个“小房间”里。- Windows:
第三步:安装项目依赖
本书的代码依赖一些第三方库,比如 openai(用来调用 OpenAI 兼容的 API)、requests(用来发送网络请求)等。我们先把最核心的几个装上。
确保虚拟环境已激活:确认你的终端前面有
(venv)标志。安装核心库:在终端里运行:
pip install openai requests预期结果:你会看到类似
Successfully installed openai-1.x.x requests-2.x.x的信息。这表示安装成功。如果遇到问题:
- 下载速度慢:可以尝试使用国内的镜像源,比如清华源。在命令后面加上
-i https://pypi.tuna.tsinghua.edu.cn/simple:pip install openai requests -i https://pypi.tuna.tsinghua.edu.cn/simple
- 下载速度慢:可以尝试使用国内的镜像源,比如清华源。在命令后面加上
第四步:获取 API 密钥
智能体的“大脑”是大语言模型(LLM),比如 GPT-4、Claude、或者国内的通义千问、DeepSeek 等。要让我们的代码能调用这些模型,需要先获取一个 API 密钥(API Key),它就像一把钥匙,证明你有权限使用这个服务。
本书的示例主要基于 OpenAI 的 API 格式,因为很多国产模型也兼容这种格式,所以非常通用。
方案一:使用 OpenAI 官方 API(需要海外支付方式)
- 访问 OpenAI API 官网。
- 注册或登录账号。
- 进入 API Keys 页面,点击 “Create new secret key”。
- 复制生成的密钥(以
sk-开头)。注意:关闭页面后,你就再也看不到这个密钥了,所以一定要先保存好。
方案二:使用国内兼容的 API(推荐初学者)
国内很多大模型厂商也提供兼容 OpenAI 格式的 API,而且通常有免费额度,对新手非常友好。这里以 DeepSeek 为例(因为它速度快、价格便宜、且兼容性好):
- 访问 DeepSeek 开放平台。
- 注册账号并登录。
- 在左侧菜单找到 “API Keys”,点击 “创建 API Key”。
- 给你的密钥起个名字(比如
hello-agents),然后创建并复制它。
方案三:使用 Datawhale 社区提供的免费 API(如果可用)
在本书的学习过程中,Datawhale 社区有时会提供临时的免费 API 供大家练习。请关注本书的配套社群或项目公告,获取相关信息。
第五步:配置环境变量
把 API 密钥直接写在代码里是非常不安全的,万一不小心把代码传到 GitHub 上,别人就能用你的密钥了。正确的做法是把它存在环境变量里。
在项目根目录创建
.env文件:在hello-agents文件夹下,创建一个名为.env的文件(注意文件名前面有一个点)。编辑
.env文件:用记事本或任何文本编辑器打开它,写入以下内容(如果你用的是 DeepSeek,就填 DeepSeek 的密钥和地址):# 你的 API 密钥 OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # API 的基础地址(如果是 OpenAI 官方,这行可以不加或注释掉) OPENAI_BASE_URL="https://api.deepseek.com"- 注意:
OPENAI_API_KEY这个变量名是通用的,很多库都默认读取它。OPENAI_BASE_URL用来指定非 OpenAI 官方的服务地址。如果你用的是 OpenAI 官方,可以不加这一行。
- 注意:
安装
python-dotenv库:这个库能帮我们自动读取.env文件里的配置。在终端(确保虚拟环境已激活)运行:pip install python-dotenv
第六步:验证环境
现在,我们来写一小段代码,验证整个环境是否配置成功。
在
hello-agents文件夹下,创建一个新文件,命名为test_env.py。用文本编辑器打开它,写入以下代码:
import os from dotenv import load_dotenv from openai import OpenAI # 1. 加载 .env 文件中的环境变量 load_dotenv() # 2. 从环境变量中读取 API 密钥和基础地址 api_key = os.getenv("OPENAI_API_KEY") base_url = os.getenv("OPENAI_BASE_URL") # 3. 检查密钥是否读取成功 if not api_key: raise ValueError("请先在 .env 文件中设置 OPENAI_API_KEY") # 4. 创建 OpenAI 客户端 # 如果 base_url 为空(即没有设置),则默认使用 OpenAI 官方地址 client = OpenAI(api_key=api_key, base_url=base_url) # 5. 发送一个简单的请求,测试连接 try: response = client.chat.completions.create( model="deepseek-chat", # 如果你用 OpenAI,可以改成 "gpt-3.5-turbo" messages=[ {"role": "user", "content": "你好,请用一句话介绍你自己。"} ] ) print("模型回复:", response.choices[0].message.content) print("\n✅ 环境配置成功!一切准备就绪。") except Exception as e: print(f"❌ 请求失败,请检查你的 API 密钥和网络连接。") print(f"错误信息:{e}")运行测试脚本:在终端(确保在
hello-agents目录下,且虚拟环境已激活)运行:python test_env.py预期结果:如果一切顺利,你会看到类似下面的输出:
模型回复: 你好!我是 DeepSeek,一个由深度求索公司开发的 AI 助手。我擅长回答问题、提供信息和协助解决问题。有什么我可以帮你的吗? ✅ 环境配置成功!一切准备就绪。如果遇到问题:
openai.NotFoundError或类似错误:通常是因为model名字填错了,或者base_url不对。请检查你的.env文件和代码中的模型名。openai.AuthenticationError:说明 API 密钥无效或已过期。请重新检查并复制你的密钥。- 网络连接错误:如果你在国内使用 OpenAI 官方 API,可能需要特殊的网络环境。建议先使用 DeepSeek 等国内服务。
小结
到这里,你已经完成了所有准备工作。回顾一下,你做到了:
- 安装了 Python 3.9+,为运行代码提供了基础环境。
- 创建并激活了虚拟环境,让项目依赖互不干扰。
- 安装了
openai、requests和python-dotenv等核心库。 - 获取了 API 密钥,拿到了调用大模型的门票。
- 配置了环境变量,安全地存储了敏感信息。
- 运行了测试脚本,成功让代码和“智能体的大脑”对话了。
现在,你的电脑已经是一个合格的“智能体开发工作站”了。在下一章,我们将正式开始学习如何构建一个最简单的智能体,让它能根据你的指令去思考和行动。准备好了吗?我们出发!
3. 快速上手:在线阅读与本地部署
在线阅读与本地部署
本章的目标很简单:让你在 5 分钟内就能开始阅读《从零开始构建智能体》的全部内容。我们会先走通最省事的在线阅读,再搞定本地部署——后者在你需要离线阅读或修改文档时很有用。
前置条件
在线阅读(零安装)
项目提供了两个访问入口,选一个就行:
打开浏览器输入上面任意一个地址,你会看到完整的教程页面。左侧是目录树,点击章节标题就能跳转。所有内容都是实时更新的,不需要下载任何东西。
预期结果:浏览器显示教程首页,左侧有完整的章节列表(前言、第一章到第十六章、社区精选等)。
本地部署(离线阅读 + 可修改)
如果你想把整个教程拉到本地,方便离线看或者自己改内容,按下面几步来。
第一步:克隆仓库
打开终端,执行:
git clone https://github.com/datawhalechina/hello-agents.git
cd hello-agents预期结果:当前目录下多了一个 hello-agents 文件夹,里面包含 docs/、README.md 等文件。
常见问题:
- 如果提示
git: command not found,说明你没装 Git。去 git-scm.com 下载安装,或者用 GitHub Desktop 这类图形工具。 - 网络慢的话,可以试试国内镜像:
git clone https://gitee.com/datawhalechina/hello-agents.git
第二步:安装依赖
教程文档是用 MkDocs 构建的,我们需要安装它和推荐的主题:
pip install mkdocs mkdocs-material预期结果:命令执行完毕,没有报错。可以用 pip list | grep mkdocs 确认安装成功。
常见问题:
- 如果提示
pip: command not found,检查 Python 是否安装,或者用python -m pip install ...代替。 - 建议在虚拟环境里安装,避免污染全局 Python。如果你不熟悉虚拟环境,直接装也行,不影响使用。
第三步:启动本地服务器
在项目根目录(就是 hello-agents 文件夹里)运行:
mkdocs serve预期结果:终端输出类似 INFO - Building documentation... INFO - Serving on http://127.0.0.1:8000 的信息。打开浏览器访问 http://127.0.0.1:8000,你会看到和在线阅读一模一样的页面。
实用技巧:
mkdocs serve支持热重载——你修改了docs/下的 Markdown 文件,浏览器会自动刷新,不用手动重启。- 按
Ctrl+C可以停止服务器。
常见报错:
Error: The 'material' theme is not installed:你跳过了第二步,或者安装时网络断了。重新执行pip install mkdocs-material。Address already in use:8000 端口被占用了。换个端口:mkdocs serve -a 0.0.0.0:8080。
一个小例子串起来
假设你正在通勤路上,手机信号不好,想离线看第四章的 ReAct 范式。你可以:
- 提前在家用
git clone把仓库拉到电脑上。 - 运行
mkdocs serve启动本地服务器。 - 用浏览器打开
http://127.0.0.1:8000,找到第四章开始阅读。 - 看到一半想记笔记,直接在
docs/chapter4/第四章 智能体经典范式构建.md里加注释,浏览器会自动刷新显示修改后的内容。
注意事项
- 在线阅读的两个地址内容完全一致,选网速快的那个就行。
- 本地部署后,
docs/目录下的 Markdown 文件就是教程原文。你可以用任何文本编辑器打开、修改,甚至提交 PR 贡献内容。 - 如果你只想读不想改,在线阅读是最省事的方案,没必要折腾本地部署。
4. 第一部分:智能体与语言模型基础(概念、历史、LLM 基础)
第一部分:智能体与语言模型基础
在动手搭建智能体之前,我们需要先搞清楚三个问题:智能体到底是什么?它从哪来?以及驱动它的语言模型是怎么工作的?这一章就是回答这三个问题,帮你建立必要的知识地基。跳过这部分直接写代码,你可能会在后续遇到"为什么我的智能体不按预期行动"这类困惑。
前置条件
1. 智能体的定义与核心特征
我们先给"智能体"一个精确的定义。在 AI 领域,智能体(Agent)是指能够感知环境、做出决策并采取行动以实现目标的系统。
这个定义包含三个核心要素:
- 感知:获取环境信息(比如用户输入、传感器数据)
- 决策:基于感知信息选择下一步行动
- 行动:执行决策,改变环境状态
一个简单的例子:你问 ChatGPT"今天天气怎么样",它回答了你。这算智能体吗?严格来说不算——因为它只做了一次"感知-决策-行动"循环,没有持续的目标导向行为。
真正的智能体应该是这样的:你让它"帮我规划下周去北京的行程",它先查天气、再查航班、然后订酒店、最后生成行程表——每一步都基于上一步的结果调整下一步行动。
2. 智能体的类型
根据能力复杂度,智能体可以分为四个层次:
| 类型 | 特点 | 例子 |
|---|---|---|
| 反应式 | 只对当前输入做出反应,无记忆 | 简单的聊天机器人 |
| 基于模型 | 维护内部状态,能推理 | 带上下文的对话系统 |
| 目标驱动 | 有明确目标,能规划路径 | 旅行规划助手 |
| 效用驱动 | 在多个目标间权衡最优解 | 资源调度系统 |
目前我们讨论的 LLM 智能体,大多属于目标驱动或效用驱动类型。
3. 智能体的经典范式
智能体如何工作?学术界总结了几种经典范式,这里先了解概念,后续章节会手把手实现:
ReAct(Reasoning + Acting) 最常用的范式。智能体先"思考"(推理当前状态),再"行动"(调用工具或回答问题),然后观察结果,继续思考。就像你解数学题:先想用什么公式,再计算,看结果对不对,不对就换方法。
Plan-and-Solve 先制定完整计划,再逐步执行。适合复杂任务,比如"写一篇论文":先规划大纲,再写每个章节。
Reflection 执行后自我反思,改进结果。比如写完代码后,自己检查一遍再提交。
4. 智能体发展简史
了解历史不是为了考试,而是理解为什么今天 LLM 智能体这么火。
1950s-1980s:符号主义时代 智能体基于规则和逻辑推理。代表:Newell 和 Simon 的"通用问题求解器"。问题:规则写不完,遇到新情况就崩。
1990s-2010s:行为主义时代 智能体通过与环境交互学习。代表:强化学习、机器人控制。问题:训练成本高,泛化能力弱。
2020s 至今:LLM 驱动时代 大语言模型让智能体"开窍"了。原因很简单:LLM 能理解自然语言、有常识推理能力、能调用工具。这三点恰好解决了前两个时代的痛点。
5. 大语言模型基础
5.1 Transformer 架构(一句话版)
LLM 的核心是 Transformer,它做了一件事:让模型知道句子中每个词和其他词的关系。
比如"他吃了苹果,因为__很饿",Transformer 能算出"他"和"很饿"的关联,从而推断空白处填"他"。
5.2 提示工程(Prompt Engineering)
提示是人和 LLM 沟通的接口。写好提示,智能体才能正确执行任务。
基本原则:
- 明确角色:告诉模型它是谁
- 明确任务:告诉模型要做什么
- 明确格式:告诉模型怎么输出
# 好的提示
你是一个旅行规划助手。用户想去北京玩3天,预算5000元。
请生成一个包含景点、交通、住宿的行程表,用Markdown表格输出。
# 差的提示
帮我规划北京旅游。5.3 主流 LLM 对比
| 模型 | 特点 | 适用场景 |
|---|---|---|
| GPT-4 | 综合能力强,支持工具调用 | 通用智能体 |
| Claude 3 | 长上下文,安全性好 | 文档分析、代码生成 |
| Gemini | 多模态能力强 | 图片/视频理解 |
| 开源模型(Llama 3, Qwen 2) | 可本地部署,可微调 | 隐私敏感场景 |
5.4 LLM 的局限性
了解局限比了解能力更重要,因为智能体的很多坑都来自这里:
- 幻觉:模型会编造事实。解决方案:加入验证机制
- 上下文窗口:模型能记住的信息有限。解决方案:记忆系统(后续章节)
- 推理不稳定:同样的输入可能得到不同输出。解决方案:多次采样取多数
- 工具调用错误:模型可能传错参数。解决方案:参数校验
6. 一个小例子串起来
假设你要做一个"智能客服助手",它需要:
- 理解用户问题(感知)
- 决定是直接回答还是查知识库(决策)
- 执行相应操作(行动)
这个智能体需要:
- LLM 来理解自然语言(第三章内容)
- ReAct 范式来循环推理(第四章内容)
- 记忆系统来记住对话历史(第八章内容)
你现在已经知道它为什么需要这些组件,以及它们各自解决什么问题。
常见坑位与排查
坑1:把 LLM 当成万能的 LLM 不是神,它不知道实时信息、不会精确计算、不能保证事实准确。智能体需要工具来弥补这些短板。
坑2:忽略提示的重要性 同样的 LLM,提示写得好和写得差,效果天差地别。花时间打磨提示,比换模型更有效。
坑3:不理解"智能体"和"聊天机器人"的区别 聊天机器人只做一次问答。智能体有目标、有规划、有循环。如果你只是调 API 问问题,那还不是智能体。
下一步
概念讲完了,接下来我们会进入第二部分:动手实现这些范式。你会看到 ReAct 到底怎么写代码,低代码平台怎么用,以及怎么从零搭建自己的智能体框架。
5. 第二部分:构建你的大语言模型智能体(经典范式、低代码平台、框架开发、自研框架)
第二部分:构建你的大语言模型智能体
这一章是整本书的核心动手环节。前面你理解了智能体是什么、LLM 怎么工作,现在我们要亲手把它造出来。我们会走四条路:先手撸经典范式(ReAct、Plan-and-Solve、Reflection),再体验低代码平台(Coze、Dify、n8n),接着用主流框架(AutoGen、AgentScope、LangGraph)开发,最后从零自研一个框架。每一条路都对应不同的场景——从理解原理到快速落地,再到深度定制。
前置条件:已完成第二章的环境准备(Python 3.10+、OpenAI API Key 或兼容接口、必要的 pip 包)。如果你还没装好,先回去搞定。
4.1 手撸经典范式:ReAct、Plan-and-Solve、Reflection
为什么要手写?框架封装了太多细节,你很难理解智能体到底在"思考"什么。手写一遍,你就能看清每一步:LLM 输出什么、我们怎么解析、怎么决定下一步。
4.1.1 ReAct:思考-行动-观察循环
ReAct 的核心是让 LLM 交替输出"思考"和"行动",然后我们根据行动结果提供"观察",再让 LLM 继续思考。这是最基础的 Agent 模式。
先写一个最小可运行的 ReAct 循环:
import json
from openai import OpenAI
client = OpenAI() # 确保环境变量 OPENAI_API_KEY 已设置
def call_llm(messages):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
temperature=0
)
return response.choices[0].message.content
def search_tool(query):
# 模拟一个搜索工具,实际可替换为真实 API
knowledge = {
"北京人口": "约 2188 万(2023年)",
"上海人口": "约 2475 万(2023年)"
}
return knowledge.get(query, f"未找到关于「{query}」的信息")
# ReAct 系统提示词
system_prompt = """你是一个智能助手,可以通过思考、行动、观察来回答问题。
请按以下格式输出:
思考:你的推理过程
行动:工具名称(参数)
观察:工具返回的结果
...(可重复多轮)
思考:最终结论
答案:你的最终回答
可用工具:
- search_tool(query): 搜索信息"""
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": "北京和上海哪个城市人口更多?"}
]
max_steps = 5
for step in range(max_steps):
response = call_llm(messages)
print(f"\n=== 第 {step+1} 轮 ===")
print(response)
if "答案:" in response:
break
# 解析行动
if "行动:" in response:
action_line = [l for l in response.split("\n") if "行动:" in l][0]
action = action_line.replace("行动:", "").strip()
# 简单解析:search_tool(北京人口)
tool_name = action.split("(")[0]
arg = action.split("(")[1].rstrip(")")
if tool_name == "search_tool":
result = search_tool(arg)
messages.append({"role": "user", "content": f"观察:{result}"})预期结果:你会看到 LLM 先思考需要查人口数据,然后调用 search_tool,拿到结果后比较,最终给出答案。
常见坑:
- LLM 输出格式不稳定:有时不写"行动:"直接写"Action:"。可以在 system prompt 里强调格式,或者用 few-shot 示例。
- 解析失败:如果 action_line 不存在,程序会报错。加个 try/except 或默认重试。
4.1.2 Plan-and-Solve:先计划再执行
ReAct 是一边想一边做,Plan-and-Solve 则是先制定完整计划,再逐步执行。适合复杂任务。
plan_prompt = """你是一个计划制定者。对于用户的问题,请先制定一个详细的执行计划。
计划格式:
步骤1: 描述
步骤2: 描述
...
然后按计划执行,每步输出:
执行步骤1: 具体操作
观察:结果"""
messages = [
{"role": "system", "content": plan_prompt},
{"role": "user", "content": "帮我比较北京和上海的人口、面积、GDP"}
]
# 第一轮:生成计划
response = call_llm(messages)
print("计划:", response)
# 解析步骤并执行(简化版)
steps = [l for l in response.split("\n") if l.startswith("步骤")]
for step_desc in steps:
# 这里实际需要更复杂的解析,示例略
print(f"执行:{step_desc}")4.1.3 Reflection:自我反思修正
Reflection 让 Agent 在得到结果后,自己检查是否正确,必要时修正。
reflection_prompt = """你是一个智能体。完成任务后,请反思你的答案:
1. 答案是否完整?
2. 是否有遗漏信息?
3. 是否需要补充?
如果答案有问题,请输出「需要修正:」并给出修正后的答案。
如果答案正确,请输出「答案正确」。"""
# 在 ReAct 循环结束后,追加反思
messages.append({"role": "user", "content": reflection_prompt})
reflection = call_llm(messages)
print("反思结果:", reflection)4.2 低代码平台:Coze、Dify、n8n
手写代码理解原理,但实际项目中你可能想快速搭建。低代码平台就是干这个的。
4.2.1 Coze(字节跳动)
Coze 是面向消费者的 Agent 搭建平台,拖拽式操作,内置插件商店。
快速上手:
- 访问 coze.cn,注册账号
- 点击「创建 Bot」
- 在「人设与回复」里写系统提示词
- 在「技能」里添加插件(搜索、计算器等)
- 点击「发布」即可获得 API 或分享链接
最佳实践:
- 提示词要写清楚角色和限制,比如「你是一个旅行助手,只回答旅行相关问题」
- 插件不要加太多,3-5 个足够,否则 LLM 选择困难
- 用「知识库」上传文档,让 Agent 能回答私有数据
4.2.2 Dify(开源)
Dify 是开源的低代码平台,可以自部署。
本地部署(Docker 方式):
git clone https://github.com/langgenius/dify.git
cd dify/docker
cp .env.example .env
docker compose up -d访问 http://localhost:3000,注册后创建应用。
关键区别:Dify 支持工作流编排,你可以把多个 LLM 调用串起来,比如先分类再回答。
4.2.3 n8n(自动化工作流)
n8n 不是专门的 Agent 平台,但可以用它编排 LLM 和外部工具。
最小示例:创建一个工作流,接收 Webhook 请求 -> 调用 OpenAI -> 发送邮件。
适用场景:需要把 Agent 集成到现有业务系统(CRM、ERP)时,n8n 比 Coze/Dify 更灵活。
4.3 框架开发:AutoGen、AgentScope、LangGraph
当低代码平台不够灵活,手写又太繁琐时,框架是折中方案。
4.3.1 AutoGen(微软)
AutoGen 的核心是多 Agent 对话。你定义多个 Agent,它们互相聊天完成任务。
pip install pyautogenimport autogen
# 定义两个 Agent
assistant = autogen.AssistantAgent(
name="assistant",
llm_config={"config_list": [{"model": "gpt-4o-mini", "api_key": "..."}]}
)
user_proxy = autogen.UserProxyAgent(
name="user_proxy",
human_input_mode="NEVER",
code_execution_config={"work_dir": "coding"}
)
# 开始对话
user_proxy.initiate_chat(
assistant,
message="写一个 Python 脚本,计算斐波那契数列前 20 项"
)预期结果:Assistant 会生成代码,UserProxy 自动执行并返回结果,Assistant 再根据结果调整。
常见坑:
- 代码执行默认在本地,注意安全(不要执行 rm -rf /)
- 如果 Agent 陷入死循环,设置
max_consecutive_auto_reply=3
4.3.2 AgentScope(阿里)
AgentScope 强调分布式和多模态,适合需要视觉、语音的 Agent。
pip install agentscopeimport agentscope
from agentscope.agents import DialogAgent
agentscope.init(model_configs={
"config_name": "my_gpt",
"model_type": "openai",
"model_name": "gpt-4o-mini"
})
agent = DialogAgent(
name="assistant",
model_config_name="my_gpt",
sys_prompt="你是一个有帮助的助手。"
)
response = agent("今天天气怎么样?")
print(response)4.3.3 LangGraph(LangChain)
LangGraph 让你用图结构定义 Agent 流程,节点是 LLM 调用或工具,边是条件跳转。
pip install langgraph langchain-openaifrom langgraph.graph import StateGraph, END
from typing import TypedDict, List
class AgentState(TypedDict):
messages: List
def call_model(state):
# 调用 LLM
return {"messages": [llm_response]}
def should_continue(state):
if "需要工具" in state["messages"][-1]:
return "tool"
return END
graph = StateGraph(AgentState)
graph.add_node("agent", call_model)
graph.add_node("tool", call_tool)
graph.add_conditional_edges("agent", should_continue)
graph.set_entry_point("agent")
app = graph.compile()LangGraph 的优势:你可以精确控制流程,比如「如果 LLM 输出包含代码,先执行再返回结果」。
4.4 自研框架:HelloAgents
前面三种方式各有局限:手写太原始、低代码不够灵活、框架太重。自研框架让你完全掌控。
4.4.1 核心设计
一个最小 Agent 框架只需要三个组件:
- LLM 接口:封装 API 调用
- 工具注册:让 Agent 知道能用什么工具
- 循环引擎:决定何时思考、何时行动、何时结束
# helloagents/core.py
from openai import OpenAI
import json
class Agent:
def __init__(self, model="gpt-4o-mini"):
self.client = OpenAI()
self.model = model
self.tools = {}
self.messages = []
def register_tool(self, name, func, description):
self.tools[name] = {"func": func, "description": description}
def run(self, user_input, max_steps=10):
self.messages.append({"role": "user", "content": user_input})
for step in range(max_steps):
response = self.client.chat.completions.create(
model=self.model,
messages=self.messages,
tools=self._build_tool_schema(),
tool_choice="auto"
)
msg = response.choices[0].message
if msg.tool_calls:
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
result = self.tools[func_name]["func"](**args)
self.messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
})
else:
return msg.content
return "达到最大步数"
def _build_tool_schema(self):
return [
{
"type": "function",
"function": {
"name": name,
"description": info["description"],
"parameters": {"type": "object", "properties": {}}
}
}
for name, info in self.tools.items()
]4.4.2 使用示例
from helloagents import Agent
agent = Agent()
def get_weather(city):
return f"{city} 天气:晴,25°C"
agent.register_tool("get_weather", get_weather, "查询城市天气")
result = agent.run("北京今天天气怎么样?")
print(result)预期结果:Agent 会调用 get_weather 工具,拿到结果后组织成自然语言回答。
4.4.3 扩展方向
- 添加记忆系统(保存历史对话)
- 支持多 Agent 协作(Agent 之间互相调用)
- 加入错误重试机制
实战串联:做一个旅行规划 Agent
把上面学到的串起来。我们用自研框架,结合 ReAct 范式,做一个能查天气、查航班、推荐景点的旅行助手。
# travel_agent.py
from helloagents import Agent
import datetime
agent = Agent()
def get_weather(city, date=None):
# 模拟天气 API
return f"{city} {date or '今天'} 天气:晴,22-28°C"
def search_flights(from_city, to_city, date):
return f"找到航班:{from_city}->{to_city},{date},价格 ¥800"
def recommend_attractions(city):
return f"{city} 推荐景点:故宫、长城、颐和园"
agent.register_tool("get_weather", get_weather, "查询城市天气")
agent.register_tool("search_flights", search_flights, "搜索航班")
agent.register_tool("recommend_attractions", recommend_attractions, "推荐景点")
result = agent.run("帮我规划一个北京三日游,包括天气、航班和景点")
print(result)6. 第三部分:高级知识扩展(记忆与检索、上下文工程、通信协议、Agentic-RL、性能评估)
好的,我们开始吧。
从“能用”到“好用”:为什么需要高级知识扩展?
在上一部分,你已经亲手搭建了自己的智能体框架,让它能调用工具、执行计划,甚至进行简单的反思。恭喜你,你已经迈过了“从无到有”的门槛。但你可能也发现了,这个智能体有点“健忘”——你跟它聊了几句,它就忘了你一开始提的要求;它有时会“断章取义”——只盯着你最后一句话,忽略了整个对话的上下文;它还很“孤独”——只能跟你单聊,没法跟其他智能体协作。
这一章,我们就要解决这些问题。我们会一起给智能体装上“记忆”、拓宽它的“视野”、教会它“社交”,甚至让它学会“自我进化”和“自我评估”。这些高级知识,正是把一个“能用”的智能体,打磨成“好用”、“可靠”的智能体的关键。
前置条件:你已经完成了第七章,拥有一个自己编写的、能运行的基础智能体框架(比如 HelloAgent)。你熟悉 Python 和基本的 API 调用。
第八章:记忆与检索——让智能体不再“金鱼脑”
你有没有跟 ChatGPT 聊着聊着,发现它忘了你一开始说的“我叫小明”?这就是因为它没有长期记忆。我们的智能体也一样。默认情况下,每次对话都是“全新”的。要让智能体记住关键信息,我们需要给它装上“记忆系统”。
8.1 记忆的三种形态
智能体的记忆,可以粗略分为三种:
- 短期记忆:就像你手里的便签纸,记下当前对话的内容。通常就是对话历史(
messages列表)。 - 长期记忆:像你的日记本,记录重要的、需要跨会话保留的信息。比如用户的偏好、关键事实。
- 工作记忆:像你的工作台,临时存放当前任务需要的数据。比如工具调用的结果。
我们重点实现长期记忆,因为这是让智能体“成长”的关键。
8.2 动手实现:一个简单的“事实提取”记忆系统
我们不搞复杂的数据库,先用一个最直观的方法:让智能体在每次对话结束时,自己总结出需要记住的“事实”,然后存到一个文件里。下次对话开始时,再把这些事实读出来,塞进系统提示词里。
第一步:编写记忆存储函数
在你的 HelloAgent 框架里,新建一个 memory.py 文件。
# memory.py
import json
import os
MEMORY_FILE = "agent_memory.json"
def load_memory():
"""从文件加载长期记忆"""
if os.path.exists(MEMORY_FILE):
with open(MEMORY_FILE, "r", encoding="utf-8") as f:
return json.load(f)
return []
def save_memory(memory_list):
"""将长期记忆列表保存到文件"""
with open(MEMORY_FILE, "w", encoding="utf-8") as f:
json.dump(memory_list, f, ensure_ascii=False, indent=2)第二步:让智能体学会“记笔记”
在智能体处理完一轮对话后,我们额外调用一次 LLM,让它从本轮对话中提取出需要长期记住的事实。
# 在你的 agent.py 中,修改 run 方法
def run(self, user_input):
# ... 之前的对话逻辑 ...
# 假设 self.messages 已经包含了本轮对话
# 1. 构造一个“记忆提取”提示
extract_prompt = {
"role": "system",
"content": (
"请从以下对话中提取出需要长期记住的关键事实。"
"例如:用户的姓名、偏好、重要日期、项目进展等。"
"如果没有任何需要记住的信息,请返回一个空列表 []。"
"请只返回 JSON 格式的列表,例如:[\"用户名叫小明\", \"用户喜欢喝咖啡\"]"
)
}
# 2. 调用 LLM 进行提取(复用你的 llm 调用函数)
extraction_messages = [extract_prompt] + self.messages[-4:] # 只看最近几轮
facts_json = self.call_llm(extraction_messages)
# 3. 解析结果并合并到长期记忆
try:
new_facts = json.loads(facts_json)
if isinstance(new_facts, list):
existing_memory = load_memory()
# 简单去重(更复杂的可以用语义相似度)
for fact in new_facts:
if fact not in existing_memory:
existing_memory.append(fact)
save_memory(existing_memory)
print(f"[记忆] 新记住: {new_facts}")
except json.JSONDecodeError:
print("[记忆] 提取失败,LLM 返回格式不对")第三步:让智能体学会“回忆”
在每次对话开始时,把长期记忆注入到系统提示词里。
# 在 agent 初始化或每次 run 开始时
def _build_system_prompt(self):
base_prompt = "你是一个有用的助手。"
memory = load_memory()
if memory:
memory_str = "\n".join([f"- {fact}" for fact in memory])
base_prompt += f"\n\n## 你记得的关于用户的信息:\n{memory_str}"
return {"role": "system", "content": base_prompt}预期结果:现在,你跟智能体说“我叫小明,我喜欢喝冰美式”。它会在本轮回答后,默默记下这两条事实。下次你再启动对话,它就会在系统提示词里看到这些信息,并主动说:“小明你好,今天还要来一杯冰美式吗?”
常见问题:
- 记忆膨胀:如果每次对话都提取,记忆文件会越来越大。解决办法:限制记忆条数(比如最多50条),或者让 LLM 定期“总结”和“遗忘”旧记忆。
- 格式错误:LLM 返回的 JSON 可能不标准。可以用
try-except捕获,或者用更宽松的解析方式(比如用正则表达式提取[...]部分)。
8.3 进阶:RAG(检索增强生成)
上面的方法只能存“事实”,但存不了“文档”。如果你的智能体需要参考一本手册、一堆论文,就需要 RAG。
RAG 的核心流程是:用户提问 -> 将问题转为向量 -> 在知识库中搜索最相似的文本块 -> 把搜索到的文本块作为上下文,连同问题一起发给 LLM。
你可以用 chromadb 或 faiss 这样的向量数据库。这里不展开,但你可以把 RAG 看作是“记忆”的一种更强大的形式——它让智能体拥有了“查阅资料”的能力。
小结:现在,你的智能体有了“记性”。它不再是一个每次见面都像陌生人的聊天机器人,而是一个能记住你、了解你的伙伴。
第九章:上下文工程——让智能体“看懂”全局
有了记忆,智能体记住了“你是谁”。但在一段很长的对话里,它还是会“迷失”。比如你聊了10分钟A项目,突然问“那个截止日期是什么?”,它可能还在想A项目,但你说的其实是B项目。这就是上下文理解的问题。
上下文工程,就是一系列主动管理对话上下文的技术,确保 LLM 始终“知道”当前在聊什么、目标是什么、已经完成了什么。
9.1 核心问题:窗口有限,信息无限
LLM 的上下文窗口是有限的(比如 128K tokens)。你不能把整个对话历史都塞进去。所以我们需要“取舍”。
9.2 动手实现:上下文压缩与摘要
一个实用的技巧是:当对话历史超过一定长度时,对前面的内容进行“压缩”或“摘要”。
第一步:实现一个上下文管理器
# context_manager.py
class ContextManager:
def __init__(self, max_tokens=4000):
self.max_tokens = max_tokens
self.history = [] # 存储原始消息
self.summary = "" # 存储压缩后的摘要
def add_message(self, message):
self.history.append(message)
# 检查是否超限(这里用简单字符数估算,实际应用需用 tokenizer)
if len(str(self.history)) > self.max_tokens * 4:
self._compress()
def _compress(self):
"""调用 LLM 对早期历史进行摘要"""
# 取最早的一半历史进行压缩
early_history = self.history[:len(self.history)//2]
compress_prompt = {
"role": "system",
"content": (
"请将以下对话历史压缩成一个简短的摘要,"
"保留所有关键信息、决定和用户偏好。"
)
}
# 调用 LLM 生成摘要
summary_text = call_llm([compress_prompt] + early_history)
self.summary = summary_text
# 移除已被压缩的历史
self.history = self.history[len(self.history)//2:]
def get_context(self):
"""获取当前上下文,包含摘要和最近历史"""
context = []
if self.summary:
context.append({
"role": "system",
"content": f"[对话历史摘要] {self.summary}"
})
context.extend(self.history)
return context第二步:在智能体中使用上下文管理器
在你的 HelloAgent 中,用 ContextManager 替代原来的 self.messages 列表。
# agent.py
from context_manager import ContextManager
class HelloAgent:
def __init__(self):
self.context = ContextManager(max_tokens=4000)
# ... 其他初始化
def run(self, user_input):
self.context.add_message({"role": "user", "content": user_input})
messages = self.context.get_context()
# 调用 LLM
response = self.call_llm(messages)
self.context.add_message({"role": "assistant", "content": response})
return response预期结果:现在,即使你跟智能体聊了上百轮,它也不会“失忆”。它会把早期的内容压缩成一段摘要,然后专注于最近的对话。你问“那个截止日期”,它会先看摘要里有没有提到,再看最近的对话,从而给出准确的回答。
实用技巧:
- 滑动窗口:除了摘要,也可以直接丢弃最早的消息,只保留最近 N 轮。这是最简单的方法。
- 结构化提示:在系统提示词里明确告诉 LLM 当前任务的状态,比如“你正在完成一个旅行计划,已经确定了目的地是巴黎,正在讨论酒店预订。” 这比让它自己猜要高效得多。
小结:上下文工程让你的智能体有了“大局观”。它不再断章取义,而是能结合整个对话的脉络来理解你的意图。
第十章:智能体通信协议——让智能体学会“社交”
你的智能体现在很“聪明”,但它很孤独。如果能让多个智能体协作,比如一个负责搜索,一个负责总结,一个负责写报告,那威力将成倍增长。这就需要通信协议。
10.1 什么是智能体通信协议?
简单说,就是一套标准化的消息格式和交互规则,让不同的智能体(甚至不同团队开发的智能体)能互相理解、协同工作。
目前比较热门的协议有:
- MCP (Model Context Protocol):由 Anthropic 提出,侧重于让 LLM 应用(如 Claude Desktop)与外部工具和数据源交互。你可以把它理解为“AI 界的 USB 协议”。
- A2A (Agent-to-Agent):由 Google 提出,侧重于智能体之间的直接通信和任务协作。
- ANP (Agent Network Protocol):更通用的智能体网络协议。
10.2 动手实现:用 MCP 让你的智能体“用上”计算器
我们以 MCP 为例,因为它最贴近“工具调用”的概念,而且有现成的 Python SDK。
第一步:安装 MCP SDK
pip install mcp第二步:创建一个 MCP 服务器(提供计算器工具)
# calculator_server.py
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
import mcp.server.stdio
import mcp.types as types
# 创建一个服务器实例
server = Server("calculator")
@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
"""声明这个服务器提供的工具"""
return [
types.Tool(
name="calculate",
description="执行数学计算",
inputSchema={
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "数学表达式,例如 '2 + 2' 或 'sqrt(16)'",
}
},
"required": ["expression"],
},
)
]
@server.call_tool()
async def handle_call_tool(
name: str, arguments: dict
) -> list[types.TextContent]:
"""实际执行工具调用"""
if name == "calculate":
expression = arguments["expression"]
try:
# 安全地计算表达式(生产环境请用更安全的方法)
result = eval(expression, {"__builtins__": {}}, {})
return [types.TextContent(type="text", text=str(result))]
except Exception as e:
return [types.TextContent(type="text", text=f"计算错误: {e}")]
async def run():
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="calculator",
server_version="0.1.0",
),
)
if __name__ == "__main__":
import asyncio
asyncio.run(run())第三步:让你的智能体连接 MCP 服务器
在你的 HelloAgent 中,添加一个 MCP 客户端,用来发现和调用远程工具。
# agent.py (部分修改)
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
class HelloAgent:
def __init__(self):
# ... 其他初始化
self.mcp_tools = [] # 存储从 MCP 服务器发现的工具
async def connect_mcp_server(self, command: str, args: list[str]):
"""连接到 MCP 服务器并获取工具列表"""
server_params = StdioServerParameters(
command=command,
args=args7. 第四部分:综合案例进阶(智能旅行助手、自动化深度研究、赛博小镇)
好的,我们开始吧。
第十三章 智能旅行助手
本章目标
学完前面那么多理论,你肯定手痒了,想用它们做个真正能用的东西。本章我们就来干这件事:用 MCP 协议和多智能体协作,搭建一个能帮你规划旅行、查天气、订餐厅的智能旅行助手。做完它,你就能理解“协议”和“协作”在真实世界里是怎么落地、怎么解决实际问题的。
前置条件
- 你已经读完了第十章“智能体通信协议”,知道 MCP 是什么、Client/Server 怎么交互。
- 你的电脑上已经装好了 Python 3.10+ 和
pip。 - 你有一个可用的 OpenAI API Key(或其他兼容的 LLM API Key),并且知道怎么在环境变量里设置它(比如
export OPENAI_API_KEY="sk-...")。 - 你已经安装了
hello-agents项目所需的依赖(如果还没装,可以回到第二章快速过一下)。
第一步:理解我们要做什么
先别急着写代码,我们想清楚目标。
一个旅行助手,至少得能干这几件事:
- 查天气:知道目的地未来几天的天气,好决定带什么衣服。
- 查景点/餐厅:知道当地有什么好玩的、好吃的。
- 规划行程:根据上面查到的信息,生成一个合理的日程安排。
如果让一个智能体自己干所有事,它得内置一大堆 API 调用逻辑,代码会变得又臭又长。更好的方式是:让一个“总指挥”智能体,去调用几个专门的“工具”智能体。每个工具智能体只负责一件事,比如“天气查询专家”、“景点推荐专家”。它们之间通过 MCP 协议通信。
这就是多智能体协作的典型模式。我们这一章,就是要亲手实现这个模式。
第二步:搭建 MCP 服务器(工具提供方)
MCP 服务器就是提供工具的地方。我们先写一个最简单的天气查询服务器。
在你的项目目录下,新建一个文件 weather_server.py:
# weather_server.py
import json
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
import mcp.server.stdio
import mcp.types as types
# 模拟的天气数据,真实场景下你会调用第三方天气 API
def get_weather(city: str, date: str) -> str:
"""根据城市和日期返回模拟天气"""
weather_data = {
"北京": {"2025-07-15": "晴,28-35°C", "2025-07-16": "多云,26-33°C"},
"上海": {"2025-07-15": "小雨,25-30°C", "2025-07-16": "阴,24-29°C"},
"杭州": {"2025-07-15": "晴,27-34°C", "2025-07-16": "晴,26-33°C"},
}
city_weather = weather_data.get(city, {})
return city_weather.get(date, f"抱歉,没有{city}在{date}的天气数据")
# 创建 MCP 服务器实例
server = Server("weather-server")
# 注册一个工具:查询天气
@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
return [
types.Tool(
name="get_weather",
description="查询指定城市在指定日期的天气情况",
inputSchema={
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称,如北京"},
"date": {"type": "string", "description": "日期,格式 YYYY-MM-DD,如 2025-07-15"},
},
"required": ["city", "date"],
},
)
]
# 处理工具调用请求
@server.call_tool()
async def handle_call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "get_weather":
city = arguments.get("city")
date = arguments.get("date")
result = get_weather(city, date)
return [types.TextContent(type="text", text=result)]
else:
raise ValueError(f"未知工具: {name}")
# 启动服务器
async def main():
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="weather-server",
server_version="0.1.0",
),
)
if __name__ == "__main__":
import asyncio
asyncio.run(main())预期结果:运行 python weather_server.py,你不会看到任何输出,因为它在等待 MCP 客户端连接。这很正常,说明服务器已经跑起来了。
第三步:搭建 MCP 客户端(工具调用方)
现在,我们需要一个“总指挥”智能体,它知道怎么连接天气服务器,并根据用户的问题决定是否调用天气工具。
新建 travel_agent.py:
# travel_agent.py
import asyncio
import json
from openai import OpenAI
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
# 初始化 LLM 客户端
client = OpenAI()
# 定义系统提示词,告诉智能体它可以做什么
SYSTEM_PROMPT = """
你是一个智能旅行助手。你可以使用以下工具来帮助用户规划旅行:
- get_weather: 查询天气。调用时需要提供 city 和 date 参数。
当用户提出旅行相关问题时,先思考是否需要使用工具。如果需要,就调用工具获取信息,然后基于信息给出回答。
"""
async def main():
# 1. 连接到 MCP 服务器
server_params = StdioServerParameters(
command="python",
args=["weather_server.py"] # 启动天气服务器的命令
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# 2. 初始化会话
await session.initialize()
# 3. 获取服务器提供的工具列表
tools_result = await session.list_tools()
# 将 MCP 工具格式转换为 OpenAI 可用的 tool 格式
tools = [
{
"type": "function",
"function": {
"name": tool.name,
"description": tool.description,
"parameters": tool.inputSchema,
}
}
for tool in tools_result.tools
]
print("🤖 智能旅行助手已启动!输入 'quit' 退出。")
# 4. 开始对话循环
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
while True:
user_input = input("\n👤 你: ")
if user_input.lower() == 'quit':
break
messages.append({"role": "user", "content": user_input})
# 5. 调用 LLM,并传入可用的工具
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto"
)
assistant_message = response.choices[0].message
messages.append(assistant_message)
# 6. 检查 LLM 是否想要调用工具
if assistant_message.tool_calls:
for tool_call in assistant_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f"🔧 调用工具: {function_name}({function_args})")
# 通过 MCP 会话调用工具
result = await session.call_tool(function_name, function_args)
# 提取结果文本
result_text = result.content[0].text if result.content else ""
print(f"📊 工具返回: {result_text}")
# 将工具调用结果返回给 LLM
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result_text
})
# 7. 让 LLM 基于工具结果生成最终回答
final_response = client.chat.completions.create(
model="gpt-4o",
messages=messages
)
final_message = final_response.choices[0].message
print(f"🤖 助手: {final_message.content}")
messages.append(final_message)
else:
# LLM 直接回答了,没有调用工具
print(f"🤖 助手: {assistant_message.content}")
if __name__ == "__main__":
asyncio.run(main())预期结果:运行 python travel_agent.py,你会看到启动提示。输入“北京7月15号天气怎么样?”,你会看到类似这样的输出:
🔧 调用工具: get_weather({'city': '北京', 'date': '2025-07-15'})
📊 工具返回: 晴,28-35°C
🤖 助手: 北京7月15号天气晴朗,气温在28到35摄氏度之间,建议穿着轻薄衣物,注意防晒。常见报错与排查:
ModuleNotFoundError: No module named 'mcp':说明你没装mcp库。运行pip install mcp。- 连接被拒绝或工具调用失败:确保
weather_server.py和travel_agent.py在同一个目录下,并且weather_server.py没有语法错误。可以先单独运行python weather_server.py看看有没有报错。 - LLM 不调用工具:检查你的
SYSTEM_PROMPT是否写清楚了工具的功能和调用时机。有时候模型需要更明确的指示。
第四步:扩展:加入景点推荐服务器
一个工具不够,我们再做一个景点推荐服务器 attraction_server.py:
# attraction_server.py
from mcp.server import Server
from mcp.server.models import InitializationOptions
import mcp.server.stdio
import mcp.types as types
def get_attractions(city: str, interest: str = "热门") -> str:
"""根据城市和兴趣返回推荐景点"""
attractions = {
"北京": {"热门": "故宫、天安门、长城、颐和园", "美食": "王府井小吃街、簋街", "文化": "国家博物馆、798艺术区"},
"上海": {"热门": "外滩、东方明珠、迪士尼", "美食": "城隍庙、南京路步行街", "文化": "上海博物馆、田子坊"},
"杭州": {"热门": "西湖、灵隐寺、雷峰塔", "美食": "河坊街、龙井村", "文化": "浙江省博物馆、中国美术学院"},
}
city_data = attractions.get(city, {})
return city_data.get(interest, f"抱歉,没有找到{city}关于{interest}的推荐")
server = Server("attraction-server")
@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
return [
types.Tool(
name="get_attractions",
description="查询指定城市的景点推荐,可以指定兴趣类型(热门、美食、文化)",
inputSchema={
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"},
"interest": {"type": "string", "description": "兴趣类型,可选值:热门、美食、文化,默认为热门"},
},
"required": ["city"],
},
)
]
@server.call_tool()
async def handle_call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "get_attractions":
city = arguments.get("city")
interest = arguments.get("interest", "热门")
result = get_attractions(city, interest)
return [types.TextContent(type="text", text=result)]
else:
raise ValueError(f"未知工具: {name}")
async def main():
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="attraction-server",
server_version="0.1.0",
),
)
if __name__ == "__main__":
import asyncio
asyncio.run(main())现在,你需要修改 travel_agent.py,让它同时连接两个服务器。关键改动在 main 函数里:
# 在 travel_agent.py 的 main 函数中,修改连接部分
async def main():
# 同时启动两个服务器
server_params_weather = StdioServerParameters(
command="python",
args=["weather_server.py"]
)
server_params_attraction = StdioServerParameters(
command="python",
args=["attraction_server.py"]
)
# 使用 asyncio.gather 同时管理两个连接
async with stdio_client(server_params_weather) as (read_w, write_w), \
stdio_client(server_params_attraction) as (read_a, write_a):
async with ClientSession(read_w, write_w) as session_w, \
ClientSession(read_a, write_a) as session_a:
await session_w.initialize()
await session_a.initialize()
# 合并两个服务器的工具列表
tools_w = await session_w.list_tools()
tools_a = await session_a.list_tools()
all_tools = tools_w.tools + tools_a.tools
# ... 后续代码类似,但需要根据工具名称判断调用哪个 session
# 这里为了简洁,我们只演示思路,实际需要维护一个工具名到 session 的映射实用技巧:在实际项目中,你通常会用一个工具注册中心或配置文件来管理多个 MCP 服务器,而不是像上面这样硬编码。但作为入门,理解这个“一对多”的模式已经足够了。
第五步:串联一个真实场景
现在,我们来模拟一个完整的旅行规划对话:
- 用户:“我打算7月15号去杭州玩两天,帮我规划一下。”
- 助手(思考):“我需要先查杭州7月15号和16号的天气,再查杭州有什么好玩的
8. 第五部分:毕业设计与未来展望
第十六章 毕业设计:构建属于你的完整多智能体应用
走到这一步,你已经掌握了从 LLM 基础到高级技术(记忆、上下文工程、通信协议、强化学习、评估)的完整知识体系。本章的目标只有一个:把你学过的所有东西串起来,独立完成一个可运行的多智能体应用。这不是考试,而是你从“学习者”变成“构建者”的毕业作品。
前置条件
- 已完成前十五章的学习,特别是第七章(自研框架)和第十三至十五章(综合案例)
- 本地环境已配置好 Python 3.10+、OpenAI API Key(或其他兼容 API)
- 熟悉 Git 基本操作(clone、commit、push)
- 准备好一个 GitHub 账号(用于托管你的项目)
第一步:选题与设计
毕业设计不是从零造轮子,而是在已有基础上做有意义的组合与扩展。选题原则:
- 小而完整:一个核心功能,但端到端跑通
- 用上至少 3 个你学过的技术:例如 ReAct 范式 + 记忆系统 + MCP 协议
- 能演示:命令行交互或简单 Web 界面都行
几个参考方向(你也可以自己想):
| 选题 | 核心技术点 | 难度 |
|---|---|---|
| 个人知识助手 | RAG + 记忆 + 工具调用 | ⭐⭐ |
| 代码审查智能体 | 多智能体协作 + 上下文工程 | ⭐⭐⭐ |
| 自动化报告生成器 | Plan-and-Solve + 评估 | ⭐⭐ |
| 模拟社交网络 | 赛博小镇变体 + 通信协议 | ⭐⭐⭐⭐ |
预期结果:一个 README 文档,写清楚你的选题、技术选型、预期功能。
第二步:搭建项目骨架
我们推荐用第七章的自研框架 HelloAgents 作为基础,因为它轻量、无黑盒。如果你更熟悉 LangGraph 或 AutoGen,也可以用它们——但必须能解释清楚每个组件的原理。
创建一个新目录并初始化:
mkdir my-agent-graduation
cd my-agent-graduation
git init
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install helloagents openai创建基本文件结构:
my-agent-graduation/
├── agents/ # 智能体定义
├── tools/ # 工具函数
├── memory/ # 记忆模块
├── config.py # 配置
├── main.py # 入口
└── README.md预期结果:项目目录结构清晰,pip install 无报错,python -c "import helloagents" 能正常执行。
第三步:实现核心逻辑
以“个人知识助手”为例,我们实现一个能记住用户偏好、检索本地文档、调用搜索工具的智能体。
3.1 配置 API
# config.py
import os
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "your-key-here")
OPENAI_BASE_URL = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
MODEL_NAME = "gpt-4o-mini"3.2 定义工具
# tools/search_tool.py
import requests
def web_search(query: str) -> str:
"""搜索网络并返回摘要"""
# 这里用 DuckDuckGo 免费 API 做演示
url = f"https://api.duckduckgo.com/?q={query}&format=json"
resp = requests.get(url, timeout=10)
data = resp.json()
return data.get("AbstractText", "未找到结果")3.3 实现记忆模块
# memory/simple_memory.py
from typing import List, Dict
class SimpleMemory:
def __init__(self):
self.history: List[Dict] = []
self.preferences: Dict = {}
def add_interaction(self, user_input: str, agent_response: str):
self.history.append({"user": user_input, "agent": agent_response})
def get_context(self) -> str:
return "\n".join(
[f"用户: {h['user']}\n助手: {h['agent']}" for h in self.history[-5:]]
)
def remember_preference(self, key: str, value: str):
self.preferences[key] = value3.4 组装智能体
# main.py
from helloagents import Agent, ReAct
from config import OPENAI_API_KEY, MODEL_NAME
from tools.search_tool import web_search
from memory.simple_memory import SimpleMemory
def main():
memory = SimpleMemory()
agent = Agent(
name="知识助手",
model=MODEL_NAME,
api_key=OPENAI_API_KEY,
tools=[web_search],
system_prompt="你是一个知识助手,帮助用户查找信息并记住他们的偏好。"
)
print("知识助手已启动(输入 'exit' 退出)")
while True:
user_input = input("\n你: ")
if user_input.lower() == "exit":
break
# 注入记忆上下文
context = memory.get_context()
response = agent.run(user_input, context=context)
print(f"助手: {response}")
memory.add_interaction(user_input, response)
# 简单偏好提取(演示用)
if "我喜欢" in user_input or "我的名字" in user_input:
memory.remember_preference("last_topic", user_input)
if __name__ == "__main__":
main()预期结果:运行 python main.py 后,能进行多轮对话,智能体能调用搜索工具并记住上下文。
第四步:添加评估与测试
毕业设计需要证明你的智能体“工作得不错”。用第十二章学到的评估方法,写一个简单的测试脚本:
# test_agent.py
from main import agent
test_cases = [
{"input": "今天天气怎么样?", "expected_tool_call": True},
{"input": "你好", "expected_tool_call": False},
]
for case in test_cases:
result = agent.run(case["input"])
# 检查是否调用了工具(简单判断)
tool_used = "搜索" in result or "http" in result
assert tool_used == case["expected_tool_call"], f"测试失败: {case['input']}"
print("所有测试通过!")预期结果:python test_agent.py 输出“所有测试通过!”。
第五步:完善文档与发布
一个没有 README 的项目等于没做。写清楚:
- 项目简介:一句话说明做什么
- 快速开始:安装、配置、运行命令
- 技术架构:用了哪些技术、为什么选它们
- 演示截图:终端输出或界面截图
- 未来改进:你想到但没时间做的功能
然后提交到 GitHub:
git add .
git commit -m "完成毕业设计:个人知识助手"
git remote add origin https://github.com/你的用户名/my-agent-graduation.git
git push -u origin main预期结果:一个公开的 GitHub 仓库,README 完整,其他人 clone 后能直接运行。
常见坑位与排查
1. API 调用失败
报错:openai.AuthenticationError 或 ConnectionError
排查:检查 OPENAI_API_KEY 是否有效,OPENAI_BASE_URL 是否正确(国内用户可能需要代理或使用国内 API 中转)。
2. 工具函数不生效
报错:智能体不调用你定义的 web_search
排查:确认工具函数的文档字符串(docstring)写清楚了——LLM 靠它理解工具用途。另外检查 tools 参数是否传入了函数对象而非字符串。
3. 记忆不生效
表现:第二轮对话智能体忘了之前说过什么
排查:检查 context 参数是否传入了 agent.run(),以及 SimpleMemory.get_context() 返回的内容格式是否被 LLM 理解。
4. 依赖冲突
报错:pip install 时版本冲突
排查:使用虚拟环境(venv),先 pip install helloagents 再装其他包。如果冲突严重,用 pip install helloagents==0.1.0 指定版本。
一个小例子串起来
假设你想做一个“旅行规划助手”,它需要:
- 记住用户的出发城市和偏好(记忆)
- 搜索目的地天气和景点(工具调用)
- 用 ReAct 范式分步规划行程(推理)
- 最后输出一份 Markdown 格式的旅行计划(输出格式化)
你只需要把上面代码中的 system_prompt 改成旅行规划相关,添加一个 get_weather 工具,再调整记忆模块存储用户偏好(比如“我喜欢海边”)。整个过程不超过 100 行代码——这就是你学完所有技术后的能力。
未来展望
毕业设计不是终点。你可以沿着这几个方向继续深入:
- 接入 MCP 协议:让智能体能调用更多外部服务(日历、邮件、数据库)
- 加入多智能体协作:让两个智能体分工,一个负责搜索,一个负责总结
- 用 Agentic-RL 微调模型:针对你的特定任务,用 GRPO 训练一个更高效的模型
- 部署成 Web 服务:用 FastAPI 包装,让其他人通过浏览器使用你的智能体
现在,打开终端,开始你的毕业设计吧。
9. 社区贡献精选与扩展阅读
社区贡献精选
读完前面十五章,你已经掌握了从基础概念到高级技术、从框架开发到综合案例的全套技能。但智能体领域发展极快,单靠一本书很难覆盖所有方向。本章精选社区贡献的优质内容,帮你拓展视野、查漏补缺,同时告诉你如何参与贡献。
前置条件
- 已完成前十五章的学习
- 拥有 GitHub 账号(用于提交 PR 或查看社区项目)
社区精选内容一览
社区成员贡献的内容分为两类:Extra-Chapter(独立于正文的扩展文章)和 Co-creation-projects(社区共创的毕业设计项目)。以下是精选推荐:
1. 面试准备
Agent 面试题总结与答案(Extra01)
如果你正在求职,这两份文档是必读的。它汇总了 Agent 岗位常见的面试问题,涵盖概念理解、框架原理、实战场景等,并附有参考答案。建议先自己思考,再对照答案查漏补缺。
2. 知识点补充
上下文工程内容补充(Extra02)
第九章讲上下文工程时,受篇幅限制只覆盖了核心内容。这篇补充文章深入讲解了更多实用技巧,比如动态上下文压缩、长对话中的记忆管理策略等。如果你在实际项目中遇到上下文溢出问题,这里可能有解决方案。
Dify 智能体创建保姆级教程(Extra03)
第五章介绍了低代码平台,但 Dify 的实操细节很多。这篇教程从注册到部署,每一步都有截图和说明,适合想快速上手 Dify 的读者。
Hello-Agents 课程常见问题(Extra04)
学习过程中遇到的典型问题汇总,包括环境配置、代码运行报错、概念理解等。遇到问题先翻这里,大概率能找到答案。
Agent Skill 相关文章(Extra05)
这篇聚焦 Agent 的技能系统设计,包括技能注册、调用、组合等工程实践。适合想深入理解 Agent 能力边界的读者。
3. 毕业设计项目
社区共创毕业设计(Co-creation-projects)
第十六章要求你构建一个完整的多智能体应用。社区成员已经提交了多个项目,涵盖不同场景和技术栈。你可以:
- 参考这些项目的架构设计
- 基于某个项目进行二次开发
- 提交你自己的毕业设计
如何贡献
看到这里,你可能也想分享自己的学习心得或实践成果。贡献流程很简单:
- Fork 仓库:访问 hello-agents,点击右上角 Fork
- 创建分支:在本地创建一个新分支,命名如
extra-my-topic - 添加内容:
- 独立文章放到
Extra-Chapter目录,文件名格式ExtraXX-你的标题.md - 毕业设计放到
Co-creation-projects目录,建一个以你项目命名的文件夹
- 独立文章放到
- 提交 PR:推送到你的 Fork 仓库,然后向主仓库发起 Pull Request
注意事项:
- 内容必须是原创或已获授权转载
- 代码示例要可运行,依赖和版本号写清楚
- 引用外部资料时注明来源
常见问题
Q:我的内容比较短,也能提交吗? A:可以。哪怕是一篇 500 字的技术笔记,只要对他人有帮助,都欢迎提交。
Q:提交后多久会被合并? A:维护者会定期审核 PR,通常 3-7 天内会有反馈。如果长时间未回复,可以在 PR 评论区 @ 维护者。
Q:我想修改正文内容,不是新增章节,怎么办? A:直接提交 PR 修改对应文件即可。如果是修正错误,请在 PR 描述中说明。
实用技巧
- 先看已有内容:提交前浏览 Extra-Chapter 目录,避免重复
- 保持风格一致:参考已有文章的 Markdown 格式和代码块写法
- 写清楚摘要:在 PR 描述中说明你的内容解决了什么问题、适合谁阅读
社区的力量在于分享。你的每一次贡献,都在帮助下一个学习者少走弯路。
10. 常见问题与面试指南
常见问题与面试指南
学完前面十六章,你已经掌握了从理论到实战的全链路知识。但有两个现实问题摆在面前:一是学习过程中踩过的坑怎么排查,二是如何把这些知识转化成面试中的竞争力。本章就专门解决这两件事。
前置条件
第一部分:学习过程中的高频问题
1. 环境与安装
Q:安装依赖时总是报版本冲突,怎么办?
先确认 Python 版本:python --version,本项目要求 Python 3.10+。推荐用虚拟环境隔离:
python -m venv hello-agents-env
source hello-agents-env/bin/activate # Linux/Mac
# 或 hello-agents-env\Scripts\activate # Windows
pip install -r requirements.txt如果还冲突,大概率是 openai 和 langchain 的版本不兼容。稳妥做法:先装 openai>=1.0.0,再装其他库。
Q:OpenAI API 调用报 401/429 错误?
- 401:检查
OPENAI_API_KEY是否设置正确,不要有多余空格或换行 - 429:触发了速率限制。加
time.sleep()或用tenacity做重试
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def call_llm(prompt):
# 你的调用代码
pass2. 智能体运行问题
Q:Agent 陷入死循环,一直调用同一个工具?
这是 ReAct 模式最常见的坑。原因通常是:工具返回的结果不够明确,LLM 认为需要再试一次。
解决办法:
- 给工具输出加明确的"完成"信号,比如返回
{"status": "done", "result": ...} - 设置最大迭代次数,超时强制终止
MAX_ITERATIONS = 10
for i in range(MAX_ITERATIONS):
# 你的 Agent 循环
if i == MAX_ITERATIONS - 1:
return "已达到最大尝试次数,请简化你的请求"Q:LLM 输出格式不对,解析 JSON 总是失败?
LLM 输出的 JSON 经常带多余文字或格式错误。不要直接 json.loads(),用正则提取或加一层校验:
import re
import json
def extract_json(text):
# 匹配第一个 { 到最后一个 } 之间的内容
match = re.search(r'\{.*\}', text, re.DOTALL)
if match:
try:
return json.loads(match.group())
except json.JSONDecodeError:
# 尝试修复常见问题:单引号替换为双引号
fixed = match.group().replace("'", '"')
return json.loads(fixed)
raise ValueError("未找到有效的 JSON")Q:Memory 越长,Agent 响应越慢,还容易跑偏?
这是上下文窗口的物理限制。不要把所有历史都塞进去,用滑动窗口或摘要策略:
class SlidingWindowMemory:
def __init__(self, max_messages=20):
self.max_messages = max_messages
self.messages = []
def add(self, message):
self.messages.append(message)
if len(self.messages) > self.max_messages:
# 保留系统提示和最近的对话
self.messages = [self.messages[0]] + self.messages[-(self.max_messages-1):]3. 框架与平台
Q:Dify 和 Coze 上搭建的 Agent,导出后怎么在本地跑?
低代码平台的导出格式通常是 JSON 或 YAML 描述文件,不是可执行代码。如果你需要本地部署,建议:
- 用 Dify 的 API 模式,远程调用
- 或者参考第七章,用导出的工作流逻辑,在自研框架里重写
Q:LangGraph 的 StateGraph 总是画不对?
常见错误:节点之间的边连错了。先画流程图再写代码,每个节点只做一件事。调试时加 print 看 state 变化:
def debug_node(state):
print(f"当前状态: {state.keys()}")
# 你的逻辑
return state第二部分:面试指南
面试前的准备
先梳理你的项目经验
面试官最常问的不是八股文,而是"你做过什么"。把你跑通的 Agent 项目整理成 STAR 格式:
- Situation:项目背景,解决什么问题
- Task:你的具体任务
- Action:你做了什么(技术选型、架构设计、踩坑解决)
- Result:效果如何(准确率、响应时间、用户反馈)
一个真实的例子(你可以参考这个结构):
我做了一个智能旅行助手,用 ReAct 模式 + 三个工具(天气查询、酒店预订、路线规划)。一开始 Agent 总是调用错工具,比如用户问天气,它却去查酒店。后来我在工具描述里加了明确的触发条件,比如"仅当用户提到'天气''温度''下雨'等词时才调用此工具",准确率从 62% 提升到 89%。
高频面试题
以下题目按频率排序,每个都附了回答要点。
1. 什么是 AI Agent?和传统程序有什么区别?
回答要点:
- Agent 是能感知环境、自主决策、执行动作的智能体
- 传统程序是确定性的:输入 → 固定逻辑 → 输出
- Agent 是不确定性的:输入 → LLM 推理 → 选择工具 → 观察结果 → 循环直到完成
- 核心区别:Agent 有"思考"和"适应"的能力
2. ReAct 模式是怎么工作的?
回答要点:
- ReAct = Reasoning + Acting
- 循环:思考(Thought) → 行动(Action) → 观察(Observation) → 再思考
- 每个 Action 调用一个工具,Observation 是工具返回的结果
- 直到 Thought 认为任务完成,输出 Final Answer
3. 怎么解决 Agent 的幻觉问题?
回答要点(分层次):
- 提示层:明确告诉 LLM "不知道就说不知道"
- 工具层:用外部工具(搜索、数据库)获取事实,不依赖模型内部知识
- 验证层:对输出做二次校验,比如用另一个 LLM 做事实核查
- 架构层:用 RAG 或 Memory 提供上下文约束
4. 多 Agent 协作怎么保证一致性?
回答要点:
- 通信协议:定义标准化的消息格式(JSON Schema)
- 共享记忆:所有 Agent 读写同一个 Memory 实例
- 仲裁机制:设一个 Coordinator Agent 做决策汇总
- 容错设计:超时重试、降级策略
5. 怎么评估一个 Agent 的好坏?
回答要点:
- 任务完成率:给定测试集,看 Agent 能否正确完成
- 工具调用准确率:是否调对了工具、参数是否正确
- 响应速度:从输入到输出的总耗时
- 鲁棒性:输入有噪声或歧义时,表现是否稳定
- 成本:API 调用次数和 token 消耗
6. 你遇到过最棘手的 Agent 问题是什么?怎么解决的?
这道题考的是你的实战能力。不要编,用你真实踩过的坑。如果你没遇到过特别难的,可以说:
最棘手的是 Agent 在复杂任务中频繁切换上下文,导致前面的推理结果丢失。我通过引入"工作记忆"——把中间结果持久化到 JSON 文件,每次推理前加载——解决了这个问题。虽然增加了 I/O 开销,但任务成功率从 55% 提升到 83%。
面试实战建议
技术面常见环节
手撕代码:可能会让你现场写一个简单的 ReAct 循环。提前练熟第七章的框架代码,能徒手写出核心逻辑。
系统设计:给一个场景,让你设计 Agent 架构。比如"设计一个客服 Agent"。注意:不要只堆技术名词,要说清楚为什么选这个方案、有什么 trade-off。
追问细节:面试官会深挖你简历上的项目。确保你能说清楚每个技术选型的理由,比如"为什么用 LangGraph 而不是 AutoGen"。
反问环节(加分项)
面试最后通常会让你提问。别问"加班多吗"这种,问点有深度的:
- "贵团队的 Agent 在生产环境里是怎么做错误恢复的?"
- "你们在 Agent 的 Memory 管理上有什么实践经验?"
- "如果遇到 LLM 输出格式不稳定,你们是怎么处理的?"
这些问题表明你真正做过、思考过。
实用技巧汇总
调试 Agent 的黄金三招
- 加日志:在每个关键节点打印输入输出,特别是 LLM 的原始响应
- 降级测试:先用最简单的 prompt 跑通流程,再逐步加复杂度
- 人工模拟:把 LLM 调用替换成固定返回值,先验证逻辑正确性
快速定位问题
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| Agent 不调用工具 | 工具描述不清晰 | 检查 prompt 中的工具定义 |
| 调用工具但参数错误 | 输出格式解析失败 | 检查 JSON 解析逻辑 |
| 响应速度越来越慢 | Memory 膨胀 | 检查上下文窗口大小 |
| 结果前后矛盾 | 缺乏全局记忆 | 检查 Memory 策略 |
最后一条建议
面试官看重的不是你知道多少概念,而是你有没有真正动手做过。哪怕只是一个简单的 ReAct Agent,只要你把踩过的坑、怎么解决的、效果如何讲清楚,就比背一百道八股文强。现在就去打开你的项目,把那些调试记录整理成面试素材吧。
常见问题
问题1:安装或运行项目时遇到 Python 版本或依赖冲突怎么办?
项目基于 Python 3.10+ 开发,建议使用虚拟环境(如 conda 或 venv)隔离依赖。首先执行 pip install -r requirements.txt,若遇到版本冲突,可尝试手动升级/降级关键库(如 openai、langchain)。如果使用自研框架 HelloAgents,请确保已安装 openai>=1.0.0。推荐使用 pip install --upgrade pip 后再安装依赖。
问题2:为什么我无法访问在线文档?国内用户如何加速?
项目提供了两个在线阅读入口:
- 国外访问:
https://datawhalechina.github.io/hello-agents/ - 国内加速:
https://hello-agents.datawhale.cc如果国外链接加载缓慢或被墙,请直接使用国内加速地址。若仍无法访问,可尝试克隆仓库后在本地用docsify或mkdocs启动本地服务器阅读。
问题3:教程中提到的“AI Native Agent”和“低代码平台 Agent”有什么区别?
- 低代码平台 Agent(如 Dify、Coze、n8n):本质是流程驱动的软件开发,LLM 作为数据处理的后端,适合快速搭建业务流。
- AI Native Agent:真正以 AI 驱动的智能体,核心是 LLM 自主决策、规划、调用工具,本教程重点讲解后者。如果你只想快速体验,可先看第五章;若想深入原理,建议从第四章开始。
问题4:运行第四章的 ReAct 或 Plan-and-Solve 示例时,报错“API key not found”或“模型不存在”?
请检查环境变量是否设置正确,例如:
export OPENAI_API_KEY="your-api-key"如果使用其他模型(如通义千问、DeepSeek),需在代码中修改 base_url 和 model 参数。部分示例默认使用 gpt-4,若你的 API 没有该模型权限,可改为 gpt-3.5-turbo 或兼容模型。
问题5:教程中提到的“HelloAgents”框架和 LangGraph、AutoGen 有什么区别?我需要全部学习吗?
- HelloAgents:本项目自研的轻量级框架,基于 OpenAI 原生 API,适合理解 Agent 核心原理(如 ReAct、Memory、工具调用)。
- LangGraph / AutoGen:工业级框架,功能更丰富,但学习曲线较陡。 建议顺序:先学第四章(经典范式)→ 第七章(自研框架)→ 第六章(主流框架对比),这样能由浅入深,避免被框架细节淹没。
问题6:我在学习第十一章 Agentic-RL(从 SFT 到 GRPO)时,训练代码跑不起来,显存不够怎么办?
Agentic-RL 训练需要较高显存(建议 24GB+)。如果显存不足,可以:
- 减小
batch_size和max_length参数。 - 使用
gradient_accumulation_steps模拟更大 batch。 - 尝试使用更小的基座模型(如
Qwen2-1.5B替代7B)。 - 如果本地无法运行,推荐使用 Colab(需 Pro)或 AutoDL 等云 GPU 服务。
问题7:教程中的“赛博小镇”案例需要哪些额外依赖?为什么我运行后没有看到交互界面?
“赛博小镇”是一个多智能体模拟项目,需要安装 pygame 或 streamlit(具体见第十五章开头)。如果运行后没有界面,请检查:
- 是否在终端中正确执行了启动命令(如
python main.py或streamlit run app.py)。 - 是否安装了所有依赖(
pip install pygame streamlit)。 - 如果使用 Jupyter Notebook,部分交互可能无法正常显示,建议在纯 Python 环境中运行。
问题8:我是初学者,应该从哪一章开始?需要先学完所有章节才能做毕业设计吗?
- 零基础:建议按顺序从第一章到第四章,理解智能体概念和经典范式后,再跳转到第七章(自研框架)或第十三章(综合案例)。
- 有基础:可以直接从第四章或第六章开始。
- 毕业设计:第十六章毕业设计是开放性的,你可以结合前几章学到的知识(如 Memory、MCP、多智能体协作)构建自己的应用,不需要学完所有章节。社区也提供了共创毕业设计项目供参考。