数据截至 (上游 commit e3a5b8994b30)
smolagents — 架构与原理
30 秒导读: smolagents 是 Hugging Face 的一个极简 agent 库。它最大的赌注是——让大模型不要用 JSON 描述「我要调用哪个工具」,而是直接写一段 Python 代码来行动。这段代码跑在一个它自己手写的、逐行解释 AST 的「迷你 Python」里,只放行白名单里的模块和函数。核心 agent 循环压到约一千行。
本项目较大(源码约 1.3 万行,多个子系统),文档拆成多章。本页是 Layer 0(这是什么)+ Layer 1(顶层全景)+ 阅读地图;各机制的细节在分章里。
1. 这是什么(零基础也能懂)
一句话定义: smolagents 是一个「让 LLM 反复地思考→行动→看结果」的 agent 框架,而它的行动方式是写代码。
它想解决的问题。 你想让 AI 自动完成一个多步骤任务(「查一下猎豹全速跑过这座桥要几秒」),这需要:上网搜、把数字抠出来、做算术、给出答案。单靠一次模型调用做不到——模型不会上网、不会精确算术。于是需要一个循环:模型说一步,系统执行一步,把结果喂回 去,再问下一步。这类系统叫 agent(智能体)。
它和别的 agent 框架不同在哪。 多数框架让模型输出结构化的「工具调用」(一段 JSON:工具名 + 参数)。smolagents 的主打是另一条路——CodeAgent:模型直接写 Python。想连续调三个工具、把结果存进变量、写个循环?一段代码就搞定,不用来回三轮对话。
它能做什么:
- 两种 agent:
CodeAgent(写代码行动)和ToolCallingAgent(传统 JSON 工具调用)。 - 模型无关:HF Inference、LiteLLM(100+ 家)、OpenAI、Bedrock、本地 Transformers/vLLM/MLX 都接。
- 工具无关:自带 web 搜索/访问网页;能从 MCP server、LangChain、HF Hub Space 拉工具。
- 代码执行有多档隔离:本地受限解释器,或 E2B / Docker / Modal / Blaxel 远程沙箱。
- agent 可嵌套(一个 agent 当另一个的「工具」,即 managed agents),可存取 Hub。
用起来什么样:
from smolagents import CodeAgent, WebSearchTool, InferenceClientModel
model = InferenceClientModel()
agent = CodeAgent(tools=[WebSearchTool()], model=model)
agent.run("猎豹全速跑过巴黎艺术桥要多少秒?")
agent.run(...) 内部会转起一个循环:模型写一段代码 → 解释器执行 → 把打印输出和返回值当「观测」喂回 → 直到模型调用 final_answer(...) 收尾。
一 句话直觉: 把 agent 想成一个「只会用 Python 交互的实习生」——你给它一套函数(工具),它写代码调用它们、串联它们;它每写一段你就帮它跑一段,把结果念给它听,直到它说「这就是最终答案」。
2. 顶层全景(它大概怎么转)
2.1 部件一句话职责
| 部件 | 干什么 | 主要文件 |
|---|---|---|
MultiStepAgent | ReAct 循环的骨架:排步骤、插规划、管记忆、判终止 | src/smolagents/agents.py:268 |
CodeAgent | 把「行动」实现成写代码 + 交给执行器跑 | src/smolagents/agents.py:1505 |
ToolCallingAgent | 把「行动」实现成传统 JSON 工具调用 | src/smolagents/agents.py:1215 |
LocalPythonExecutor | 手写的受限 Python 解释器(招牌) | src/smolagents/local_python_executor.py:1688 |
RemotePythonExecutor 家族 | 把代码送到 E2B/Docker/Modal/Blaxel 沙箱跑 | src/smolagents/remote_executors.py:53 |
Tool | 工具抽象:一个可调用对象 + 元数据(名/描述/入参/出参) | src/smolagents/tools.py:106 |
Model | 统一各家 LLM 的接口,产出 ChatMessage | src/smolagents/models.py:452 |
AgentMemory | 存每一步(任务/规划/行动),又能回灌成消息列表 | src/smolagents/memory.py:214 |
2.2 主线走一遍(高层,不进代码)
下图是一次 CodeAgent.run(task) 的主循环。怎么读:从上到下是一步(step)内的顺序;右侧虚线是「没结束就回到顶部开下一步」。
agent.run(task)
│ 把 task 塞进记忆(TaskStep),把工具/变量灌进执行器
▼
┌─────────────────────────────────────────────┐
│ 一个 step(ReAct 的一轮): │ ◄─┐
│ │ │
│ ① 记忆 → 消息列表 write_memory_to_messages │ │
│ ② 模型生成一段带 <code>…</code> 的回答 │ │
│ ③ 从回答里抠出代码 parse_code_blobs │ │
│ ④ 执行器跑这段代码 python_executor(code) │ │
│ ⑤ 把「打印输出 + 返回值」写回记忆当观测 │ │
│ │ │
│ 代码里调了 final_answer(x) 吗? │ │
│ 否 ──────────────────────────────────────┼───┘ 下一步
│ 是 → 返回 x,循环结束 │
└─────────────────────────────────────────────┘
三个要点先记住,后面各章展开:
- 「行动」= 一段代码,不是一次函数调用。这让「连续多个工具 + 变量 + 控 制流」在一步内完成(见
02-code-agent.md)。 - 终止靠
final_answer。它不是普通返回值,而是靠抛一个特殊异常打断执行(见02§5)。 - 记忆是「可逆」的:每步既存成结构化对象(给回放/序列化),又能
to_messages()变回对话喂给模型(见05-models-and-memory.md)。
3. 阅读地图(建议顺序)
01-agent-loop.md— 先懂通用循环:run/_run_stream/ 一步的生命周期、规划步、记忆回灌。这是所有 agent 的共同骨架。02-code-agent.md— 再看 CodeAgent 怎么把「行动」变成写代码:停止序列、代码抠取、final_answer终止。03-local-python-executor.md— 招牌深潜:一个逐节点解释 AST 的迷你 Python,如何用白名单 + 返回值检查 + 计步器/超时把代码关起来。想学到精华就重点读这章。04-tools.md— 工具抽象:同一个工具的两副面孔(代码签名 vs JSON schema)、校验、@tool装饰器、MCP/Hub 来源。05-models-and-memory.md— Model 如何抹平各家 API;Memory 每步存什么、又怎么变回消息。06-remote-execution-and-boundaries.md— 远程沙箱、安全边界的诚实交代、和兄弟项目的横向对比、总代码地图。
给 AI agent 的提示: 按
keyTopics匹配任务再下钻单章即可,不必读全部。要改代码执行/安全相关的,直接跳03与06;要接新模型或改上下文拼装,跳05;要加工具,跳04。