重排序与筛选(中文译文)
原始 DeepWiki 页面:https://deepwiki.com/infiniflow/ragflow/9.3-reranking-and-filtering
翻译时间:2026-05-27T08:44:53.585Z
翻译模型:deepseek-chat
原文字符数:16570
项目:RAGFlow (ragflow)
---
重排序与过滤
相关源文件
以下文件被用作生成此维基页面的上下文:
agent/tools/retrieval.pyapi/apps/llm_app.pyapi/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.pyconf/llm_factories.jsonrag/llm/__init__.pyrag/llm/chat_model.pyrag/llm/cv_model.pyrag/llm/embedding_model.pyrag/llm/rerank_model.pyrag/llm/sequence2txt_model.pyrag/llm/tts_model.pyrag/nlp/search.pyrag/raptor.pyrag/svr/task_executor.pyweb/src/components/rerank.tsxweb/src/components/similarity-slider/index.tsxweb/src/components/svg-icon.tsxweb/src/components/switch-fom-field.tsxweb/src/components/top-n-item.tsxweb/src/components/use-knowledge-graph-item.tsxweb/src/constants/llm.tsweb/src/pages/agent/form/retrieval-form/next.tsxweb/src/pages/agent/form/tool-form/retrieval-form/index.tsxweb/src/pages/user-setting/setting-model/constant.tsweb/src/utils/common-util.ts
本文档介绍 RAGFlow 的双层重排序系统和过滤机制,这些机制会在搜索结果呈现给大语言模型(LLM)进行答案生成之前对其进行优化。该系统结合了基于相似度的评分、可选的基于模型的重排序、排序特征评分(标签、PageRank)以及阈值过滤,以优化片段选择。
有关初始搜索和检索过程的信息,请参阅 9.2 查询处理与混合搜索。有关将检索到的片段格式化为上下文的后续步骤,请参阅 9.4 响应生成与引用。
系统概览
重排序与过滤系统作为混合搜索检索后的后处理层运行。它接收来自文档存储(Elasticsearch、Infinity 或 OpenSearch)的初始搜索结果,并应用额外的评分和过滤逻辑。核心逻辑位于 rag/nlp/search.py 的 Dealer 类中 rag/nlp/search.py:37-41。
高层重排序管线
flowchart LR
subgraph Input["输入数据"]
SearchResults["SearchResult<br/>(来自混合搜索)"]
Query["用户查询"]
Config["重排序配置<br/>similarity_threshold<br/>vector_similarity_weight<br/>rerank_mdl"]
end
subgraph "Dealer.search() 执行"
SearchPhase["Dealer.search()<br/>混合搜索<br/>(向量 + BM25)"]
RerankDecision{"rerank_mdl<br/>是否提供?"}
ModelRerank["Dealer.rerank_by_model()<br/>基于大语言模型的重排序"]
SimilarityRerank["Dealer.rerank()<br/>基于相似度的重排序"]
InfinityScore["使用 Infinity 融合分数<br/>(预归一化)"]
end
subgraph "评分逻辑"
RankFeatures["_rank_feature_scores()<br/>TAG_FLD + PAGERANK_FLD"]
HybridSim["hybrid_similarity()<br/>Token + 向量加权"]
FinalScore["最终分数<br/>(sim + rank_fea)"]
end
subgraph "过滤逻辑"
ThresholdFilter["应用 similarity_threshold"]
AvailabilityFilter["过滤 available_int 片段"]
TopN["选择前 N 个结果"]
end
subgraph Output["输出结果"]
RankedChunks["排序后的片段<br/>(按分数排序)"]
end
SearchResults --> SearchPhase
Query --> SearchPhase
Config --> SearchPhase
SearchPhase --> RerankDecision
RerankDecision -->|是| ModelRerank
RerankDecision -->|否,ES| SimilarityRerank
RerankDecision -->|否,Infinity| InfinityScore
ModelRerank --> RankFeatures
SimilarityRerank --> RankFeatures
InfinityScore --> RankFeatures
RankFeatures --> FinalScore
HybridSim --> FinalScore
FinalScore --> ThresholdFilter
ThresholdFilter --> AvailabilityFilter
AvailabilityFilter --> TopN
TopN --> RankedChunks
来源:rag/nlp/search.py:132-167, api/db/services/dialog_service.py:176-181
基于相似度的重排序
Dealer.rerank() 方法通过计算混合相似度分数来实现基于相似度的重排序,该分数结合了基于 Token 的相似度(BM25 风格)和基于向量的相似度 rag/nlp/search.py:296-300。这是未指定外部重排序模型时的默认行为。
实现
重排序过程从每个片段中提取可搜索的 Token,包括内容、标题、重要关键词和问题关键词。然后,使用 Token 重叠度和向量余弦相似度,将这些 Token 与用户查询进行评分。
基于相似度的重排序数据流
flowchart TB
subgraph Input["输入(Dealer.rerank)"]
SRes["sres: SearchResult<br/>ids, fields, query_vector"]
Query1["query: str"]
Weights["tkweight, vtweight<br/>(默认:0.3, 0.7)"]
end
subgraph "Token 提取"
ExtractTokens["为每个片段提取 Token:<br/>content_ltks<br/>title_tks x2<br/>important_kwd x5<br/>question_tks x6"]
QueryTokens["query.FulltextQueryer.question()<br/>提取查询关键词"]
end
subgraph "向量准备"
ExtractVectors["从 fields 中提取 q_N_vec<br/>(如果缺失则使用零向量)"]
end
subgraph "评分(qryr.hybrid_similarity)"
TokenSim["token_similarity()<br/>Jaccard 相似度<br/>在查询与片段 Token 之间"]
VectorSim["vector_similarity()<br/>余弦相似度<br/>在 query_vector 与片段向量之间"]
WeightedSum["sim = tkweight * tksim<br/>+ vtweight * vtsim"]
end
subgraph "排序特征"
RankFea["_rank_feature_scores()<br/>TAG_FLD 余弦相似度<br/>+ PAGERANK_FLD"]
end
subgraph Output["输出"]
FinalSim["final_sim = sim + rank_fea"]
ReturnScores["返回 (sim, tksim, vtsim)"]
end
SRes --> ExtractTokens
SRes --> ExtractVectors
Query1 --> QueryTokens
ExtractTokens --> TokenSim
QueryTokens --> TokenSim
ExtractVectors --> VectorSim
SRes --> VectorSim
TokenSim --> WeightedSum
VectorSim --> WeightedSum
Weights --> WeightedSum
WeightedSum --> RankFea
SRes --> RankFea
RankFea --> FinalSim
FinalSim --> ReturnScores
来源:rag/nlp/search.py:296-333, rag/nlp/query.py:23-25, rag/nlp/query.py:41-43
Token 加权策略
系统对不同 Token 类型应用差异化的权重,以反映其语义重要性:
| Token 来源 | 权重乘数 | 字段名 | 用途 |
|---|---|---|---|
| 内容 Token | 1x | content_ltks | 基础内容匹配 |
| 标题 Token | 2x | title_tks | 文档标题相关性 |
| 重要关键词 | 5x | important_kwd | 大语言模型提取的关键概念 |
| 问题 Token | 6x | question_tks | 为问答匹配生成的问题 |
这种加权方案优先考虑与大语言模型生成的元数据(问题、关键词)的匹配,而非原始内容的匹配,从而提高了语义相关性 rag/nlp/search.py:318-323。
来源:rag/nlp/search.py:318-323
向量维度处理
重排序逻辑会处理片段向量与查询向量维度不同(例如,当嵌入模型发生更改时)的情况。维度不匹配的片段会收到零向量,以防止崩溃 rag/nlp/search.py:310-315。
来源:rag/nlp/search.py:310-315
基于模型的重排序
当通过 Dialog 模型中的 rerank_id 配置了重排序模型时,系统会使用 Dealer.rerank_by_model() 来计算基于大语言模型的相关性分数 rag/nlp/search.py:335-340。这提供了比纯相似度指标更复杂的语义理解能力。
重排序器模型接口
重排序模型作为配置了 LLMType.RERANK 的 LLMBundle 实例传入 api/db/services/llm_service.py:85-86。该模型的 similarity() 方法 rag/llm/rerank_model.py:34-35 计算查询与每个片段文本之间的相关性分数。
基于模型的重排序架构
flowchart TB
subgraph Input["输入(rerank_by_model)"]
RerankMdl["rerank_mdl: LLMBundle<br/>(LLMType.RERANK)"]
SRes2["sres: SearchResult"]
Query2["query: str"]
Weights2["tkweight, vtweight"]
end
subgraph "Token 处理"
ExtractToks["提取 Token:<br/>content_ltks<br/>title_tks<br/>important_kwd"]
PrepareTexts["拼接 Token<br/>remove_redundant_spaces()"]
end
subgraph "双重评分"
TokenScore["token_similarity()<br/>(传统 BM25 风格)"]
ModelScore["rerank_mdl.similarity()<br/>(基于大语言模型的相关性)"]
end
subgraph "组合"
WeightedCombine["tkweight * tksim<br/>+ vtweight * vtsim"]
AddRankFea["+ _rank_feature_scores()"]
end
subgraph Output2["输出"]
FinalScore2["(final_scores, tksim, vtsim)"]
end
RerankMdl --> ModelScore
SRes2 --> ExtractToks
Query2 --> TokenScore
Query2 --> ModelScore
ExtractToks --> PrepareTexts
PrepareTexts --> ModelScore
ExtractToks --> TokenScore
TokenScore --> WeightedCombine
ModelScore --> WeightedCombine
Weights2 --> WeightedCombine
WeightedCombine --> AddRankFea
SRes2 --> AddRankFea
AddRankFea --> FinalScore2
来源:rag/nlp/search.py:335-356, api/db/services/dialog_service.py:181-183, rag/llm/rerank_model.py:34-35
排序特征评分
_rank_feature_scores() 方法添加了超越纯文本相似度的领域特定排序信号。它基于标签匹配和 PageRank 值计算分数 rag/nlp/search.py:269-272。
标签特征评分
基于标签的评分计算查询的标签特征与每个片段标签之间的余弦相似度。标签存储在 TAG_FLD 字段中 rag/nlp/search.py:28-28。
标签特征评分算法
flowchart TB
subgraph Input3["输入"]
QueryRfea["query_rfea: dict<br/>{tag: score, ...}"]
ChunkTags["chunk TAG_FLD<br/>JSON 编码的字典"]
ChunkPagerank["chunk PAGERANK_FLD"]
end
subgraph "查询归一化"
CalcQDenor["q_denor = sqrt(sum(score^2))<br/>(排除 PAGERANK_FLD)"]
end
subgraph "逐片段评分"
ParseTags["eval(chunk[TAG_FLD])"]
DotProduct["nor = sum(query[tag] * chunk[tag])<br/>用于匹配的标签"]
ChunkNorm["denor = sqrt(sum(chunk_score^2))"]
CosineSim["score = nor / (sqrt(denor) * q_denor)"]
end
subgraph "组合"
ScaleTag["tag_score * 10.0"]
AddPagerank["+ chunk[PAGERANK_FLD]"]
FinalRank["final_rank_score"]
end
QueryRfea --> CalcQDenor
ChunkTags --> ParseTags
CalcQDenor --> CosineSim
ParseTags --> DotProduct
DotProduct --> CosineSim
ParseTags --> ChunkNorm
ChunkNorm --> CosineSim
CosineSim --> ScaleTag
ScaleTag --> AddPagerank
ChunkPagerank --> AddPagerank
AddPagerank --> FinalRank
来源:rag/nlp/search.py:269-294
PageRank 集成
PageRank 值(PAGERANK_FLD)提供了独立于查询内容的文档级重要性信号。这些值会直接添加到排序特征分数中 rag/nlp/search.py:294。
来源:rag/nlp/search.py:272-294, common/constants.py:93-93
阈值过滤
检索管线会应用多个过滤阶段来移除低质量或不相关的片段。
相似度阈值
similarity_threshold 参数根据片段的最终相似度分数进行过滤。该参数按对话进行配置,默认值为 0.2 api/db/services/dialog_service.py:178-178。
检索中的阈值应用
flowchart LR
subgraph "初始搜索"
HybridSearch["使用相似度参数的<br/>混合搜索"]
end
subgraph "重排序"
Rerank["计算最终分数<br/>(sim + rank_fea)"]
SortScores["按分数降序排序"]
end
subgraph "过滤阶段"
ThreshFilter["过滤:score >= threshold"]
TopKFilter["选择前 K 个片段"]
AvailFilter["过滤:available_int == 1"]
end
subgraph Output3["输出"]
FinalChunks["过滤并排序后的片段"]
end
HybridSearch --> Rerank
Rerank --> SortScores
SortScores --> ThreshFilter
ThreshFilter --> TopKFilter
TopKFilter --> AvailFilter
AvailFilter --> FinalChunks
来源:rag/nlp/search.py:120-130, api/db/services/dialog_service.py:176-180
可用性过滤
可以使用 available_int 字段将片段标记为不可用。这允许在不删除片段的情况下,手动或自动管理片段的可见性 rag/nlp/search.py:125-129。
# 来自 search.py:150-153
src = req.get("fields",
["docnm_kwd", "content_ltks", "kb_id", "img_id", "title_tks", "important_kwd", "position_int",
"doc_id", "chunk_order_int", "page_num_int", "top_int", "create_timestamp_flt", "knowledge_graph_kwd",
"question_kwd", "question_tks", "doc_type_kwd",
"available_int", "content_with_weight", "mom_id", PAGERANK_FLD, TAG_FLD, "row_id()"])
来源:rag/nlp/search.py:150-153
在检索管线中的集成
完整的检索流程将重排序和过滤集成为一个统一的管线,由 Dealer.search() 执行 rag/nlp/search.py:132-137。
重排序限制与分页
检索逻辑使用分页参数来控制为重排序检索的候选数量 rag/nlp/search.py:144-147。
# 来自 search.py:144-147
pg = int(req.get("page", 1)) - 1
topk = int(req.get("topk", 1024))
ps = int(req.get("size", topk))
offset, limit = pg * ps, ps
来源:rag/nlp/search.py:144-147
后端特定的重排序逻辑
系统会根据文档存储后端(Elasticsearch 与 Infinity)调整其重排序策略。Infinity 会预归一化融合分数,而 Elasticsearch 则需要通过 rerank() 方法进行手动归一化 rag/nlp/search.py:174-180。
后端特定的重排序逻辑
flowchart TB
subgraph Config["配置检查"]
CheckRerank{"rerank_mdl<br/>是否提供?"}
CheckBackend{"settings.DOC_ENGINE_INFINITY"}
end
subgraph "重排序路径"
ModelPath["使用 rerank_by_model()<br/>(适用于两个后端)"]
InfinityPath["使用 Infinity 融合分数<br/>(预归一化)"]
ESPath["使用 rerank()<br/>(ElasticSearch 需要归一化)"]
end
subgraph "分数处理"
UseScores["从 sres.field 提取 _score"]
NormalizeScores["归一化并组合<br/>Token + 向量分数"]
end
subgraph Output4["输出"]
SortedChunks["按最终分数排序的片段"]
end
CheckRerank -->|是| ModelPath
CheckRerank -->|否| CheckBackend
CheckBackend -->|True| InfinityPath
CheckBackend -->|False| ESPath
InfinityPath --> UseScores
ESPath --> NormalizeScores
ModelPath --> NormalizeScores
UseScores --> SortedChunks
NormalizeScores --> SortedChunks
来源:rag/nlp/search.py:132-180, common/settings.py:92-92