RAGFlow Agent 知識檢索節點源碼解析:從粗排到精排的完整流程

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…