news 2026/9/19 7:23:52

smolagents Agentic RAG 实战:用 CodeAgent 打造可推理、可迭代检索的知识库问答系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
smolagents Agentic RAG 实战:用 CodeAgent 打造可推理、可迭代检索的知识库问答系统

smolagents Agentic RAG 实战:用 CodeAgent 打造可推理、可迭代检索的知识库问答系统

【免费下载链接】smolagents🤗 smolagents: a barebones library for agents that think in code.项目地址: https://gitcode.com/gh_mirrors/smo/smolagents

导读

本文基于 smolagents 官方示例 docs/source/en/examples/rag.md 与仓库内完整可运行的 examples/rag.py,讲解如何把传统 RAG(检索增强生成)升级为Agentic RAG:即以 smolagents 的CodeAgent为核心,通过自定义Tool把 BM25 检索器包装成语义检索工具,让大模型自主优化查询、多轮检索、交叉验证并最终作答。读完本文,你将掌握在 smolagents 中定义检索工具、配置InferenceClientModel模型、驱动CodeAgent完成知识库问答的完整套路,并理解其底层工具校验与执行机制。


一、RAG 是什么:把答案建立在检索到的事实之上

Retrieval-Augmented Generation(检索增强生成,RAG)的核心思想可以概括为一句话:"用 LLM 回答用户问题,但回答的依据是从知识库中检索到的信息"。它把大语言模型的生成能力与外部知识检索能力结合起来,从而产出更准确、更有事实依据、更贴合上下文的回答。

1.1 为什么用 RAG

相比直接使用 vanilla 大模型或微调(fine-tuned)模型,RAG 有五个显著优势:

  1. 事实锚定(Factual Grounding):回答锚定在检索到的真实文档上,显著降低幻觉(hallucination)概率;
  2. 领域专精(Domain Specialization):无需重新训练模型,即可让通用模型回答特定领域的专业问题;
  3. 知识时效(Knowledge Recency):可以访问超出模型训练截止时间(training cutoff)的最新信息;
  4. 可追溯性(Transparency):生成内容可以引用来源文档,方便用户核对;
  5. 可控性(Control):可以精细控制模型能访问哪些信息、不能访问哪些信息。

1.2 传统 RAG 的局限

传统 RAG 虽然好用,但作为"一次检索 + 一次生成"的固定流水线,它面临四个典型挑战:

  • 单次检索(Single Retrieval Step):如果第一轮检索结果质量差,最终生成的答案也会跟着遭殃,没有补救机会;
  • 查询与文档不匹配(Query-Document Mismatch):用户的查询往往是疑问句,而包含答案的文档通常是陈述句,词面差异会让字面匹配失效;
  • 推理能力有限(Limited Reasoning):简单的 RAG 流水线无法进行多步推理或查询修正;
  • 上下文窗口约束(Context Window Constraints):检索到的文档必须能塞进模型的上下文窗口,限制了可用的信息量。

二、Agentic RAG:从固定流水线到可推理的检索 Agent

上述局限的根因在于:传统 RAG 是一条"单向、不可变"的流水线。而Agentic RAG的思路是:给 Agent 装备检索能力,把 RAG 变成"交互式、由推理驱动"的过程。

2.1 Agentic RAG 的关键能力

一个带检索工具的 Agent 可以做到:

  1. 生成优化查询(Formulate optimized queries):把用户的原始问题改写为更适合检索的查询形式;
  2. 多次检索(Perform multiple retrievals):按需迭代式地多次检索,逐步逼近答案;
  3. 对检索内容进行推理(Reason over retrieved content):对多个来源的信息进行分析、综合与结论提炼;
  4. 自我批判与修正(Self-critique and refine):评估检索结果质量,调整检索策略后再试。

2.2 天然实现的高级 RAG 技术

这种"思考-行动-观察"的循环天然就实现了两类高级 RAG 技术:

  • HyDE(Hypothetical Document Embedding,假设性文档嵌入):不再直接用用户查询去检索,而是让 Agent 先生成一个"检索友好"的假设性文档或查询再检索(对应论文:2212.10496,HyDE 由 Gao 等人提出);
  • Self-Query Refinement(自查询修正):Agent 先分析第一轮检索结果,发现信息不足或方向不对时,用修正后的查询发起第二轮检索。

