召回与检索系统
检索与搜索系统
相关源文件
以下文件为本维基页面的生成提供了上下文:
api/db/__init__.pyapi/db/db_models.pyapi/db/services/dialog_service.pyapi/db/services/document_service.pyapi/db/services/file_service.pyapi/db/services/knowledgebase_service.pyapi/db/services/llm_service.pyapi/db/services/task_service.pyapi/db/services/user_service.pycommon/query_base.pymemory/services/query.pyrag/nlp/query.pyrag/nlp/rag_tokenizer.pyrag/nlp/search.pyrag/nlp/term_weight.pyrag/raptor.pyrag/svr/task_executor.py
目的与范围
本文档概述了 RAGFlow 的检索与搜索系统,该系统结合了 BM25 文本搜索与向量相似度搜索,用于检索与对话式 AI 响应相关的文档片段。系统支持混合搜索策略、重排序、元数据过滤以及自动引用插入。
关于文档存储层实现的详细信息,请参阅文档存储抽象层。关于查询处理算法的详细信息,请参阅查询处理与混合搜索。关于重排序模型集成,请参阅重排序与过滤。关于上下文格式化与大语言模型(LLM)响应生成,请参阅响应生成与引用。
系统架构
检索系统作为用户查询与文档存储之间的桥梁,协调嵌入向量生成、混合搜索、重排序和引用插入。
检索编排图
来源: api/db/services/dialog_service.py:98-150 rag/nlp/search.py:37-41 rag/nlp/search.py:132-172 api/db/services/llm_service.py:85-163
核心组件
Dealer 类
Dealer 类 rag/nlp/search.py:37-41 是检索操作的核心编排器。它封装了以下功能:
- 使用
FulltextQueryerrag/nlp/query.py:28-40进行查询处理,用于 BM25 分词和扩展。 - 通过
self.dataStorerag/nlp/search.py:40管理文档存储连接。 - 通过
get_vector()rag/nlp/search.py:53-61生成向量嵌入向量。 - 使用
FusionExprrag/nlp/search.py:25协调混合搜索。 - 通过
insert_citations()rag/nlp/search.py:177-267实现引用插入逻辑。
系统会实例化一个单例 Dealer 实例作为 settings.retriever common/settings.py,该实例在整个应用程序中使用。
文档存储抽象层
RAGFlow 通过 DocStoreConnection common/doc_store/doc_store_base.py 中定义的统一接口支持多种文档存储后端:
| 存储引擎 | 实现类 | 引擎标志 |
|---|---|---|
| Elasticsearch | ESConnection rag/utils/es_conn.py | DOC_ENGINE=elasticsearch |
| Infinity | InfinityConnection rag/utils/infinity_conn.py | DOC_ENGINE=infinity |
| OpenSearch | OpenSearchConnection rag/utils/opensearch_conn.py | DOC_ENGINE=opensearch |
每个实现都提供了 search() 方法 rag/nlp/search.py:132-172,该方法接受以下参数:
- 要检索的源字段(
src)rag/nlp/search.py:149-153。 - 用于关键词强调的高亮字段
rag/nlp/search.py:168-172。 - 通过
get_filters()rag/nlp/search.py:120-130设置的过滤条件(kb_id、doc_id 等)。 - 匹配表达式(文本、稠密向量、融合)
rag/nlp/search.py:173-180。 - 通过
OrderByExprrag/nlp/search.py:142指定的排序规范。
用于模型的 LLMBundle
LLMBundle 类 api/db/services/llm_service.py:85 为以下功能提供了统一接口:
- 嵌入向量模型:
encode()api/db/services/llm_service.py:95和encode_queries()api/db/services/llm_service.py:120生成向量表示。 - 重排序模型:通过
similarity()api/db/services/llm_service.py:136计算查询与文本之间的相关性分数。 - 聊天模型:用于响应生成和查询优化。
来源: rag/nlp/search.py:37-61 api/db/services/llm_service.py:85-163 rag/nlp/query.py:28-40
对话式 AI 中的检索流程
以下时序图展示了检索如何集成到对话式 AI 管线中:
关键步骤:
- 模型加载:通过
get_model_config_by_type_and_nameapi/db/joint_services/tenant_model_service.py:78为对话的知识库加载嵌入向量、聊天和可选的重排序模型。 - 查询优化:如果启用了多轮对话,则使用大语言模型(LLM)通过
full_question()api/db/services/dialog_service.py:51生成一个独立的问题。 - 元数据过滤:如果配置了文档元数据过滤器,则通过
apply_meta_data_filterapi/db/services/dialog_service.py:38应用过滤。 - 混合搜索:使用加权融合将 BM25 文本搜索与向量相似度搜索结合
rag/nlp/search.py:115-148。 - 重排序:可选地使用专门的重排序模型或基于相似度的分数对结果进行重排序
rag/nlp/search.py:296-387。 - 引用插入:如果启用,通过将答案句子与源片段进行匹配,在答案中注入
[ID:X]标记rag/nlp/search.py:177-267。
来源: api/db/services/dialog_service.py:16-100 rag/nlp/search.py:132-172 rag/nlp/search.py:177-267
混合搜索策略
RAGFlow 实现了一种结合词法(BM25)和语义(向量)检索的混合搜索方法:
匹配表达式
搜索管线构建匹配表达式 rag/nlp/search.py:115-130:
- MatchTextExpr(BM25):
- 由
FulltextQueryer.question()rag/nlp/query.py:42-181生成。 - 在
FulltextQueryer定义的分词字段中搜索:title_tks、important_kwd、content_ltks等rag/nlp/query.py:32-40。 - 使用字段特定的权重(例如,
title_tks^10、important_kwd^30)。
- 由
- MatchDenseExpr(向量):
- 来自
get_vector()rag/nlp/search.py:53-61的查询嵌入向量。 - 与
q_{dim}_vec列进行匹配rag/nlp/search.py:60。 - 使用余弦相似度度量,并带有可配置的阈值
rag/nlp/search.py:61。
- 来自
- FusionExpr(组合):
- 方法:
weighted_sumrag/nlp/search.py:25。 - 结合来自词法和语义索引的结果。
- 方法:
回退策略
如果初始搜索返回零结果,系统可能会使用更宽泛的参数进行重试。Dealer 还包含一个 _prune_deleted_chunks 机制 rag/nlp/search.py:76-118,通过检查 DocumentService.get_by_ids() rag/nlp/search.py:72 来确保检索到的片段对应于数据库中存在的文档。
来源: rag/nlp/search.py:132-172 rag/nlp/query.py:32-40 rag/nlp/search.py:53-61
重排序与评分
重排序方法
Dealer.rerank() 方法 rag/nlp/search.py:296-387 使用多种评分机制来优化搜索结果:
评分组件:
- 混合相似度
rag/nlp/query.py:183-187:- Token 重叠:
token_similarity计算查询 Token 与片段 Token 之间的重叠。 - 向量余弦:查询嵌入向量与片段嵌入向量之间的余弦相似度。
- 公式:
vtweight * vector_sim + tkweight * token_simrag/nlp/query.py:183-187。
- Token 重叠:
- 排序特征
rag/nlp/search.py:269-294:- 标签相似度:查询标签与片段标签之间的余弦相似度
rag/nlp/search.py:286。 - PageRank:来自
PAGERANK_FLD的文档重要性分数rag/nlp/search.py:290。
- 标签相似度:查询标签与片段标签之间的余弦相似度
- 最终分数
rag/nlp/search.py:373-387:- 基础分:
hybrid_similarity * 100。 - 提升分:
+ rank_feature_score。 - 结果按最终分数降序重新排序。
- 基础分:
来源: rag/nlp/search.py:296-387 rag/nlp/query.py:183-187 rag/nlp/search.py:269-294
引用插入
insert_citations() 方法 rag/nlp/search.py:177-267 通过将答案句子与检索到的片段进行匹配,为生成的答案添加引用标记。
算法
- 句子分割:使用一个正则表达式将答案分割成句子,该正则表达式处理各种标点符号,并避免在代码块内进行分割
rag/nlp/search.py:182-210。 - 嵌入向量:使用嵌入向量模型对每个句子进行嵌入向量
rag/nlp/search.py:236。 - 相似度计算:对于每个句子,计算其与所有检索到的片段之间的
hybrid_similarityrag/nlp/search.py:241。 - 阈值匹配:如果相似度超过阈值(起始为 0.63,衰减至 0.3),则添加引用
rag/nlp/search.py:228, 246。 - 标记插入:在符合条件的句子后插入
[ID:X]等标记rag/nlp/search.py:252-266。
来源: rag/nlp/search.py:177-267
API 集成
元数据过滤
元数据过滤在搜索请求构建期间进行处理。get_filters 方法 rag/nlp/search.py:120-130 将请求参数映射到文档存储过滤器,包括 kb_ids、doc_ids 以及特定的元数据字段,如 knowledge_graph_kwd、entity_kwd 或 available_int。通过 apply_meta_data_filter api/db/services/dialog_service.py:38 应用使用布尔条件的高级过滤逻辑。
来源:
rag/nlp/search.py:120-130api/db/services/dialog_service.py:38