| 功能模块 | 描述 |
|---|---|
| 解析器 Parser | 把原始文件拆分成若干 Section 对象,每个 Section 对应文件的一个自然边界(PDF 页、PPTX 幻灯片、Markdown 标题段、整张图片等) |
| 切块器 Chunker | 把 Section 切成最终入库的 Chunk,并保证不跨 Section 合并 |
| 嵌入模型 Embedding Model | 把 Chunk 的文本或多模态内容嵌入为向量 |
| 向量库 Vector Store | 连接向量数据库,存储 Chunk 的向量与元信息,并支持检索 |
| 知识库句柄 KnowledgeBase | 把嵌入模型 + 向量库 + collection 绑定在一起,封装 insert_document / search / list_documents / delete_document 四个一站式接口 |
现有实现
AgentScope 为每个模块提供了开箱即用的默认实现,全部基于基类继承,方便用户替换:解析器
| 类 | 描述 | 支持文件类型 |
|---|---|---|
TextParser | 文本数据解析器,整文件作为一个 Section 返回,由下游切块器切分 | text/plaintext/markdowntext/csvtext/htmltext/x-rstapplication/jsonapplication/xmlapplication/x-yaml |
PDFParser | PDF 解析器,每页一个 Section,元信息中携带从 1 开始的页码 page 字段。 | application/pdf |
PPTParser | PowerPoint (.pptx) 解析器,按幻灯片顺序遍历形状:- 文本/表格合并为同一 Section,- 图片作为独立 DataBlock 读取。元信息中携带从 1 开始的幻灯片序号 slide 字段。 | application/vnd.openxmlformats-officedocument.presentationml.presentation |
ImageParser | 图片解析器,将整张图片读取为一个 Section | image/pngimage/jpegimage/gifimage/bmpimage/webp |
| 开发中 … |
切块器
| 类 | 描述 |
|---|---|
ApproxTokenChunker | 按近似 Token 数进行切分,不依赖任何 tokenizer。 近似策略: len(text.encode("utf-8")) // 4;多模态 DataBlock 整块透传不切分 |
| 开发中 … |
嵌入模型
请见嵌入模型章节。向量数据库
| 类 | 描述 |
|---|---|
QdrantStore | 基于 Qdrant 的向量数据库实现,支持内存(location=":memory:")、本地磁盘(path=...)、远程服务(url=...)三种部署方式 |
| 开发中 … |
RAG 使用
AgentScope 推荐通过知识库句柄KnowledgeBase 作为入口使用 RAG。它把嵌入模型、向量库、collection(以及可选的 metadata_filter 多租户隔离配置)绑定在一起,对外只暴露四个动作:
| 方法 | 描述 |
|---|---|
insert_document(chunks, document_id=None, document_metadata=None) | 把一批 Chunk 作为同一个文档批量嵌入并写入,返回 document_id |
search(queries, top_k=5, score_threshold=None) | 对一组查询(str / TextBlock / DataBlock)执行向量检索,自动去重排序 |
delete_document(document_id) | 按 document_id 删除整个文档的所有 chunk |
list_documents() | 返回当前知识库中所有文档的 DocumentSummary 列表 |
索引文件
索引文件需要经过 文件解析 → 切块 → 嵌入入库 三步,对应上述三个模块。下面展示端到端的索引流程。解析文件
使用解析器的
parse 方法把原始文件读取成 Section 数组,每个 Section 对应文件的一个自然边界(PDF 页 / PPT 幻灯片 / 图片 …)。parse(file, filename) 的 file 参数同时支持 bytes 与 str:bytes直接作为原始文件内容;str在二进制解析器(PDFParser/PPTParser/ImageParser)中表示文件路径,解析器自动读盘;str在TextParser中按运行时判断——若该字符串指向一个存在的文件就当作路径读盘并按encoding解码,否则当作已解码的文本内容直接使用。
切分 Chunk
使用切块器的
chunk 方法把 Section 数组切成最终入库的 Chunk 数组。约定:不跨 Section 合并;多模态 DataBlock 整块透传;chunk_index 从 0 连续编号,total_chunks 在每个 chunk 上都是同一值。向量检索
通过KnowledgeBase.search 直接传入查询字符串/TextBlock/DataBlock 即可,无需手动嵌入:
search 内部做了以下几件事:
- 过滤不可用查询:若绑定的嵌入模型
supports_multimodal == False,会静默丢弃DataBlock类型的查询; - 批量嵌入:所有查询一次性批量嵌入,再并发地对 collection 检索;
- 去重:按
(document_id, chunk_index)去重,保留每条记录的最高分; - 截断:按分数降序排序后截断为
top_k。
VectorSearchResult 数组,每条记录包含 score、document_id 与命中 chunk。
文档管理
KnowledgeBase 暴露了文档级别的两个辅助方法:
DocumentSummary 包含 document_id、原始文件名 source、chunk_count,以及由解析器/上传方写入第一条 chunk 的 metadata。
多租户隔离:metadata_filter
如果多个逻辑知识库需要共用同一个物理 collection,可以在构造 KnowledgeBase 时传入 metadata_filter(典型场景:每条记录都带一个 {"tenant_id": "..."} payload):
metadata_filter 是深度防御机制:
search与list_documents严格按这些key == value过滤记录——永远跨不出当前作用域;insert_document会强制覆盖每个 chunk 的同名 metadata 字段,从而即使解析器/调用方误写也不会让记录跨域泄漏。
None(默认值)表示禁用过滤,对应”每个知识库独占自己的 collection”的部署形态。
多模态支持
AgentScope 的 RAG 原生支持多模态数据的入库与检索,关键在于解析器与嵌入模型能力的匹配——前者要能把多模态文件解析成DataBlock,后者要能直接对 DataBlock 做嵌入:
-
查看 Parser 支持的文件类型:每个
ParserBase子类通过类属性supported_media_types(IANA 媒体类型列表)声明能力,可直接读取或在 IDE 中自动补全。 -
查看嵌入模型支持的模态:通过实例属性
embedding_model.supports_multimodal判断模型是否能直接处理DataBlock(图片 / 视频 / 音频)。
Chunk、且 embedding_model.supports_multimodal == True 时,入库与检索链路无需额外配置即可工作。文本模型遇到 DataBlock 查询时会在 KnowledgeBase.search 内部被静默丢弃,不会报错。
集成到智能体
通过RAGMiddleware 把检索接入智能体类 Agent 的推理-行动循环。中间件不拥有嵌入模型或向量库——它消费的是一组已经构造好的 KnowledgeBase 句柄,可以混合多个使用不同嵌入模型的知识库。
RAGMiddleware 支持两种工作模式(RAGMiddleware.Parameters.mode),可以单独使用,也可以叠加使用(同时挂两个不同 mode 的实例):
| 模式 | 触发时机 | 检索关键词 | 注入方式 |
|---|---|---|---|
"static" | 每次 reply 的首次推理前 | reply 方法的输入消息作为检索关键词,支持多模态数据 | 检索结果被包装成 HintBlock 并注入到上下文中 |
"agentic"(默认) | 模型自主调用检索工具 | 模型自主给出 | 暴露 search_knowledge 工具,由智能体自己判断何时检索、用什么 query |
RAGMiddleware.Parameters 模型中:
| 字段 | 默认值 | 描述 |
|---|---|---|
mode | "agentic" | 集成模式,详见上表 |
top_k | 5 | 单次检索返回的最大命中数;跨所有知识库与 query 输入去重后截断 |
score_threshold | None | 命中相似度下限,仅在 cosine / dot-product 下有意义 |
emit_hint_event | True | static 模式下是否额外发出 HintBlockEvent 供前端展示命中片段 |
persist_hint | False | static 模式下注入块是否持久留在上下文(默认推理后即移除,避免污染下一轮) |
RAGMiddleware.list_tools() 在 agentic 模式下会返回一个 search_knowledge 工具——需要手动把它注册到智能体的 Toolkit 里,模型才能调用。该工具的描述里会自动列出已挂载的所有知识库的 name / description,模型也可以通过 knowledge_bases=[...] 参数把搜索限定到指定子集。
通过如下代码给智能体实例配置 RAG 功能:
自定义拓展
RAG 的所有模块都采用基类继承的方式,用户可以自定义 Parser、Chunker、Embedding Model、Vector Store——只要继承对应基类、实现核心方法,就能被无缝接入上面的流水线。自定义解析器
继承ParserBase,在类属性 supported_media_types 中声明能处理的 IANA 媒体类型,并实现 async def parse(file, filename) 把字节流拆成若干 Section:
supported_extensions()(默认由 supported_media_types 反查得到;如果你的解析器希望前端文件选择器只展示某几个扩展名,建议显式覆盖)。
自定义切块器
继承ChunkerBase,实现 async def chunk(sections) 把若干 Section 切成入库的 Chunk。约定:不跨 Section 合并;多模态 DataBlock 整块透传;chunk_index 在结果内从 0 连续编号;total_chunks 在每个 chunk 上一致:
自定义向量数据库
继承VectorStoreBase,实现 create_collection / delete_collection / has_collection / insert / delete / search / list_documents,并通过 __aenter__ / __aexit__ 管理底层连接的生命周期:
delete按document_id删除该文档的所有记录,调用方按文档为单位增删。search/list_documents必须把metadata_filter翻译成对应后端的 payload filter,以支持多租户隔离。insert时需要把VectorRecord.document_id与chunk都持久化下来——否则delete与list_documents都无法工作。
延伸阅读
RAG 服务
多租户、分布式的 RAG 服务,支持 HTTP API、文件托管、向量数据库托管。
中间件
了解
RAGMiddleware 是如何嵌入 reply / reasoning 钩子的。嵌入模型
可用的嵌入模型及其参数。