向量搜尋

隨著生成式 AI 的興起,向量資料庫在資料庫世界中獲得了強大的關注。這些資料庫能夠高效地儲存和查詢高維向量,使其非常適合語義搜尋、推薦系統和自然語言理解等任務。

向量搜尋是一種透過比較向量表示(也稱為嵌入)而非依賴傳統精確匹配查詢來檢索語義相似資料的技術。這種方法支援智慧的、上下文感知的應用程式,超越了基於關鍵詞的檢索。

在 Spring Data 的上下文中,向量搜尋為構建智慧的、上下文感知的應用程式開闢了新的可能性,尤其是在自然語言處理、推薦系統和生成式 AI 等領域。透過使用熟悉的倉庫抽象對基於向量的查詢進行建模,Spring Data 允許開發人員以 Spring Data 程式設計模型的簡潔性和一致性無縫整合基於相似度的向量資料庫。

要使用 MongoDB 的向量搜尋,您需要一個 MongoDB Atlas 例項,該例項可以在雲端執行,或者透過使用 Docker 執行。

向量模型

為了以型別安全和慣用的方式支援向量搜尋,Spring Data 引入了以下核心抽象

Vector

Vector 型別表示 n 維數值嵌入,通常由嵌入模型生成。在 Spring Data 中,它被定義為浮點數陣列的輕量級包裝器,確保不變性和一致性。此型別可用作搜尋查詢的輸入,或作為域實體上的屬性來儲存關聯的向量表示。

Vector vector = Vector.of(0.23f, 0.11f, 0.77f);

在域模型中使用 Vector 消除了使用原始陣列或數字列表的需要,提供了一種更型別安全和富有表現力的方式來處理向量資料。這種抽象還允許輕鬆整合各種向量資料庫和庫。它還允許實現供應商特定的最佳化,例如不對映到標準浮點數(根據 IEEE 754floatdouble)表示的二進位制或量化向量。域物件可以具有向量屬性,可用於相似性搜尋。請看以下示例

class Comment {

  @Id String id;
  String country;
  String comment;

  Vector embedding;

  // getters, setters, …
}
將向量與域物件關聯會導致向量作為實體生命週期的一部分被載入和儲存,這可能會增加檢索和持久化操作的額外開銷。

搜尋結果

SearchResult<T> 型別封裝了向量相似性查詢的結果。它包括匹配的域物件和表示其與查詢向量匹配程度的相關性分數。這種抽象提供了一種結構化的方式來處理結果排名,並使開發人員能夠輕鬆處理資料及其上下文相關性。

示例 1. 在儲存庫搜尋方法中使用 SearchResult<T>
interface CommentRepository extends Repository<Comment, String> {

  @VectorSearch(indexName = "my-index", numCandidates="#{#limit.max() * 20}")
  SearchResults<Comment> searchByCountryAndEmbeddingNear(String country, Vector vector, Score score,
    Limit limit);

  @VectorSearch(indexName = "my-index", limit="10", numCandidates="200")
  SearchResults<Comment> searchByCountryAndEmbeddingWithin(String country, Vector embedding,
      Score score);

}

SearchResults<Comment> results = repository.searchByCountryAndEmbeddingNear("en", Vector.of(…), Score.of(0.9), Limit.of(10));

MongoDB 向量搜尋聚合 階段定義了一組必需的引數和限制。請務必遵循指南,並確保提供諸如 limit 等必需引數。

在此示例中,searchByCountryAndEmbeddingNear 方法返回一個 SearchResults<Comment> 物件,其中包含一個 SearchResult<Comment> 例項列表。每個結果都包括匹配的 Comment 實體及其相關性得分。

相關性分數是一個數值,表示匹配向量與查詢向量的匹配程度。根據分數是表示距離還是相似度,更高的分數可能意味著更接近的匹配或更遠的匹配。

用於計算此分數的評分函式可以根據底層資料庫、索引或輸入引數而變化。

分數、相似度和評分函式

Score 型別儲存一個數值,表示搜尋結果的相關性。它可用於根據搜尋結果與查詢向量的相似性對結果進行排名。Score 型別通常是浮點數,其解釋(越高越好或越低越好)取決於所使用的特定相似性函式。分數是向量搜尋的副產品,並非成功搜尋操作所必需。分數值不屬於域模型,因此最好表示為帶外資料。

通常,分數由 ScoringFunction 計算。用於計算此分數的實際評分函式可能取決於底層資料庫,並且可以從搜尋索引或輸入引數中獲取。

Spring Data 支援為常用函式宣告常量,例如

歐幾里得距離

計算 n 維空間中的直線距離,涉及平方差之和的平方根。

餘弦相似度

透過首先計算點積,然後將其結果除以它們的長度之積進行歸一化來測量兩個向量之間的角度。

點積

計算元素乘法之和。

相似性函式的選擇會影響搜尋的效能和語義,並且通常由所使用的底層資料庫或索引決定。Spring Data 適應資料庫的本機評分函式功能以及分數是否可用於限制結果。

MongoDB 直接將分數報告為相似度值。評分函式必須在索引中指定,因此,向量搜尋方法不考慮 Score.scoringFunction。由於搜尋結果中沒有關於分數如何計算的資訊,評分函式預設為 ScoringFunction.unspecified()

