首页
/ CrewAI 动态知识库工具 RagTool 完全指南:源码级解析与多数据源实战

CrewAI 动态知识库工具 RagTool 完全指南:源码级解析与多数据源实战

2026-09-07 19:58:46作者:裘旻烁

导读

RagTool 是 CrewAI 生态中面向信息检索(RAG)的通用工具:它把知识库封装成一个可供 Agent 直接调用、以自然语言提问的工具,帮助 Crew 中的 Agent 基于自有文档与数据源回答事实性问题。本文将围绕其数据加载(add)、检索(query/_run)、Embedding 与向量库配置等核心能力展开,结合仓库内实现源码与测试逐层剖析,读完你就能在自己的 Crew 中把 RagTool 接入文件、网页、YouTube、数据库等多样化知识源。

本文以 RagTool 官方 README 为主体骨架,相关结论均在 crewai-toolscrewai 原生 RAG 子系统 的源码、测试中得到验证。

RagTool 是什么:让 Agent 拥有"可查询的知识库"

RagTool 被设计用于"通过 RAG(检索增强生成)回答基于知识库的问题",官方定位是 Dynamic Knowledge Base Tool。它的使用价值在于:LLM 自身的参数化知识是有截止时间且不可控的,而业务场景往往需要 Agent 基于企业私有资料回答——RagTool 允许你先把知识内容灌入向量库,再让 Agent 像查资料一样检索最相关的片段。

  • 适用场景:让 Agent 依据公司制度问答、基于产品文档提供支持、对内部研究报告做事实核查等"需要引用一手资料"的任务。
  • 与 Crew 的集成方式:RagTool 继承自 CrewAI 的 BaseTool(见 rag_tool.py),因此可以像普通工具一样塞进 Agenttools 列表中,由 Agent 自主决定何时调用。
from crewai import Agent
from crewai_tools import RagTool

knowledge_base = RagTool(collection_name="company_policies")

support_agent = Agent(
    role="Customer Support Specialist",
    goal="Answer user questions based on the company knowledge base",
    backstory="You answer precisely, always grounding answers in the KB.",
    tools=[knowledge_base],   # RagTool 作为 Agent 可用工具
)

需要注意的是,README 中对引擎的说明沿用了早期 "EmbedChain" 的说法;在当前仓库版本中,RagTool 的默认实现已经切换为 CrewAI 原生 RAG 子系统:模型校验后会自动构建 CrewAIRagAdapterrag_tool.py),再经由 ChromaDB/Qdrant 客户端完成写入与检索。

快速上手:导入与两种"喂数据"写法

RagTool 的导入路径在 README 示例中写作 crewai_tools.tools.rag_tool,这是较早版本的模块路径。当前源码将实现放在 crewai_tools/tools/rag/rag_tool.py,并已从包顶层多处再导出(见 crewai-tools 包 __init__.pytools 子包 __init__.py),以下几种写法均可用:

from crewai_tools import RagTool                       # 顶层导出,推荐
from crewai_tools.tools import RagTool
from crewai_tools.tools.rag.rag_tool import RagTool    # 模块真实位置

历史 API 与当前 API 的差异

README 中给出了如下"链式工厂"示例:

rag_tool = RagTool().from_file('path/to/your/file.txt')
rag_tool = RagTool().from_directory('path/to/your/directory')
rag_tool = RagTool().from_web_page('https://example.com')

需要澄清的是:当前源码中并不存在 from_file / from_directory / from_web_page 这三个方法(对 crewai-tools 全量搜索无任何定义),它们是 README 继承自旧版封装的历史用法。现在所有数据加载统一收敛到 add() 方法,该方法支持按扩展名自动识别数据类型,语义上与旧 API 一一对应:

rag_tool = RagTool()
rag_tool.add("path/to/your/file.txt")      # 等价于旧 from_file:自动识别为 text_file
rag_tool.add("path/to/your/directory")     # 等价于旧 from_directory:递归加载文本类文件
rag_tool.add("https://example.com")        # 等价于旧 from_web_page:识别为 website

检索:直接调用

知识注入后即可提问,底层 _runBaseTool 的调用入口)会把结果拼成带 Relevant Content: 前缀的上下文返回(rag_tool.py):

answer_context = rag_tool._run("What are our refund rules?")
# 'Relevant Content:\n退款政策:自购买之日起 30 天内可无理由退款……'

