不依賴rerank 模型排序通過使用 PostgreSQL 中的 pgvector 與 tsearch2 函數進行混合搜索提高召回率

前言

在向量搜索中,召回率是一個關鍵指標,它衡量搜索結果的相關性。然而,提高召回率往往會犧牲其他指標,如索引大小或查詢延遲。為了平衡這些權衡,混合搜索技術應運而生。本文將介紹如何在 PostgreSQL 中結合 pgvector 實現混合搜索,并探討其對搜索結果的影響。

前提條件

必須使用PostgreSQL中的 pgvector 插件和 tsearch2 函數。請先檢查一下,你所使用的PostgreSQL 是否支持。

什么是混合搜索?

混合搜索是將向量相似性搜索與其他搜索方法(如全文搜索)相結合的一種技術。它通過多種搜索方法對同一數據進行搜索,對每種方法的結果進行排序,然后合并所有結果以確定最終排名。混合搜索的目標是提高搜索結果的質量,即提高召回率。

在混合搜索中,互惠排序融合(RRF)是一種常用的評分方法。RRF 通過加權評分系統,根據排名對結果進行評分。公式如下:

1.0 / (result_search_1_rank + rrf_k) +
1.0 / (result_search_2_rank + rrf_k)

其中,rrf_k 是一個常數,用于控制權重。較小的 rrf_k 值會賦予排名較高的項目更大的權重。

PostgreSQL 中的全文搜索

PostgreSQL 提供了多種全文搜索方法,如 tsearch2 和 pg_trgm,以及擴展如 pg_bigm 和 PGroonga。在本文中,我們將使用 tsearch2 函數,并結合 GIN 索引和 ts_rank_cd 結果排序方法。

示例:在 PostgreSQL 中構建混合搜索

數據準備

我們使用 Python 的 faker 庫生成隨機文本數據,并使用 multi-qa-MiniLM-L6-cos-v1 句子轉換器模型計算向量嵌入。以下是 Python 代碼:

from faker import Faker
import psycopg
from pgvector.psycopg import register_vector
from sentence_transformers import SentenceTransformerfake = Faker()
sentences = [fake.sentence(nb_words=50) for i in range(0, 50_000)]model = SentenceTransformer('multi-qa-MiniLM-L6-cos-v1')
embeddings = model.encode(sentences)conn = psycopg.connect(dbname="<YOUR DATABASE>", autocommit=True)
cur = conn.cursor()with cur.copy("COPY products (description, embedding) FROM STDIN WITH (FORMAT BINARY)") as copy:copy.set_types(["text", "vector"])for content, embedding in zip(sentences, embeddings):copy.write_row((content, embedding))cur.close()
conn.close()

數據庫設置

在 PostgreSQL 中,我們需要創建表和索引:

-- 創建擴展
CREATE EXTENSION vector;-- 創建表
CREATE TABLE products (id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,description text NOT NULL,embedding vector(384) NOT NULL
);-- 創建 RRF 評分函數
CREATE OR REPLACE FUNCTION rrf_score(rank int, rrf_k int DEFAULT 50)
RETURNS numeric
LANGUAGE SQL
IMMUTABLE PARALLEL SAFE
AS $$SELECT COALESCE(1.0 / ($1 + $2), 0.0);
$$;-- 創建全文搜索索引
CREATE INDEX ON productsUSING GIN (to_tsvector('english', description));-- 創建向量搜索索引
CREATE INDEX ON productsUSING hnsw(embedding vector_cosine_ops) WITH (ef_construction=256);

搜索實現

單獨的向量相似性搜索
SELECT id, description, rank() OVER (ORDER BY $1 <=> embedding) AS rank
FROM products
ORDER BY $1 <=> embedding
LIMIT 10;
單獨的全文搜索
SELECTid,description,rank() OVER (ORDER BY ts_rank_cd(to_tsvector(description), plainto_tsquery('travel computer')) DESC) AS rank
FROM products
WHEREplainto_tsquery('english', 'travel computer') @@ to_tsvector('english', description)
ORDER BY rank
LIMIT 10;
混合搜索
SELECTsearches.id,searches.description,sum(rrf_score(searches.rank)) AS score
FROM ((SELECTid,description,rank() OVER (ORDER BY $1 <=> embedding) AS rankFROM productsORDER BY $1 <=> embeddingLIMIT 40)UNION ALL(SELECTid,description,rank() OVER (ORDER BY ts_rank_cd(to_tsvector(description), plainto_tsquery('travel computer')) DESC) AS rankFROM productsWHEREplainto_tsquery('english', 'travel computer') @@ to_tsvector('english', description)ORDER BY rankLIMIT 40)
) searches
GROUP BY searches.id, searches.description
ORDER BY score DESC
LIMIT 10;

