大模型向量去重的N種解決方案!
簡單來說,“向量”Vector 是大模型(LLM)在搜索時使用的一種“技術手段”,通過向量比對,大模型能找出問題的相關答案,并且進行智能回答。
向量簡介
Vector 是向量或矢量的意思,向量是數學里的概念,而矢量是物理里的概念,但二者描述的是同一件事。
“
定義:向量是用于表示具有大小和方向的量。
向量可以在不同的維度空間中定義,最常見的是二維和三維空間中的向量,但理論上也可以有更高維的向量。例如,在二維平面上的一個向量可以寫作 (x,y),這里 x 和 y 分別表示該向量沿兩個坐標軸方向上的分量;而在三維空間里,則會有一個額外的 z 坐標,即 (x,y,z)。
例如,有以下 4 種狗,我們要在大模型中如何表示它們呢:
我們就可以使用向量來表示,如下圖所示:
向量關系圖:
向量數據庫
定義:向量數據庫是一種專門用于存儲、管理和檢索向量數據(即高維數值數組)的數據庫系統。其核心功能是通過高效的索引結構和相似性計算算法,支持大規模向量數據的快速查詢與分析。
向量數據庫以向量為基本存儲單元,這些向量通常由文本、圖像、音頻等非結構化數據通過深度學習模型(如 Embedding 技術)轉換而來,每個向量代表對象在多維空間中的特征。例如,一段文本可轉化為 512 維的浮點數向量,用于表示其語義信息。
“
向量數據庫維度越高,查詢精準度也越高,查詢效果也越好。
常用向量數據庫
Java 領域常用的向量數據庫有:
- Redis Stack:原有 Redis 服務升級之后就可以用來存儲向量數據。
- Elastic Search
- Milvus:一款開源的高性能向量數據庫,專為存儲、索引和檢索大規模向量數據而設計。它可以實現萬億級向量的毫秒級相似性搜索。
向量數據去重
向量數據庫去重通常是在添加時進行判斷,它主要實現方式有以下幾種:
- 基于向量相似度去重。
- 基于 Redis 唯一鍵去重。
- 使用 Redis SetNX 去重。
- 基于 Redis Set 數據結構去重。
具體實現如下。
1.基于向量相似度去重
原理:在插入前計算新向量與已有向量的余弦相似度,若超過閾值(如 0.95)則視為重復。
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
.queryEmbedding(newEmbedding)
.maxResults(1)
.minScore(0.95) // 相似度閾值
.build();
List<EmbeddingMatch<TextSegment>> matches = embeddingStore.search(request);
if (matches.isEmpty()) {
embeddingStore.add(newEmbedding, textSegment);
}
優點:語義級去重,適合文本內容相似但表述不同的場景。
缺點:存在線程安全問題,多任務同時執行,可能導致插入重復數據。
2.基于 Redis 唯一鍵去重
原理:使用文本內容的哈希值(如 MD5)作為 Redis Key 的一部分,確保唯一性。
String textHash = DigestUtils.md5Hex(textSegment.text());
String redisKey = "embedding:" + textHash;
if (!redisTemplate.hasKey(redisKey)) {
embeddingStore.add(newEmbedding, textSegment);
redisTemplate.opsForValue().set(redisKey, "1");
}
優點:性能高,適合完全相同的文本內容。
缺點:存在線程安全問題,多任務同時執行,可能導致插入重復數據。
3.使用 Redis SetNX 去重
原理:使用 Redis 的 SETNX(set if not exists)命令,避免非原子性問題,它是先判斷才插入,如果已經存在就不再插入了。
具體實現代碼如下:
// 生成文本的唯一哈希(如 MD5)
String textHash = DigestUtils.md5Hex(textSegment.text());
String redisKey = "vector:" + textHash;
// 判斷是否存在
Boolean isSet = redisTemplate.opsForValue()
.setIfAbsent(redisKey, "1");
if (Boolean.TRUE.equals(isSet)) {
// 鍵不存在,保存向量數據
embeddingStore.add(embedding, textSegment);
} else {
// 鍵已存在,跳過或報錯
throw new RuntimeException("重復數據");
}
優點:性能高,不存在線程安全問題。
4.基于 Redis Set 數據結構去重
原理:Set 去重,將向量 ID 或文本哈希存入 Redis Set,插入前檢查是否存在。
// 生成文本的唯一哈希(如 MD5)
String textHash = DigestUtils.md5Hex(textSegment.text());
if (redisTemplate.opsForSet().add("unique_embeddings", textHash) == 1) {
embeddingStore.add(newEmbedding, textSegment);
}
優點:簡單高效,不存在線程安全問題。
缺點:需維護額外的 Set 數據結構。
小結
向量數據庫去重一定是生產環境要做的事,它的解決方案也有很多,通常我們會選擇一種高效、且沒有線程安全的解決方案,例如 Redis SetNX 或 Set 數據結構來解決。