RAGFlow Agent 知识检索节点深度解析:从查询到重排序的完整流程

1. 总体架构概览

RAGFlow Agent 中的知识检索(Retrieval)节点是整个RAG系统的核心组件,负责从知识库中找到与用户查询最相关的文档片段。检索流程可以分为以下几个核心阶段:

用户查询 → 查询预处理 → 粗排阶段(ES混合检索) → 重排阶段(LLM重排序) → 结果输出
  • 查询预处理:清理用户输入、收集知识库ID、绑定 Embedding 和 ReRank 模型等
  • 粗排阶段(ES混合检索):结合文本检索(BM25)和向量检索(KNN)从ES中召回候选 Chunk
  • 重排阶段(LLM重排序):使用 LLM ReRank 模型对候选 Chunk 进行重排序
  • 结果输出:按输出格式整理数据,返回最终满足条件的 Chunk

2. 源码位置与调用链路详解

主要源码 对应于:

  • 检索节点入口 (agent/component/retrieval.py):其中的类 Retrieval 对应了 RAGFlow 前端页面 Agent 中的 知识检索节点
  • 核心检索逻辑 (rag/nlp/search.py):其中的类 Dealer 是类 Retrieval 的底层实现,实现了粗排、重排等逻辑。主要方法有:retrieval、search(粗排)、rerank_by_model(重排)
  • ES存储层 (rag/utils/es_conn.py):对应 ES 层的实现,封装了 ES 的操作方法
  • ReRank模型 (rag/llm/rerank_model.py):对应了 LLM Rerank 模型的实现,封装了各种模型的调用方法

完整的调用链路 如下:

Retrieval._run() [agent/component/retrieval.py] // 前端 Agent 的知识检索节点,调用下层服务
└── Dealer.retrieval() [rag/nlp/search.py]  // 检索核心逻辑:调用 粗排 + 重排├── Dealer.search() [rag/nlp/search.py]  // 实现粗排逻辑│   └── ESConnection.search() [rag/utils/es_conn.py]  // 调用 ES 执行 BM25 / KNN 查询│└── Dealer.rerank_by_model() [rag/nlp/search.py]  // 实现基于 LLM 的重排逻辑└── QWenRerank.similarity() [rag/llm/rerank_model.py]  // 调用 LLM 计算 Question/Chunk 语义相关性得分,此处以 QWen 为例

3. 粗排阶段(ES混合检索)

3.1 检索策略概述

RAGFlow采用混合检索策略,结合两种互补的检索方法:

  1. 文本检索:基于关键词匹配,擅长精确匹配和术语查找
  2. 向量检索:基于语义相似度,擅长理解查询意图和同义词匹配

3.2 ES 实际查询 DSL 语句

测试条件如下,以下数值都是通过 RAGFlow 前端界面设置与输入的:

  • 用户问题:RAGFlow和FastGPT是什么?
  • 相似度阈值:0.11
  • 关键字权重:0.16
  • Top-K:1024 (粗排结果 Chunk 限制数)
  • Top-N:14 (重排结果 Chunk 限制数)
  • Rerank模型:阿里的 get-rerank

通过在 ESConnection.search 函数调用 es.search(index=indexNames, body=q, …) 之前打印 q 变量,可以得到以下实际执行的 ES DSL 语句(DSL 是 Elasticsearch 的查询语言,类似于 MySQL 的 SQL 语句):