性能分析

通過 EXPLAIN ANALYZE,我們可以看到 PostgreSQL 在混合搜索中同時使用了向量索引和全文搜索索引。以下是執行計劃的輸出:

Limit  (cost=789.66..789.69 rows=10 width=365) (actual time=8.516..8.519 rows=10 loops=1)->  Sort  (cost=789.66..789.86 rows=80 width=365) (actual time=8.515..8.518 rows=10 loops=1)Sort Key: (sum(COALESCE((1.0 / (("*SELECT* 1".rank + 50))::numeric), 0.0))) DESCSort Method: top-N heapsort  Memory: 32kB->  GroupAggregate  (cost=785.53..787.93 rows=80 width=365) (actual time=8.435..8.495 rows=79 loops=1)Group Key: "*SELECT* 1".id, "*SELECT* 1".description->  Sort  (cost=785.53..785.73 rows=80 width=341) (actual time=8.430..8.436 rows=80 loops=1)Sort Key: "*SELECT* 1".id, "*SELECT* 1".descriptionSort Method: quicksort  Memory: 53kB->  Append  (cost=84.60..783.00 rows=80 width=341) (actual time=0.877..8.414 rows=80 loops=1)->  Subquery Scan on "*SELECT* 1"  (cost=84.60..125.52 rows=40 width=341) (actual time=0.877..0.949 rows=40 loops=1)->  Limit  (cost=84.60..125.12 rows=40 width=349) (actual time=0.876..0.945 rows=40 loops=1)->  WindowAgg  (cost=84.60..50736.60 rows=50000 width=349) (actual time=0.876..0.942 rows=40 loops=1)->  Index Scan using products_embeddings_hnsw_idx on products  (cost=84.60..49861.60 rows=50000 width=341) (actual time=0.872..0.919 rows=40 loops=1)Order By: (embedding <=> '<redacted>'::vector)->  Subquery Scan on "*SELECT* 2"  (cost=656.58..657.08 rows=40 width=341) (actual time=7.448..7.458 rows=40 loops=1)->  Limit  (cost=656.58..656.68 rows=40 width=345) (actual time=7.447..7.453 rows=40 loops=1)->  Sort  (cost=656.58..656.89 rows=124 width=345) (actual time=7.447..7.449 rows=40 loops=1)Sort Key: (rank() OVER (?))Sort Method: top-N heapsort  Memory: 44kB->  WindowAgg  (cost=588.18..652.66 rows=124 width=345) (actual time=7.357..7.419 rows=139 loops=1)->  Sort  (cost=588.18..588.49 rows=124 width=337) (actual time=7.355..7.363 rows=139 loops=1)Sort Key: (ts_rank_cd(to_tsvector(products_1.description), plainto_tsquery('travel computer'::text))) DESCSort Method: quicksort  Memory: 79kB->  Bitmap Heap Scan on products products_1  (cost=30.38..583.87 rows=124 width=337) (actual time=0.271..7.323 rows=139 loops=1)Recheck Cond: ('''travel'' & ''comput'''::tsquery @@ to_tsvector('english'::regconfig, description))Heap Blocks: exact=138->  Bitmap Index Scan on products_description_gin_idx  (cost=0.00..30.35 rows=124 width=0) (actual time=0.186..0.186 rows=139 loops=1)Index Cond: (to_tsvector('english'::regconfig, description) @@ '''travel'' & ''comput'''::tsquery)
Planning Time: 0.193 ms
Execution Time: 8.553 ms

從執行計劃可以看出,PostgreSQL 在混合搜索中同時使用了向量索引和全文搜索索引,查詢效率較高。

為什么會使用這樣的方案,rerank模型不香嗎?

我們自己使用spring ai 框架搭建的大模型應用平臺的底層推理引擎是 ollama,因此我們重度依賴ollama 所提供的推理能力,然而ollama 并不支持rerank模型的服務,為了解決召回重排的問題,在不進一步增大部署實施難度的情況下,采用了混合檢索的方案進行簡化。

其次通過架構的討論,在算力不強的環境下,能夠盡量壓榨PostgreSQL 的能力,提高召回,也是壓縮成本的一個考慮。

spring ai 官方也將提供類似方案進行重排

已經在 spring ai 1.1.x 的pull request 中有大神實現了類似的方案。
https://github.com/spring-projects/spring-ai/pull/1097

后續在我們自己平臺上的進一步使用計劃

