博客 / 詳情

返回

🚀 RAG 系統檢索不準?是時候引入「離線精排」思維了!

很多同學在做 RAG(檢索增強生成)項目時,都會遇到一個頭疼的問題:向量檢索召回的內容經常“文不對題”,導致大模型回答出現幻覺。今天我們就來聊聊如何通過 Rerank(精排)技術,讓你的 RAG 系統脱胎換骨。

大家好,我是王中陽。

最近在 我們AI就業陪跑訓練營 裏,有不少同學問我:“我的 RAG 系統明明把文檔切好了,向量庫也建好了,為什麼用户問問題時,找出來的文檔還是不準?”

其實,這是傳統 RAG 架構中一個非常經典的問題。今天這篇文,我就帶大家深入理解“粗排”與“精排”,並手把手教你在 Golang 項目中引入 Rerank 機制。


1. 為什麼向量檢索還不夠?

在標準的 RAG 流程中,我們通常使用向量檢索(Vector Search)來尋找相關文檔。

它的工作原理是:

  1. 把用户問題(Query)變成向量。
  2. 把文檔塊(Chunk)變成向量。
  3. 計算兩個向量的餘弦相似度,取 Top K。

這種方法叫 Bi-Encoder 架構。它的最大優勢是(億級數據毫秒級響應),但缺點也很明顯:它丟失了細粒度的語義交互

舉個例子:

  • Query: "Python 怎麼調用 C++ 的動態庫?"
  • Doc A: "Python 調用 C++ 動態庫的詳細教程..." (強相關)
  • Doc B: "C++ 調用 Python 腳本的方法..." (不相關,但關鍵詞高度重合)

在向量空間中,Doc B 因為包含大量相同的關鍵詞(Python, C++, 調用),其向量距離可能和 Query 非常近,導致被錯誤召回。

這時候,大模型拿到的上下文是 Doc B,它自然就回答不出正確答案,甚至開始“一本正經地胡説八道”。

2. 什麼是 Rerank(精排)?

為了解決這個問題,我們需要引入第二階段:Rerank(重排序)

這就好比招聘:

  • 向量檢索(粗排):HR 快速篩選簡歷。只要簡歷裏有“Golang”、“3年經驗”這些關鍵詞,就先撈出來。這一步要快,可能撈出 100 份簡歷。
  • Rerank(精排):面試官進行深度面試。面試官會仔細閲讀簡歷的每一個項目經驗,甚至進行面對面交流。這一步比較慢,但非常精準,最終只選出最匹配的 3 個人。

在技術上,Rerank 通常使用 Cross-Encoder 架構。它將 Query 和 Document 同時輸入到模型中,讓模型逐字逐句地對比兩者的關係,輸出一個相關性得分(Score)。

一圖勝千言

  • 左邊的 Bi-encoder(雙塔編碼器) 正是向量檢索的核心架構:它會分別將輸入 A、B 編碼成獨立的向量,再通過餘弦相似度計算匹配度。

    • 這種方式可以預計算文檔向量並存儲在向量數據庫中,適合大規模、高效率的召回(即向量檢索)。
  • 右邊的 Cross-encoder(交叉編碼器) 是 Rerank(重排)的常用模型:它將輸入 A、B 拼接後一起編碼,直接輸出相關性分數,能捕捉文本間的細粒度交互。

    • 精度更高,但速度慢,適合對向量檢索得到的候選集進行精準重排序(即 Rerank)。

3. RAG 進階架構:Retrieve + Rerank

加入 Rerank 後,我們的 RAG 流程變成了這樣:

  1. Retrieval (粗排) :使用向量檢索,快速召回 Top 50 個候選文檔。
  2. Rerank (精排) :使用 Cross-Encoder 模型,對這 50 個文檔進行精細打分。
  3. Filter: 截取得分最高的 Top 5。
  4. Generation: 將這 Top 5 餵給大模型生成答案。

雖然 Rerank 增加了一點點延遲(通常幾十毫秒),但它能帶來質的飛躍。實驗數據表明,加入 Rerank 後,RAG 系統的檢索準確率(MRR/NDCG)通常能提升 10%~20%

4. 實戰:在 Golang 中接入 Rerank

目前市面上有很多優秀的 Rerank 模型,比如 BGE-Reranker(開源最強)、Cohere Rerank(商業閉源效果好)。

這裏我們以 Cohere Rerank 為例,看看在 Golang 中怎麼寫代碼。

首先,你需要申請一個 Cohere 的 API Key(註冊送額度)。

package main

import (
    "context"
    "fmt"
    "log"

    cohere "github.com/cohere-ai/cohere-go/v2"
    cohereclient "github.com/cohere-ai/cohere-go/v2/client"
)

func main() {
    // 1. 初始化客户端
    client := cohereclient.NewClient(cohereclient.WithToken("YOUR_API_KEY"))

    // 2. 模擬粗排召回的文檔 (這裏包含了相關和不相關的)
    docs := []*string{
        ptr("Golang 是一種靜態強類型語言,性能優異。"),
        ptr("Python 是一種解釋型語言,適合數據分析。"),
        ptr("Java 的生態系統非常龐大。"),
        ptr("Go 語言的併發模型基於 Goroutine 和 Channel。"), // 強相關
    }

    // 3. 用户問題
    query := "Go 語言的併發優勢是什麼?"

    // 4. 調用 Rerank 接口
    resp, err := client.Rerank(context.TODO(), &cohere.RerankRequest{
        Model:     ptr("rerank-multilingual-v2.0"), // 支持多語言的模型
        Query:     query,
        Documents: docs,
        TopN:      ptr(3), // 只取前 3 名
    })
    if err != nil {
        log.Fatal(err)
    }

    // 5. 打印結果
    fmt.Printf("用户問題: %s\n", query)
    fmt.Println("--------------------------------------------------")
    for _, result := range resp.Results {
        docContent := *docs[result.Index]
        fmt.Printf("排名: %d | 得分: %.4f | 內容: %s\n", result.Index, result.RelevanceScore, docContent)
    }
}

func ptr[T any](v T) *T { return &v }

運行結果預期:

即便粗排時混入了很多不相關的文檔,Rerank 也能把最相關的 "Go 語言的併發模型基於 Goroutine 和 Channel。" 準確地排到第一名,並且給出一個很高的相關性得分。

5. 什麼時候需要“離線”精排?

標題裏提到了“離線精排”,這通常指的是在對檢索質量要求極高,或者模型私有化部署的場景。

如果你的數據非常敏感(不能發給 Cohere/OpenAI),或者你想追求極致的性價比,你可以選擇離線部署 BGE-Reranker 模型

你可以使用 Python 的 sentence-transformers 庫加載 BGE 模型,將其封裝成一個 HTTP 服務,供 Golang 業務層調用。這樣既保證了數據安全,又節省了 API 費用。

總結

RAG 系統不是簡單的“向量庫 + 大模型”。要想效果好,Rerank 是必不可少的一環

它就像一個嚴謹的“安檢員”,把那些濫竽充數的文檔擋在門外,只把最精華的內容送給大模型。

如果你現在的 RAG 系統效果卡在瓶頸期,不妨試試加上 Rerank,相信會給你帶來驚喜!


最後

如果你對 RAG 技術感興趣,或者在做 AI 應用落地時遇到了坑,歡迎瞭解 我們的AI就業陪跑訓練營。在這裏,我們不僅有全套的 Golang AI 實戰課程(從零手寫 RAG、Agent、微調),還有一羣志同道合的夥伴一起交流。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.