{"query": {"bool": {"must": [{"query_string": {"fields": ["title_tks^10","title_sm_tks^5","important_kwd^30","important_tks^20","question_tks^20","content_ltks^2","content_sm_ltks"],"type": "best_fields","query": "(ragflow^0.4312 ) (和^0.1377 ) (fastgpt^0.4312 ) \"ragflow 和\"^0.8623 \"和 fastgpt\"^0.8623","minimum_should_match": "0%","boost": 1}}],"filter": [{"terms": {"kb_id": ["cb7e95d8683311f080cb725e7685c9ee","03316fc06e7c11f0a10ec67c9f2d779f"]}},{"bool": {"must_not": [{"range": {"available_int": {"lt": 1}}}]}}],"boost": 0.050000000000000044}},"knn": {"field": "q_1024_vec","k": 1024,"num_candidates": 2048,"query_vector": [-0.07246076315641403,0.007768463809043169,...,-0.02680240198969841],"filter": {"bool": {"must": [{"query_string": {"fields": ["title_tks^10","title_sm_tks^5","important_kwd^30","important_tks^20","question_tks^20","content_ltks^2","content_sm_ltks"],"type": "best_fields","query": "(ragflow^0.4312 ) (和^0.1377 ) (fastgpt^0.4312 ) \"ragflow 和\"^0.8623 \"和 fastgpt\"^0.8623","minimum_should_match": "0%","boost": 1}}],"filter": [{"terms": {"kb_id": ["cb7e95d8683311f080cb725e7685c9ee","03316fc06e7c11f0a10ec67c9f2d779f"]}},{"bool": {"must_not": [{"range": {"available_int": {"lt": 1}}}]}}],"boost": 0.050000000000000044}},"similarity": 0.11},"from": 0,"size": 70
}

通过 DSL 语句可以看到,ES搜索结合了文本搜索与向量搜索,分别对应 “query” (文本搜索)与 “knn” (向量搜索)两部分:

  • "query"文本搜索部分:通过 fields 参数指定了被搜索的字段、字段权重,然后使用最匹配的字段的分数作为文本搜索分数 (“type”: “best_fields”)。
  • "knn"向量搜索部分:传入 User Question 向量 query_vector,指定需要的Chunk数 k 1024(对应RAGFlow前端中指定的 Top-K)、相似度阈值 similarity 0.11

ES会综合文本搜索、向量搜索两部分数得到最终粗排召回的 Chunk 。

在 "query"文本搜索的 fields 字段解读

  • "important_kwd^30"表示对 important_kwd 字段搜索,权重调整系数为 30,权重调整值越大表示该字段越重要。
  • 从 fields 中几个字段的权重可以看出 ES 文本搜索时几个字段重要程度为 important_kwd/important_tks (Chunk 绑定的关键词) > question_tks (Chunk 绑定的问题) > title_tks/title_sm_tks (Chunk 对应的文档标题) > content_ltks/content_sm_ltks (Chunk 文本内容)
  • 关于 Chunk 的这几个字段是如何生成的,可以参考我上一篇文章:《 Ragflow 文档处理深度解析:从解析到存储的完整流程 》

4. 重排阶段(基于 Rerank 模型)

4.1 重排序策略选择

RAGFlow 其实是支持两种重排序策略:

  1. 基于模型的重排序 (源码 Dealer.rerank_by_model):基于前端界面中为知识检索节点设定的 Rerank 模型实现重排。
  2. 非模型的重排序 (源码 Dealer.rerank):基于User Question/ES Chunk的文本特征、现有Embedding余弦相似度相似度、Chunk 排名等计算对Chunk进行重排序。

下文只介绍 基于模型的重排序。

4.2 LLM Rerank 重排模型概念介绍

Embedding 检索方法通过分别编码 Query 和 Chunk 得到向量,并用余弦相似度评估相关性。优点是可以提前计算Chunk的向量并存储,检索效率高、可大规模向量召回,适合在粗排阶段使用。但这种独立编码方式无法建模两者之间的语义交互。

而 Rerank 模型会将 Query 和 Chunk 作为一个成对的输入,同时送入模型进行处理。模型可以在编码过程中捕捉两者之间的深层语义关系和交互信息,更准确地评估相关性。这种方式虽然计算开销较大,但在排序质量上具有明显优势,常用于精排阶段。

调用阿里的 gte-rerank 重排模型的代码示例