本文展示了如何在 PostgreSQL 中結合 pgvector 實現混合搜索,并通過示例驗證了其可行性。然而,這只是一個起點。未來的工作包括:

  1. 評估混合搜索的性能:在更大的數據集上測試混合搜索的召回率、查詢延遲和每秒查詢次數(QPS),并與單獨的向量搜索進行對比。
  2. 優化參數:調整 rrf_k 等參數,以找到最佳的混合搜索策略。
  3. 探索其他全文搜索算法:分析 PostgreSQL 中不同的全文搜索算法(如 pg_trgm、pg_bigm 等)對混合搜索結果的影響。

混合搜索為提升搜索結果的相關性提供了一種有效的途徑。通過結合向量相似性搜索和全文搜索的優勢,我們可以在不顯著增加查詢延遲的情況下,提高搜索結果的召回率。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/85356.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/85356.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/85356.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Uniapp 跨平臺開發框架全面解析:一次開發,多端運行

在移動互聯網時代&#xff0c;開發者面臨著一個重要挑戰&#xff1a;如何高效地開發出能在多個平臺&#xff08;iOS、Android、Web、小程序等&#xff09;上運行的應用&#xff1f;傳統的原生開發方式需要為每個平臺單獨編寫代碼&#xff0c;導致開發周期長、維護成本高。而 Un…

ios如何把H5網頁變成主屏幕webapp應用

一、將 H5 頁面添加到主屏幕的步驟 打開 Safari 瀏覽器 在 iPhone 上打開 Safari 瀏覽器&#xff0c;訪問目標網頁&#xff08;H5 頁面&#xff09;。 點擊分享按鈕 在 Safari 瀏覽器底部點擊 “分享” 圖標&#xff08;箭頭向上的按鈕&#xff09;。 添加到主屏幕 在分享菜單…

Node.js 項目啟動命令大全 (形象版)

文章目錄 Node.js 項目啟動命令大全 &#x1f31f;?&#xff08;形象版&#xff09;一、&#x1f50d; 如何查看項目啟動命令&#xff08;魔法書目錄&#xff09;package.json scripts 參數詳解開發相關腳本測試相關腳本構建相關腳本代碼質量相關腳本最佳實踐 二、&#x1f68…

愛普特APT32F1104C8T6單片機 高抗干擾+硬件加密雙保障

愛普特APT32F1104C8T6單片機深度解析 1. 產品定位 APT32F1104C8T6 是愛普特半導體&#xff08;APT&#xff09;推出的 32位高性能經濟型單片機&#xff0c;基于 ARM Cortex-M0內核&#xff0c;采用 LQFP48封裝&#xff0c;主打 高性價比、低功耗、強抗干擾&#xff0c;是替代進…

使用uni-app ios 打包流程

配置幾個步驟即可 1、打包ios需要BundleID ID 2、證書私鑰密碼 3、信任文件證書文件 4、私鑰證書 5、打包 6、獲取打包后的ipa文件 7、通過愛思助手安裝到iso手機上 8、完成 1、下載&#xff1a;App Uploader去獲取我們想要的證書私鑰等文件 2、下載完成解壓后的文件如下打…

仿muduo庫實現并發服務器

1.實現目標 仿muduo庫One Thread One Loop式主從Reactor模型實現高并發服務器&#xff1a; 通過實現高并發服務器的組件&#xff0c;可以快速實現一個高并發服務器的搭建&#xff0c;并且&#xff0c;通過組內不同應用層協議的支持&#xff0c;可以快速完成高性能服務器的搭建…

迭代器模式:集合遍歷的統一之道

引言&#xff1a;集合遍歷的演進之路 在軟件開發中&#xff0c;集合遍歷是我們每天都要面對的基礎操作。從最初的數組索引遍歷到現代的流式處理&#xff0c;我們經歷了&#xff1a; #mermaid-svg-KwTr9k8JgbwRTDhU {font-family:"trebuchet ms",verdana,arial,sans-…

Spring Security OAuth2 組件

我們來系統地講解一下 Spring Security OAuth2 這個強大的組件。我會從概念、作用、核心組件&#xff0c;以及實際應用場景來為你剖析。 1. 什么是 Spring Security OAuth2&#xff1f; 簡單來說&#xff0c;Spring Security OAuth2 是 Spring Security 框架的一個模塊&#…

Redis的持久化功能

Redis的持久化功能能夠將內存中的數據保存到磁盤&#xff0c;從而在重啟后恢復數據。下面為你詳細介紹Redis的兩種主要持久化方式及其配置方法。 RDB&#xff08;Redis Database&#xff09;持久化 RDB持久化是通過生成某個時間點的數據集快照來實現的。它具有高性能的特點&a…

Chrome 將成為下一個 IE6