示例 2. 在儲存庫搜尋方法中使用 ScoreSimilarity
interface CommentRepository extends Repository<Comment, String> {

  @VectorSearch(…)
  SearchResults<Comment> searchTop10ByEmbeddingNear(Vector vector, Score similarity);

  @VectorSearch(…)
  SearchResults<Comment> searchTop10ByEmbeddingNear(Vector vector, Similarity similarity);

  @VectorSearch(…)
  SearchResults<Comment> searchTop10ByEmbeddingNear(Vector vector, Range<Similarity> range);
}

repository.searchByEmbeddingNear(Vector.of(…), Score.of(0.9));                (1)

repository.searchByEmbeddingNear(Vector.of(…), Similarity.of(0.9));           (2)

repository.searchByEmbeddingNear(Vector.of(…), Similarity.between(0.5, 1));   (3)
1 執行搜尋並返回相似度為 0.9 或更高的結果。
2 返回相似度為 0.9 或更高的結果。
3 返回相似度介於 0.51.0 之間的結果。

向量搜尋方法

向量搜尋方法使用與標準 Spring Data 查詢方法相同的約定在儲存庫中定義。這些方法返回 SearchResults<T> 並需要一個 Vector 引數來定義查詢向量。實際實現取決於底層資料儲存的實際內部結構及其向量搜尋功能。

如果您不熟悉 Spring Data 儲存庫,請務必熟悉儲存庫定義和查詢方法的基礎知識

通常,您可以選擇使用兩種方法宣告搜尋方法

  • 查詢派生

  • 宣告基於字串的查詢

向量搜尋方法必須宣告一個 Vector 引數來定義查詢向量。

派生搜尋方法

派生搜尋方法使用方法名來派生查詢。向量搜尋支援以下關鍵詞在宣告搜尋方法時執行向量搜尋

表 1. 查詢謂詞關鍵詞
邏輯關鍵字 關鍵字表達式

NEAR

Near, IsNear

WITHIN

Within, IsWithin

MongoDB 搜尋方法必須使用 @VectorSearch 註解來定義 $vectorSearch 聚合階段的索引名稱。

示例 3. 在儲存庫搜尋方法中使用 NearWithin 關鍵詞
interface CommentRepository extends Repository<Comment, String> {

  @VectorSearch(indexName = "my-index", numCandidates="200")
  SearchResults<Comment> searchTop10ByEmbeddingNear(Vector vector, Score score);

  @VectorSearch(indexName = "my-index", numCandidates="200")
  SearchResults<Comment> searchTop10ByEmbeddingWithin(Vector vector, Range<Similarity> range);

  @VectorSearch(indexName = "my-index", numCandidates="200")
  SearchResults<Comment> searchTop10ByCountryAndEmbeddingWithin(String country, Vector vector, Range<Similarity> range);
}

派生搜尋方法可以定義領域模型屬性來為索引欄位建立預過濾器。

派生搜尋方法通常更容易閱讀和維護,因為它們依賴方法名來表達查詢意圖。但是,派生搜尋方法需要宣告一個 ScoreRange<Score>ScoreFunction 作為 Near/Within 關鍵詞的第二個引數,以透過分數限制搜尋結果。

註解搜尋方法

註解方法提供對查詢語義和引數的完全控制。與派生方法不同,它們不依賴於方法名約定。

帶註解的搜尋方法使用 @VectorSearch 註解來定義 $vectorSearch 聚合階段的引數。

示例 4. 使用 @VectorSearch 搜尋方法
interface CommentRepository extends Repository<Comment, String> {

  @VectorSearch(indexName = "cos-index", filter = "{country: ?0}", limit="100", numCandidates="2000")
  SearchResults<Comment> searchAnnotatedByCountryAndEmbeddingWithin(String country, Vector embedding,
      Score distance);

  @VectorSearch(indexName = "my-index", filter = "{country: ?0}", limit="?3", numCandidates = "#{#limit * 20}",
				searchType = VectorSearchOperation.SearchType.ANN)
  List<Comment> findAnnotatedByCountryAndEmbeddingWithin(String country, Vector embedding, Score distance, int limit);
}

帶註解的搜尋方法可以定義 filter 用於預過濾。

filterlimitnumCandidates 支援值表示式,允許引用搜索方法引數。

透過對實際查詢的更多控制,Spring Data 可以對查詢及其引數做出更少的假設。例如,Similarity 歸一化使用查詢中的原生評分函式將給定相似度歸一化為評分謂詞值,反之亦然。如果註解查詢未定義,例如,分數,則返回的 SearchResult<T> 中的分數將為零。

排序

預設情況下,搜尋結果按其分數排序。您可以使用 Sort 引數覆蓋排序。

示例 5. 在儲存庫搜尋方法中使用 Sort
interface CommentRepository extends Repository<Comment, String> {

  SearchResults<Comment> searchByEmbeddingNearOrderByCountry(Vector vector, Score score);

  SearchResults<Comment> searchByEmbeddingWithin(Vector vector, Score score, Sort sort);
}

請注意,自定義排序不允許將分數表示為排序條件。您只能引用域屬性。

© . This site is unofficial and not affiliated with VMware.