import dashscope# 请替换为您自己的DashScope API密钥
API_KEY = "sk-d9a37e073d3e446ab359e445315d8394"# 查询问题
query = "如何学习Python编程语言"# 候选文档列表
documents = ["Java是一种面向对象的编程语言,广泛用于企业级应用开发。它具有跨平台性和强类型系统。","Python是一种简单易学的编程语言,语法清晰,适合初学者。它有丰富的第三方库,在数据科学、Web开发等领域应用广泛。","机器学习是人工智能的一个分支,通过算法让计算机从数据中学习模式。常用的框架包括TensorFlow和PyTorch。","Python学习建议:先掌握基础语法,然后通过实际项目练习。推荐从官方教程开始,多写代码多实践。","JavaScript是一种脚本语言,主要用于Web前端开发。现在也可以用Node.js进行后端开发。","数据结构和算法是编程的基础,包括数组、链表、树、图等。掌握这些对提高编程能力很重要。",
]# 调用重排序模型 gte-rerank API
response = dashscope.TextReRank.call(api_key=API_KEY,model="gte-rerank",query=query,documents=documents
)# 输出重排序结果
for rank, result in enumerate(response.output.results, 1):score = result.relevance_scoredoc_text = documents[result.index]print(f"文档排名: {rank}; 相关度: {score:.4f}; 文档内容: {doc_text}")

输出结果:

文档排名: 1; 相关度: 0.6545; 文档内容: Python学习建议:先掌握基础语法,然后通过实际项目练习。推荐从官方教程开始,多写代码多实践。
文档排名: 2; 相关度: 0.5206; 文档内容: Python是一种简单易学的编程语言,语法清晰,适合初学者。它有丰富的第三方库,在数据科学、Web开发等领域应用广泛。
文档排名: 3; 相关度: 0.2310; 文档内容: 数据结构和算法是编程的基础,包括数组、链表、树、图等。掌握这些对提高编程能力很重要。
文档排名: 4; 相关度: 0.0737; 文档内容: JavaScript是一种脚本语言,主要用于Web前端开发。现在也可以用Node.js进行后端开发。
文档排名: 5; 相关度: 0.0701; 文档内容: 机器学习是人工智能的一个分支,通过算法让计算机从数据中学习模式。常用的框架包括TensorFlow和PyTorch。
文档排名: 6; 相关度: 0.0527; 文档内容: Java是一种面向对象的编程语言,广泛用于企业级应用开发。它具有跨平台性和强类型系统。

4.3 RAGFlow LLM Rerank 重排序

RAGFlow 前端界面中如果在知识检索节点配置了 Rerank 模型,那么会调用 Dealer.rerank_by_model,执行逻辑大致如下:

  1. 计算 tksim:基于文本特征计算 Question/Chunk 的 tksim (Token Similarity,其实是知识检索节点前端配置页中指代的 关键词相似度)
  2. 计算 vtsim:基于 LLM Rerank 模型计算 Question/Chunk 的 vtsim (Vector Similarity,向量相似度)
  3. 计算最终 sim:使用 vtsim 与 tksim 加权计算最终的 Question/Chunk 的 sim (Similarity,最终相似度)。

源码如下:

# sres :包含 ES Chunk 的内容
# query :User Question;
# tkweight :前端配置的“关键字相似度权重”
# vtweight :是公式 “1 - tkweight” 计算的结果,表示 rerank 得分的权重
def rerank_by_model(self, rerank_mdl, sres, query, tkweight=0.3,vtweight=0.7, cfield="content_ltks",rank_feature: dict | None = None):# 1. 提取 Query 的关键词                    _, keywords = self.qryr.question(query) # 2. 基于 Chunk 的 token 构建 ins_tw for i in sres.ids:if isinstance(sres.field[i].get("important_kwd", []), str):sres.field[i]["important_kwd"] = [sres.field[i]["important_kwd"]]ins_tw = []for i in sres.ids:content_ltks = sres.field[i][cfield].split()           # Chunk 的内容tokentitle_tks = [t for t in sres.field[i].get("title_tks", "").split() if t]  # Chunk 的文档标题 tokenimportant_kwd = sres.field[i].get("important_kwd", []) # Chunk 的关键词tks = content_ltks + title_tks + important_kwd ins_tw.append(tks) # 组合各种 Token 拼接为 Ins_tw# 3. 计算 Query Keywords 与 Chunk token 间的 关键词相似度 tksim (基于词汇匹配和TF-IDF权重)tksim = self.qryr.token_similarity(keywords, ins_tw)# 4. 计算 向量相似度 vtsim(使用 Rerank Model)vtsim, _ = rerank_mdl.similarity(query, [rmSpace(" ".join(tks)) for tks in ins_tw])# 5. 获取 知识库配置 页中设置的 “页面排名” (Page Rank)参数数值rank_fea = self._rank_feature_scores(rank_feature, sres)# 6. 融合多种相似度得到最终排序分数,并返回三个项:sim, tsim, vsim#    最终分数 sim = tkweight * (tksim + “页面排名”) + vtweight * vtsimreturn tkweight * (np.array(tksim)+rank_fea) + vtweight * vtsim, tksim, vtsim