最近在技術圈刷到一個帖子&#xff0c;說&#xff1a;“Chrome 就快變成新的 IE6 了。” 乍一看有點危言聳聽&#xff0c;但你一細品&#xff0c;發現還真挺像回事。 想當年&#xff1a;IE6 是怎么垮的&#xff1f; IE6 當年多風光&#xff1f;全球市場份額一度超過 90%&#…

Redis 配置文件詳解redis.conf 從入門到實戰

一、redis.conf 是什么&#xff1f; Redis 的配置文件&#xff08;默認命名為 redis.conf&#xff0c;Redis 8.0 之后改為 redis-full.conf&#xff09;控制著服務運行的各項參數。該文件采用以下結構&#xff1a; 指令名 參數1 參數2 ... 參數N例如&#xff1a; replicaof …

autoware docker的安裝

前言 官方的安裝說明&#xff1a; 官方的安裝說明 安裝前&#xff0c;請確認安裝的硬件&#xff1a; CPU with 8 cores16GB RAM[Optional] NVIDIA GPU (4GB RAM) 滿足需求 1. 安裝軟件依賴 這一步主要是安裝三個軟件&#xff1a; DockerNVIDIA Container Toolkit (pref…

AWS 解決方案深度剖析:Amazon QLDB — 構建可信賴、不可變的數據審計基石

導言&#xff1a;數據可信的挑戰 在現代應用開發中&#xff0c;尤其是在金融、供應鏈、身份認證、政府事務、醫療記錄管理等領域&#xff0c;數據完整性和歷史追溯性至關重要。我們常常面臨以下挑戰&#xff1a; 審計困難&#xff1a; 如何證明數據從誕生至今未被篡改&#xf…

Leetcode-?1358. 包含所有三種字符的子字符串數目?

Problem: 1358. 包含所有三種字符的子字符串數目 思路 滑動窗口 解題過程 滑動窗口&#xff1a;使用左右指針 l 和 r 維護一個窗口&#xff0c;窗口內字符的頻次由 cnt 記錄。 右指針擴展&#xff1a;右指針 r 不斷右移&#xff0c;將字符加入窗口并更新頻率。 左指針收縮&a…

iTunes 無法備份 iPhone:10 種解決方法

Apple 設備是移動設備市場上最先進的產品之一&#xff0c;但有些人遇到過 iTunes 因出現錯誤而無法備份 iPhone 的情況。iTunes 拒絕備份 iPhone 時&#xff0c;可能會令人非常沮喪。不過&#xff0c;幸運的是&#xff0c;我們有 10 種有效的方法可以解決這個問題。您可以按照以…

Unity 接入抖音小游戲一

目錄 一、搭建小游戲環境 二、接入抖音SDK 1.初始化 2.登錄 3.分享 4.添加到桌面 5.側邊欄功能 6. 接入流量主 三、完整代碼 下一篇傳送門 Unity 接入抖音小游戲二 -CSDN博客 一、搭建小游戲環境 我這邊因為沒有下載其他版本的Unity所以就先用2022.3.57f1了 大家還是下載…

Node.js 項目啟動命令全面指南:從入門到精通(術語版)

文章目錄 Node.js 項目啟動命令全面指南&#xff1a;從入門到精通一、核心啟動命令深度解析1. 基礎命令結構與執行機制2. 參數傳遞機制詳解 二、常用命令分類詳解1. 運行環境命令對比2. 質量保障命令詳解3. 構建部署全流程 三、高級配置實戰技巧1. 環境變量管理進階2. 命令組合…

創意風格行業PPT模版分享

極簡主題PPT模版&#xff0c;設計類PPT模版&#xff0c;快樂童年成長PPT模版&#xff0c;教育機構通用PPT模版&#xff0c;創意風格行業PPT模版 創意風格行業PPT模版分享&#xff1a;https://pan.quark.cn/s/3bac52e09479

Java + Spring Boot + MyBatis 枚舉變量傳遞給XML映射文件做判斷

枚舉定義 ReagentStatus.java package com.weiyu.utils.enums;import lombok.Getter;/*** 試劑狀態枚舉*/ Getter public enum ReagentStatus {// 常規REGULAR,// 少庫存LESS_INVENTORY,// 零庫存ZERO_INVENTORY,// 將過期WILL_EXPIRE,// 已過期EXPIRED,// 已注銷LOGGED,// 全…

華為云Flexus+DeepSeek征文 | 華為云CCE容器高可用部署Dify高可用版實測:從0到1的高可靠應用實踐

引言 隨著大語言模型&#xff08;LLM&#xff09;技術的爆發&#xff0c;如何快速構建具備高可用、彈性擴展能力的AI應用開發平臺&#xff0c;成為企業數字化轉型的關鍵命題。華為云依托其云原生基礎設施&#xff0c;推出CCE容器高可用版Dify部署方案&#xff0c;通過“一鍵部…