该返回内容通常被 Agent 视为检索到的片段,再交给 LLM 组织成最终答复。

数据源矩阵:一类知识源对应一套 Loader + Chunker

README 用图标罗列了 RagTool 可接入的数据源:PDF、CSV、JSON、TXT、目录、网页、YouTube 频道/视频、Docs 站、MDX、DOCX、XML、Gmail、GitHub、Postgres、MySQL、Slack、Discord、Discourse、Substack、Beehiiv、Dropbox、图片与自定义源。

其中 GitHub、Postgres、MySQL、Gmail、Slack、Discord、Discourse、Substack、Beehiiv、Dropbox 等属于社区/旧版(EmbedChain 时代)loader 的接入目标;当前仓库原生 RAG 层实际内置的 Loader 与 DataType 一一对应,可从 data_types.pyloaders 目录 核实:

数据类型(DataType 底层 Loader 适合喂入的内容
pdf_file PDFLoader(pdf_loader.py PDF 报告、合同
text_file / text TextFileLoader / TextLoader .txt、纯文本片段
csv CSVLoader(csv_loader.py 表格数据
json JSONLoader(json_loader.py JSON 结构数据
xml XMLLoader(xml_loader.py XML 配置/文档
docx DOCXLoader(docx_loader.py Word 文档
mdx MDXLoader(mdx_loader.py MDX/Markdown
directory DirectoryLoader(directory_loader.py 整目录批量入库
website WebPageLoader(webpage_loader.py 单网页
docs_site DocsSiteLoader(docs_site_loader.py 文档站点
youtube_video / youtube_channel YoutubeVideoLoader / YoutubeChannelLoader 视频/字幕内容
github GithubLoader(github_loader.py GitHub 仓库代码/文档
mysql MySQLLoader(mysql_loader.py 表数据
postgres PostgresLoader(postgres_loader.py 表数据

每种类型都会关联专属 Chunker 做分块(.mdx 用 MDX 分块器、csv/json/xml 用结构化分块器,其余大多用文本分块器),保证后续检索的粒度。分块结果会写入携带 data_typesourcechunk_indextotal_chunks 等元数据的文档记录,并基于内容生成确定性的 doc_idcrewai_rag_adapter.py)。

add() 的参数契约

add() 的签名定义在 types.pyAddDocumentParams 中,支持位置参数与关键字参数混合,常用参数如下:

参数 类型 说明
data_type DataType 枚举或字符串(见下方列表) 显式指定数据源类型;不传时按扩展名/URL 自动识别,"file" 恒代表自动识别
path / file_path str | Path 指向单个文件路径(二者互为别名)
directory_path str | Path 目录路径
url / website str 网页 URL
github_url str GitHub 仓库地址
youtube_url str YouTube 视频地址
metadata dict 附加元数据,会合并进每个 chunk
位置参数 str | Path | dictContentItem 路径、URL、纯文本或 {"source": ...} 形式的文档描述

合法的 data_type 字符串与 DataTypeStr 一致:filepdf_filetext_filecsvjsonxmldocxmdxmysqlpostgresgithubdirectorywebsitedocs_siteyoutube_videoyoutube_channeltext

from crewai_tools import RagTool
from crewai_tools.rag.data_types import DataType

tool = RagTool()

# 1) 位置参数 + 自动识别:按扩展名自动路由到对应 Loader
tool.add("reports/annual.pdf")                       # -> pdf_file
tool.add("notes/architecture.md")                    # -> mdx(.md/.mdx 共用)
tool.add("metrics/daily.csv")                        # -> csv

# 2) 关键字参数,显式指定类型
tool.add(path="data.json", data_type=DataType.JSON)
tool.add(file_path="manual.docx", data_type=DataType.DOCX)

# 3) 网页 / GitHub / YouTube 等 URL 源
tool.add(website="https://example.com/docs/start")
tool.add(github_url="https://github.com/org/repo")
tool.add(youtube_url="https://www.youtube.com/watch?v=...")

# 4) 目录:递归跳过隐藏文件与二进制(如 .png/.zip/.pyc 等)
tool.add(directory_path="./my_knowledge_dir")

数据类型推断规则见 DataTypes.from_contentdata_types.py):URL 按路径后缀判文件类型,含 docs 域名/路径视为文档站,GitHub 域名路由到 github,否则视为普通网页;本地路径按扩展名映射,目录归为 directory,其余默认视为纯文本。

目录加载的工程细节

data_typedirectory 时,适配器会递归遍历目录并遵循保守的安全策略(crewai_rag_adapter.py):

  • 跳过隐藏目录(以 . 开头)与隐藏文件;
  • 跳过二进制/不可文本化扩展名清单(含 .png/.jpg/.pdf/.zip/.so/.sqlite 等约 30 类);
  • 跳过 __pycache__ 目录;
  • 单个文件解析失败的场景被静默跳过,不影响整体入库。

检索行为与关键运行参数

RagTool 在类上以 Pydantic 字段暴露一组"检索超参数",均有默认值(rag_tool.py):

字段 默认值 语义
name "Knowledge base" 工具的 LLM 可见名称
description "A knowledge base that can be used to answer questions." 供 Agent 判断何时调用该工具
collection_name "rag_tool_collection" 向量库集合名(collection)
similarity_threshold 0.6 相似度阈值,低于该分数视为不相关,不返回
limit 5 每次检索最多返回的片段数
summarize False 是否对检索结果做摘要后返回
config RagToolConfig() 向量库与 Embedding 提供方配置(见下节)

这些参数既可在构造时设置,也可在单次调用时临时覆盖:_run(query, similarity_threshold=..., limit=...) 支持在调用级覆盖默认阈值与条数(rag_tool.py)。

从源码结构看,调用链为:RagTool._run()CrewAIRagAdapter.query()client.search(collection_name, query, limit, score_threshold)。查询阶段会把命中片段按换行拼装返回;当无任何片段超过阈值时返回 No relevant content found.crewai_rag_adapter.py),该信号同样会传给 Agent 作为"知识库中未找到相关信息"的反馈。

配置深度解析:向量库与 Embedding 提供方

RagTool 的 config 字段接收 RagToolConfig,目前只包含两个子配置(types.py):vectordb(向量数据库)与 embedding_model(Embedding 模型)。配置在构造时会被校验、归一化,再交给 CrewAIRagAdapter 落地(rag_tool.py)。

import os
from crewai_tools import RagTool

rag_tool = RagTool(
    collection_name="customer_faqs",
    similarity_threshold=0.7,
    limit=3,
    config={
        # 向量库:当前支持 chromadb(默认)与 qdrant 两种 provider
        "vectordb": {
            "provider": "chromadb",
            # config 中的键值会透传给 ChromaDBConfig,例如
            # tenant / database / settings(persist_directory 等)
            "config": {},
        },
        # Embedding 模型:provider + config 结构,见下方提供方列表
        "embedding_model": {
            "provider": "openai",
            "config": {
                "api_key": os.getenv("OPENAI_API_KEY"),
                "model_name": "text-embedding-3-small",
            },
        },
    },
)

vectordb:ChromaDB 与 Qdrant

vectordbprovider 字段是 Literal["chromadb", "qdrant"],传入其他值会直接抛出异常,错误信息中会列出受支持的两个 provider(rag_tool.py)。

  • ChromaDB(默认):不传任何配置时,_parse_config 会默认构造 ChromaDB provider。其底层配置类为 ChromaDBConfig,默认 tenant="default_tenant"database="default_database",并使用持久化存储 + allow_reset=True(默认落盘路径由 crewai_core.paths.db_storage_path() 决定,见 constants.py)。
  • Qdrant:将 provider 改为 "qdrant" 后,config 会透传给 QdrantConfig;使用 Qdrant 时,适配器会把 vectors_config 一并传给集合创建逻辑(crewai_rag_adapter.py)。

embedding_model:跨 18 家提供方的 Embedding 工厂

embedding_model 使用 ProviderSpec 联合类型校验,结构统一为 {"provider": "...", "config": {...}}。从 embeddings/types.pyAllowedEmbeddingProviders 看,当前支持以下 provider:azureamazon-bedrockcoherecustomgoogle-generativeaigoogle-vertexhuggingfaceinstructorjinaollamaonnxopenaiopencliproboflowsentence-transformertext2vecvoyageaiwatsonx

例如 Ollama 本地模型与 OpenAI 云端模型的写法差异仅在 provider 与各自的 config 字段上:

# 本地 Ollama(无需联网与 API Key)
{"provider": "ollama", "config": {"model_name": "nomic-embed-text", "url": "http://localhost:11434"}}

# OpenAI(各 provider 的 config 键见 lib/crewai/src/crewai/rag/embeddings/providers/<name>/types.py)
{"provider": "openai", "config": {"api_key": "...", "model_name": "text-embedding-3-large"}}

配置处理上有两处易用性设计值得注意(均来自 rag_tool.py):

  1. 嵌入函数自动注入config.embedding_model 通过 build_embedder()factory.py)构造出嵌入函数后,会被注入到 ChromaDBConfig/QdrantConfigembedding_function 字段,无需手动在 vectordb.config 中重复声明。
  2. 不配置时的默认行为:默认走 ChromaDB 的 _default_embedding_function(),即读取环境变量 OPENAI_API_KEY 并使用 text-embedding-3-smallconfig.py);这意味着开箱即用的前提是环境中已配置 OPENAI_API_KEY,或显式指定 embedding_model
  3. 更友好的校验报错:Embedding 配置校验失败时,自定义 pre-validator 会过滤掉无关的 Union 报错,只显示你指定的那个 provider 的具体字段错误,而不会抛出混杂 18 个分支的长堆栈(rag_tool.py)。

安全保障:路径与 URL 的防御性校验

add() 在真正写库前,会先对所有"用户可控"的路径与 URL 做校验,防止两类典型攻击(rag_tool.py):

  • 文件路径校验(防未授权文件读取):位置参数中形似路径的内容以及 path/file_path/directory_path 关键字参数,都会经过 safe_path.pyvalidate_file_path() 检查,非法输入会被拒绝并抛出 Blocked unsafe file path/… 异常。
  • URL 校验(防 SSRF)url/website/github_url/youtube_url 以及位置参数中的 http(s)/file 链接统一走 validate_url(),被拦截时抛出 Blocked unsafe URL: …

代码对已解析路径做了规范化后回填(对 dict 形式的内容同步改写其 source/content),以规避符号链接(symlink)带来的 TOCTOU(time-of-check to time-of-use)竞争问题;关键字参数同样逐一校验,不存在绕过位置参数检查的旁路。相关安全场景在测试目录 test_rag_tool_path_validation.py 中可查到用例,测试还会通过环境变量 CREWAI_TOOLS_ALLOW_UNSAFE_PATHS=true 显式放行临时目录(rag_tool_test.py)。

结合 Agent 的端到端示例

把"注入知识 → 挂到 Agent → 提问"串起来,一个最小可运行的 Crew 如下:

import os
from crewai import Agent, Task, Crew
from crewai_tools import RagTool

# 1) 构造并注入知识(支持注入多段,add 可多次调用)
kb = RagTool(
    collection_name="product_docs",
    config={
        "embedding_model": {
            "provider": "openai",
            "config": {
                "api_key": os.getenv("OPENAI_API_KEY"),
                "model_name": "text-embedding-3-small",
            },
        }
    },
)
kb.add(directory_path="./product_docs")   # 一次灌入整个文档目录
kb.add(website="https://example.com/faq") # 补充网页源

# 2) 把知识库工具交给 Agent
researcher = Agent(
    role="Senior Research Analyst",
    goal="Answer questions grounded in the product knowledge base",
    backstory="You always verify answers against provided materials.",
    tools=[kb],
)

# 3) 让 Crew 在需要时自动检索
task = Task(
    description="What are the system requirements of product X?",
    agent=researcher,
)
crew = Crew(agents=[researcher], tasks=[task])
result = crew.kickoff()
print(result)

运行前提:请按 crewai-tools 安装说明 安装依赖;使用默认 Embedding 时需要有效 OPENAI_API_KEY,或按上文在 config.embedding_model 中显式切换到本地/自建模型(如 ollama、sentence-transformer)。

深入仓库:推荐的源码阅读路径

若想继续探究 RagTool 的实现细节,可按下面路径顺藤摸瓜:

总体而言,RagTool 把"加载多源数据 → 分块 → 向量化 → 建集合 → 相似度检索"这条 RAG 流水线完整封装成了一个标准 Agent Tool。理解它只需把握住一条主线:add() 负责一切数据的入库,_run()/query 负责一切检索,config 决定 Embedding 与向量库的形态——围绕这三件事,你就能把任何 Crew 改造成"带着知识库干活"的形态。

RagTool 遵循 MIT 协议开源,欢迎通过标准的 fork + pull request 流程向 crewai-tools 贡献新的 Loader、Chunker 或数据源支持。

登录后查看全文
热门项目推荐
相关项目推荐