在 smolagents 中,这两类能力不需要额外框架支持——它们就是CodeAgent在每一轮"写代码调用工具"中自然涌现的行为。

三、实战:构建一个 Transformers 文档问答 Agent

下面我们按步骤构建一个完整的 Agentic RAG 系统。目标:创建一个能回答Hugging Face Transformers 库相关问题的 Agent,其知识来源是 Transformers 官方文档。你可以跟着下面的代码片段逐步实现,也可以直接查看仓库中完整可运行的示例 examples/rag.py。

Step 1:安装依赖

首先安装所需依赖包:

pip install smolagents pandas langchain langchain-community sentence-transformers datasets python-dotenv rank_bm25 --upgrade

如果你打算使用 Hugging Face 的 Inference API(通过InferenceClientModel调用云端推理),需要配置 API Token。推荐用python-dotenv从环境变量加载:

# 加载环境变量(包含 HF_TOKEN) from dotenv import load_dotenv load_dotenv()

InferenceClientModel在初始化时会依次尝试显式传入的token、环境变量HF_TOKEN,最后回退到huggingface-cli login保存的本地凭据(详见 src/smolagents/models.py)。

Step 2:准备知识库

我们使用一个包含 Hugging Face 文档的数据集,过滤出 Transformers 部分,切分成适合检索的文档块:

import datasets from langchain.docstore.document import Document from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.retrievers import BM25Retriever # 加载 Hugging Face 文档数据集 knowledge_base = datasets.load_dataset("m-ric/huggingface_doc", split="train") # 只保留 Transformers 相关文档 knowledge_base = knowledge_base.filter(lambda row: row["source"].startswith("huggingface/transformers")) # 把数据集条目转换为带元数据的 Document 对象 source_docs = [ Document(page_content=doc["text"], metadata={"source": doc["source"].split("/")[1]}) for doc in knowledge_base ] # 将文档切分为更小的块,提升检索精度 text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, # 每个块的最大字符数 chunk_overlap=50, # 相邻块之间的重叠字符数,避免切断语义 add_start_index=True, strip_whitespace=True, separators=["\n\n", "\n", ".", " ", ""], # 切分优先级顺序 ) docs_processed = text_splitter.split_documents(source_docs) print(f"Knowledge base prepared with {len(docs_processed)} document chunks")

这里的关键点在于切分参数chunk_size=500保证块足够小以便精确检索,chunk_overlap=50让上下文在块边界处保持连贯,separators指定了从段落级到字符级的切分优先级。

Step 3:创建检索工具(Retriever Tool)

接下来定义一个自定义Tool,让 Agent 能用它从知识库中检索信息。这是整个 Agentic RAG 的关键桥梁:

from smolagents import Tool class RetrieverTool(Tool): name = "retriever" description = "Uses semantic search to retrieve the parts of transformers documentation that could be most relevant to answer your query." inputs = { "query": { "type": "string", "description": "The query to perform. This should be semantically close to your target documents. Use the affirmative form rather than a question.", } } output_type = "string" def __init__(self, docs, **kwargs): super().__init__(**kwargs) # 用处理后的文档初始化 BM25 检索器,返回 Top-10 相关文档 self.retriever = BM25Retriever.from_documents( docs, k=10 ) def forward(self, query: str) -> str: """执行检索并格式化返回结果。""" assert isinstance(query, str), "Your search query must be a string" # 执行检索 docs = self.retriever.invoke(query) # 格式化检索结果,便于 Agent 阅读 return "\nRetrieved documents:\n" + "".join( [ f"\n\n===== Document {str(i)} =====\n" + doc.page_content for i, doc in enumerate(docs) ] ) # 用处理好的文档初始化检索工具 retriever_tool = RetrieverTool(docs_processed)

[!TIP] 这里选用BM25(词法检索方法)是为了简单和快速。生产环境可以换用基于 embedding 的语义检索以获得更好的检索质量,可参考 MTEB 排行榜挑选高质量的 embedding 模型。

源码视角:Tool基类到底做了什么