这个 Dealer.rerank_by_model 函数返回 “sim, tsim, vsim” 三个返回值后,Dealer.retrieval 会基于 sim 变量得到每个 Chunk 的排名(rank)

# 部分源码如下
def retrieval(...):sim, tsim, vsim = self.rerank_by_model(...) # 得到粗排召回的 question/chunk 的精排相似度 sim                  idx = np.argsort(sim * -1)[(page - 1) * page_size:page * page_size] # 基于 sim 从大到小重排 chunk ranks = {"chunks": [], ...} # 基于排序结果 idx 将每个重排后的 chunk 添加到最终召回结果 ranks 中for i in idx:ranks["chunks"].append(d) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91634.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91634.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/91634.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python算法实战:从排序到B+树全解析

Python中常见的算法示例 以下是Python中常见的算法示例,涵盖基础算法和经典问题解决方案,代码可直接运行: 排序算法 冒泡排序 def bubble_sort(arr):n = len(arr)for i in range(n):for j in range(0, n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr…

【C++算法】85.BFS解决最短路径问题_最小基因变化

文章目录题目链接:题目描述:解法C 算法代码:题目链接: 433. 最小基因变化 题目描述: 解法 先看懂题目 先把这个问题转化:图论问题 边权为1的最短路问题。 为什么可以这么想?! 因为每…

基于单片机汽车少儿安全预警系统

文章目录一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成【4】设计意义【5】市面上同类产品研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发1.5 模块的技术详情介绍1.6 框架图框架图说明&…

Mac 上配置jdk 环境变量

核心步骤是设置 JAVA_HOME 变量,并将其 bin 目录添加到系统的 PATH 变量中。 macOS 从 Catalina (10.15) 版本开始,默认的终端 Shell 从 bash 切换到了 zsh。因此,你需要先确定你正在使用的 Shell,然后编辑对应的配置文件。步骤一…

硬件-音频学习DAY1——音箱材料选择:密度板为何完胜实木

每日更新教程,评论区答疑解惑,小白也能变大神!" 目录 一.音箱材料选择的关键因素 二.密度板的声学优势 三.材料稳定性的对比 四.生产工艺的适应性 五.成本与环保的平衡 六.特殊场景的例外情况 七.消费者选购指南 八.行业发展趋势…

微波(Microwave)与毫米波(Millimeter wave)简介

一、电磁波频段划分,微波与毫米波所属 二、微波 可以看出UHF及以上的频段都可以统称为微波。记得之前上微波技术实验课的时候会接触比巴掌还大的金属波导,后来每次看到微波技术的时候都还是感到陌生。今天突然想到,不像在手机里就能完成的5G频…

ObjectMapper教程

ObjectMapper 简介ObjectMapper 是 Jackson 库的核心类,用于 Java 对象与 JSON 数据之间的相互转换。它支持序列化(对象转 JSON)和反序列化(JSON 转对象),广泛应用于 REST API、数据存储和配置处理等场景。…

【Node.js安装注意事项】-安装路径不能有空格

问题描述:在项目中使用 nodemon时,出现了nodemon 启动问题:nodemon : 无法将“nodemon”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。解决办法:在网上找了很多教程,试了很多办法,什么重新配置环境…

Shader开发(六)什么是着色器

在前面的章节中,我们简要提到了着色器的概念,现在有了渲染管线的基础知识,我们可以更深入地理解着色器的真正含义。着色器(Shader)是运行在图形处理单元(GPU)上的专用程序,这与我们日…

操作系统-lecture4(进程的调度)

进程的切换 接下来需要了解两个问题 谁触发了进程切换进程切换的动作 中断技术 中断源 中断处理过程(陷阱机制) 特权指令和非特权指令 Privileged Instructions:特权指令 •The Instructions that can run only in Kernel Mode are called…

机器人程序优化

机器人程序优化核心摘要 本视频详细讲解了机器人程序优化的方法与实践,旨在提高程序的可读性和复用性。通过学习文件夹、子程序调用以及路点优化等核心概念,观众将掌握如何将复杂的机器人搬运程序进行结构化整理,使其更易于理解、调试和在不…

一套视频快速入门并精通PostgreSQL

PostgreSQL从入门到精通系列PostgreSQL数据库是一个对理论知识与操作能力并重的技术,想要快速入门PostgreSQL数据库,这两个方面都要重视。这里的PostgreSQL从入门到精通,是专门针对刚入门的新手小白而录制的一套,有理论讲解也有动…

供应商管理系统有哪些功能?

在企业供应链数字化体系中,供应商管理系统是连接企业与外部合作伙伴的核心枢纽。以鲸采云采购管理系统的供应商模块为例,其功能设计围绕 “全生命周期管理 风险防控 协同效率” 三大核心,通过技术手段解决传统供应商管理中的信息碎片化、流…

新手向:国内外大模型体验与评测

国内外大模型体验与评测技术详解 近年来,人工智能领域的大模型技术取得了突破性进展,以GPT-4、Claude、文心一言等为代表的大语言模型(LLM)已经成为行业热点。国内外科技巨头纷纷布局这一赛道:国外有OpenAI的GPT系列、Anthropic的Claude、Google的PaLM,国内则有百度的文…

深度解读 CSGHub:开源协议、核心功能与产品定位

在大模型时代,“可用”不再足够,企业更需要“可管”、“可控”、“可演进”的一体化解决方案。作为国产开源阵营的中坚力量,CSGHub 如何从“开源与协议”到“功能定位”层层打磨,满足不同行业对合规、安全和灵活部署的诉求&#x…

本土化DevOps实践新篇章:Gitee引领企业高效协作新时代

本土化DevOps实践新篇章:Gitee引领企业高效协作新时代 在数字化转型的浪潮席卷全球的当下,软件开发与运维的协同效率已经成为决定企业竞争力的关键因素。随着国内企业对于数据安全和合规性的要求日益严格,寻找一套既符合本土监管要求又能提升…

B树、B+树、红黑树区别

一、核心概念与性质对比1. B树(Balanced Tree)定位:多路平衡搜索树,专为磁盘存储优化核心性质:每个节点存储 k-1个键值和k个子节点指针(m/2 ≤ k ≤ m,m为阶数)所有叶子节点位于同一…

Spring AI 使用阿里百炼平台实现流式对话:基于 SSE 的实践

Spring AI阿里百炼平台实现流式对话:基于 SSE 的实践指南 在大模型应用开发中,流式对话是提升用户体验的关键特性。本文将详细介绍如何利用 Spring AI 结合 Spring Boot,基于 SSE(Server-Sent Events)协议实现高效的流…

Ubuntu lamp

Ubuntu lamp 前言 在Ubuntu安装lamp架构 我们了解到 lamp是完整的架构 我们前面了解到了 集合了Linux系统 apache MySQL 和PHP语言的完整架构 我们前面说了Centos7中编译安装 lamp 那么 我们去说一下在Ubuntu中安装 ‍ ‍ 安装apache2 ‍ apt直接安装apache2 apt -y install a…

开源向量LLM - Qwen3-Embedding

1 Qwen3-Embedding介绍 Qwen3-Embedding遵循 Apache 2.0 许可证,模型大小从0.6B到8B,支持32k长文本编码。 Model TypeModelsSizeLayersSequence LengthEmbedding DimensionMRL SupportInstruction AwareText EmbeddingQwen3-Embedding-0.6B0.6B2832K10…