第七章 构建你的智能体框架(架构导读)
一句话总结
这一章是全书的"内功大考":把前六章学到的所有零件——LLM 调用、消息、工具、范式——组装成一个可以 pip install、可以 import、别人拿去就能用的智能体框架。完整的 15 文件手敲教程在 docs/2 第 18 篇《终极手敲-构建你自己的Agent框架》,本文负责让你先看懂架构再动手,敲起来事半功倍。
为什么要自己造框架(明明有 LangGraph 们)
三个理由,一个比一个实在:
- 祛魅:用过框架(第六章)你会觉得它们很神,造过框架你会发现核心不过千行代码。祛魅之后,再读 LangChain/AutoGen 源码就像逛自己家后院;
- 面试硬通货:"我从零写过一个支持四种范式、可 pip 安装的 Agent 框架"——这句话在面试里的分量,远超"我会用 LangChain";
- 工程能力跃迁:包设计、抽象基类、依赖注入、多提供商适配……这些通用软件工程能力,只有"造轮子"能逼你练出来。
框架的架构:五层积木
动手前,先把要造的东西的全貌装进脑子。我们的迷你框架(myagents)分五层,自下而上依次构建:
┌─────────────────────────────────────────┐
│ 第5层 Agent 范式层 │
│ SimpleAgent / ReActAgent / ReflectionAgent│
│ / PlanAndSolveAgent / FunctionCallAgent │
├─────────────────────────────────────────┤
│ 第4层 工具层 Tool / ToolRegistry / 内置工具 │
├─────────────────────────────────────────┤
│ 第3层 LLM 层 多提供商适配 / 流式 / 原生函数调用│
├─────────────────────────────────────────┤
│ 第2层 数据层 Message(消息) / Config(配置) │
├─────────────────────────────────────────┤
│ 第1层 包基建 pyproject.toml / __init__.py │
└─────────────────────────────────────────┘
每一层解决一个明确的问题:
- 包基建:让
pip install -e .生效,你的代码从"一堆脚本"升格为"一个可安装的库"。pyproject.toml是包的身份证(名字、版本、依赖、Python 版本要求); - 数据层:
Message(role + content 的标准结构)统一全框架的对话表示;Config集中管密钥、模型名、超时等配置——别让os.getenv散落在二十个文件里; - LLM 层:一个
LLM类适配多家提供商(DeepSeek/通义/Kimi/本地 Ollama……),支持流式输出和原生 tool_calls。框架最值钱的一层:上层代码永远不用关心底下接的是哪家模型; - 工具层:
Tool定义"一个工具长什么样"(名字、描述、参数、执行函数),ToolRegistry负责注册和查找——第四章ToolExecutor的正式版; - 范式层:一个抽象基类
Agent定义所有智能体的公共骨架(名字、LLM、run 方法),五个子类各实现一种范式——第四章徒手写的三个范式,在这里变成框架的"标准件",外加最简单的 SimpleAgent 和用原生函数调用的 FunctionCallAgent。
名词补课——抽象基类(ABC):Python 里"只定规矩、不干实事"的类。
Agent基类规定"所有智能体必须有 run 方法",子类不实现就报错。这保证了框架使用者面对任何范式都是同一套用法:agent.run(question)。
造完之后长什么样(先看终点)
框架完工后,使用者(包括三个月后的你)的体验是这样的:
from myagents import LLM, Config
from myagents.agents import ReActAgent
from myagents.tools import ToolRegistry, calculator
config = Config() # 自动读 .env
llm = LLM(config) # 自动识别提供商
registry = ToolRegistry()
registry.register(calculator)
agent = ReActAgent("小助手", llm, registry)
print(agent.run("123 乘以 456 等于多少?"))
五行组装一个能用工具的智能体——对比第一章你敲的 110 行单文件,这就是"框架化"的意义:把不变的部分沉淀成库,把会变的部分留给使用者。
动手路线(去 docs/2 第 18 篇,按顺序敲)
完整教程 15 个文件、约 600 行,分八节循序渐进,每节带 Checkpoint:
- 第 1~2 节:建包骨架(
pyproject.toml+ 空__init__.py)→pip install -e .。注意教程里的顺序:先建好所有__init__.py再安装,顺序错了会踩"命名空间包"的坑(教程里有说明); - 第 3 节:
message.py+config.py(数据层,用dataclasses); - 第 4 节:
llm.py(多提供商检测、流式、invoke_with_tools原生函数调用); - 第 5 节:
tool.py+registry.py+builtin_tools.py(工具层); - 第 6~7 节:
base.py抽象基类 + 五个范式各一个文件; - 第 8 节:总装测试——在框架外面新建项目,
import myagents跑通全部五种范式。
总验收标准:在任意新目录里 from myagents.agents import ReActAgent 能用,五种范式全部跑通,你就拥有了一个真正属于自己的框架。
面试视角:造框架时最值得记住的三个设计决策
- "为什么 LLM 层要做多提供商适配?"——供应商锁定是真实风险(涨价、限流、下线)。适配层让"换模型"变成改一行配置。追问实现:按 base_url 特征自动检测提供商,各家的小差异(参数名、流式格式)在适配层内消化。
- "文本协议解析工具调用 vs 原生 Function Calling,怎么选?"——文本协议(
Action: xxx[...])通用、任何模型都能用,但解析易碎;原生 tool_calls 可靠、结构化,但依赖模型支持。框架两种都提供(ReActAgent 用前者,FunctionCallAgent 用后者),让使用者按模型能力选。 - "抽象基类的 run 方法为什么只收一个字符串?"——接口最小化原则:签名越简单,子类越自由,使用者心智负担越小。复杂需求(历史、流式回调)通过构造函数和可选参数扩展,不污染核心接口。
划重点
- 造框架的三重收益:祛魅、面试硬通货、工程能力跃迁。
- 架构五层自下而上:包基建 → 数据 → LLM → 工具 → 范式,每层只解决一个问题。
- 框架化的本质:不变的沉淀成库,会变的留给使用者。
- 抽象基类统一接口、适配层隔离供应商、注册表管理工具——三个模式在所有主流框架里都能找到影子。
- 现在就去 docs/2 第 18 篇 动手,敲完回来看第六章的框架,你会有"不过如此"的踏实感。
下一章预告:框架有了,但你的智能体还是"金鱼记忆"——关掉进程就忘光。第八章给它装上记忆系统和 RAG 检索,让它记住你、并能查阅私有知识库。