要理解RetrieverTool,需要看看它的基类实现(src/smolagents/tools.py):

  • 必填类属性:子类必须声明namestr)、descriptionstr)、inputsdict,每个输入项必须含typedescription两个键)、output_typestr)。Tool.__init_subclass__会触发validate_after_init,即在__init__执行完毕后自动调用validate_arguments()做一次全量校验;
  • 校验规则validate_arguments):name必须是合法 Python 标识符且非保留字;inputs中的type必须是受支持类型,合法取值来自AUTHORIZED_TYPES = ["string", "boolean", "integer", "number", "image", "audio", "array", "object", "any", "null"]forward方法的参数名集合必须与inputs的键完全一致,否则直接抛异常;
  • 调用入口__call__会先检查is_initialized,若未初始化则调用可覆写的setup()(适合放置加载模型等昂贵操作);随后执行forward(*args, **kwargs)并返回结果;
  • 提示词注入to_code_prompt()会把工具的签名(如retriever(query: string) -> string)、描述与参数说明拼装成代码形式的函数文档,注入到 CodeAgent 的系统提示词中,让模型知道"可以调用retriever(query)这个函数"。

这也是为什么示例中inputs里只有query一个键,forward就只接收query一个参数——两者必须严格对应,代码里对工具的使用方式与给模型的提示词才一致。

Step 4:创建检索 Agent

现在创建能调用retriever_toolCodeAgent

from smolagents import InferenceClientModel, CodeAgent # 用我们的检索工具初始化 Agent agent = CodeAgent( tools=[retriever_tool], # 提供给 Agent 的工具列表 model=InferenceClientModel(), # 默认模型 "Qwen/Qwen3-Next-80B-A3B-Thinking" max_steps=4, # 限制推理步数 verbosity_level=2, # 输出详细的 Agent 推理过程 ) # 想指定特定模型时,可以这样写: # model=InferenceClientModel(model_id="meta-llama/Llama-3.3-70B-Instruct")

[!TIP] Inference Providers 通过 serverless 推理合作伙伴提供数百个模型。不传provider时默认走 "auto",即按用户在账户设置里的偏好顺序选择可用供应商;支持 Cerebras、Cohere、Fal、Fireworks、HF-Inference、Hyperbolic、Nebius、Novita、Replicate、SambaNova、Together 等多家供应商(详见 src/smolagents/models.py)。

源码视角:CodeAgentInferenceClientModel的关键参数

CodeAgent(src/smolagents/agents.py)是"以代码形式表达工具调用"的 Agent:LLM 每次行动会生成一段 Python 代码(例如调用retriever(query=...)),解析后交给 Python 执行器运行。常用参数:

参数默认值说明
tools必填Agent 可用的Tool列表
model必填负责生成行动的Model实例
max_steps20最大推理步数,MultiStepAgent._run_stream中循环条件为self.step_number <= max_steps,超限会进入_handle_max_steps_reached分支(src/smolagents/agents.py)
verbosity_levelLogLevel.INFO日志详细程度,示例中2对应更详细的推理输出
stream_outputsFalse是否流式输出;置True时要求模型实现generate_stream方法,否则抛ValueError(src/smolagents/agents.py)
executor_type"local"代码执行器类型,可选localblaxele2bmodaldocker
planning_intervalNone每隔 N 步插入一次规划步骤,适合复杂长任务
additional_authorized_imports[]额外允许 Agent 导入的包

仓库示例 examples/rag.py 中还额外开启了stream_outputs=True,可以边推理边流式输出。

InferenceClientModel(src/smolagents/models.py)是访问 Hugging Face Inference Providers 的模型封装:

  • model_id默认"Qwen/Qwen3-Next-80B-A3B-Thinking",也支持传入已部署的 Inference Endpoint URL;
  • provider用于指定供应商(如"hyperbolic"),默认"auto"按用户偏好自动选择;传了base_urlprovider不生效;
  • token:需要被授权"调用 serverless Inference Providers";若模型是 gated(如 Llama-3 系列),token 还需有对应仓库的读取权限。不传时依次回退到HF_TOKEN环境变量和 HF CLI 登录凭据;
  • timeout默认 120 秒;
  • api_keytoken的别名(与 OpenAI 客户端风格对齐),二者不能同时传入;
  • 若要本地私有部署,也可换用仓库中的TransformersModel(src/smolagents/models.py)直接加载本地模型权重。

Step 5:运行 Agent 回答问题

最后,向 Agent 提出一个需要检索文档才能回答的问题:

# 提出一个需要检索信息才能回答的问题 question = "For a transformers model training, which is slower, the forward or the backward pass?" # 运行 Agent 获取答案 agent_output = agent.run(question) # 打印最终答案 print("\nFinal answer:") print(agent_output)

agent.run()背后的执行流程是:生成系统提示词(包含retriever工具的代码签名)→ 进入"思考-写代码-执行-观察"循环 → 每步把结果写回 memory → 直到模型输出final_answer或达到max_steps上限(src/smolagents/agents.py)。针对"forward 与 backward 谁更慢"这类问题,Agent 会先改写为陈述式检索查询(如"backward pass is slower than forward pass"),调用retriever拿到相关文档片段,再综合多个文档块给出有依据的答案——这正是 HyDE 与多轮检索在实践中的体现。

四、Agentic RAG 的典型应用场景

掌握上述构建方式后,Agentic RAG 可以迁移到多种实际业务中:

  1. 技术文档助手:帮用户快速定位复杂技术文档中的关键信息;
  2. 科研论文分析:从多篇论文中抽取并综合结论;
  3. 法律文书审查:在海量判例与条款中查找相关先例;
  4. 智能客服:基于产品文档与知识库回答用户问题;
  5. 教育辅导:基于教材与学习资料提供定制化讲解。

替换知识库来源(如换成自己的内部 Wiki、PDF 语料或数据库)、换用语义检索器(如基于 embedding 的向量检索)即可适配上述场景,而 Agent 的"检索-推理"骨架无需改动。

五、结论

Agentic RAG 相对传统 RAG 流水线是一次显著升级:把 LLM Agent 的推理能力与检索系统的事实锚定能力结合起来,可以构建更强大、更灵活、更准确的信息系统。本文演示的方案:

  • RetrieverTool(继承Tool基类)把 BM25 检索器包装成 Agent 可调用的工具;
  • CodeAgent+InferenceClientModel驱动"思考-检索-推理"循环;
  • 突破了单次检索的局限,让 Agent 与知识库之间形成更自然的交互;
  • 通过自我批判与查询修正,为持续改进提供了框架。

当你构建自己的 Agentic RAG 系统时,建议在检索方法(BM25 vs 语义检索)、Agent 架构(CodeAgentvsToolCallingAgent,后者见 src/smolagents/agents.py)以及知识源三个维度上多做实验,找到最适合自己业务场景的组合。

【免费下载链接】smolagents🤗 smolagents: a barebones library for agents that think in code.项目地址: https://gitcode.com/gh_mirrors/smo/smolagents

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 7:23:10

数据结构从理论到代码:手写链表、二叉树、哈希表与调试实战

简介&#xff1a;这份PDF是山东大学《数据结构》课程内容整理&#xff0c;面向计算机专业本&#xff08;专&#xff09;科生、考研与期末复习者&#xff0c;帮助快速建立从数据组织到算法分析的知识框架。资源共1个文件&#xff0c;为PDF格式&#xff0c;压缩包大小仅324KB&…

作者头像 李华
网站建设 2026/9/19 7:19:55

聚氨酯一体板vs铝单板:建筑外围护选型全维度对比与决策指南

1. 建筑外围护选型&#xff1a;聚氨酯一体板vs铝单板1.1 核心需求解析建筑外围护选型这件事&#xff0c;说大不大&#xff0c;说小也绝对不小。往小了说&#xff0c;它决定了建筑外立面好不好看、耐不耐用&#xff1b;往大了说&#xff0c;它直接关系到项目的综合造价、施工周期…

作者头像 李华
网站建设 2026/9/19 7:17:54

多机器人任务分配核心算法:市场机制与群体智能实战解析

简介&#xff1a;这份PPT围绕多机器人系统的任务分配技术展开&#xff0c;适合智能机器人、人工智能方向的初学者及研究参考。内容从多机器人系统概述出发&#xff0c;梳理集中式、分布式与混合式三种结构&#xff0c;并系统解析任务分配的分类维度&#xff0c;如静态/动态、同…

作者头像 李华
网站建设 2026/9/19 7:15:24

N_m3u8DL-RE 完整上手指南:M3U8/MPD 下载、解密与直播录制实战

N_m3u8DL-RE 完整上手指南&#xff1a;M3U8/MPD 下载、解密与直播录制实战 【免费下载链接】N_m3u8DL-RE Cross-Platform, modern and powerful stream downloader for MPD/M3U8/ISM. English/简体中文/繁體中文. 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8…

作者头像 李华
网站建设 2026/9/19 7:14:38

新国标下移动电源SoC与锂电保护链路设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华