Microsoft.Extensions.VectorData 函式庫在其向量儲存抽象中提供向量搜尋功能。 這些功能包括過濾及其他多種選項。
向量搜尋
此 SearchAsync 方法執行相似度搜尋,回傳向量特性與指定值最相似的紀錄。 假設你已經有一個包含資料的集合,這裡有一個使用 Qdrant 進行向量搜尋的最小範例:
// Create a Qdrant VectorStore object and get a VectorStoreCollection for a collection that already contains records
VectorStore vectorStore = new QdrantVectorStore(new QdrantClient("localhost"), ownsClient: true);
VectorStoreCollection<ulong, Hotel> collection = vectorStore.GetCollection<ulong, Hotel>("skhotels");
// Get the 3 hotels whose vector property is most similar to the query text
IAsyncEnumerable<VectorSearchResult<Hotel>> results = collection.SearchAsync("Big rooms with a view", top: 3);
// Inspect the returned hotels and their similarity scores
await foreach (VectorSearchResult<Hotel> record in results)
{
Console.WriteLine("Found hotel description: " + record.Record.Description);
Console.WriteLine("Found record score: " + record.Score);
}
欲了解更多嵌入生成的資訊,請參見 向量性質與嵌入生成。
結果數量與跳過結果
SearchAsync 有一個強制 top 參數,控制搜尋回傳的最大紀錄數量。 務必考慮實際需要多少頂尖紀錄,因為過度取數據會降低應用程式效能:
IAsyncEnumerable<VectorSearchResult<Hotel>> searchResult = collection.SearchAsync("Big rooms with a view", top: 3);
此外,你也可以選擇跳過紀錄。 例如,以下搜尋跳過40個後,會回傳20個最相關的產品:
IAsyncEnumerable<VectorSearchResult<Product>> results = collection.SearchAsync(
"Green socks",
top: 20,
new() { Skip = 40 });
top 和 Skip 可以用於分頁,以透過分別的呼叫來取得大量結果。 然而,這種技術在資料庫上可能表現不佳,因為它仍需尋找並處理跳過的紀錄。 欲了解更多資訊,請參閱您的資料庫文件。
元資料過濾
在應用向量搜尋前,請先使用 VectorSearchOptions<TRecord>.Filter 篩選所選集合中的紀錄選項。 這有多重好處:
- 降低延遲與處理成本,因為只有過濾後剩餘的紀錄需要與搜尋向量比較,因此所需的向量比較次數較少。
- 限制結果集集合。 例如,您可以透過排除使用者不應該存取的資料來實作存取控制,或只在特定類別的產品內搜尋。
為了用於篩選,許多向量儲存器要求先將這些欄位索引。 欲了解更多如何啟用資料屬性索引的資訊,請參見 資料屬性。
篩選器會根據資料模型類型,使用 LINQ 表達式來表示。 支援的 LINQ 表達式集合會依據各資料庫所支援的功能而異,但所有資料庫都支援廣泛的常用表達式,例如 equals、not equals、 and、 or和 。
class Glossary
{
// ...
// Category is marked as indexed, since you want to filter using this property.
[VectorStoreData(IsIndexed = true)]
public required string Category { get; set; }
// Tags is marked as indexed, since you want to filter using this property.
[VectorStoreData(IsIndexed = true)]
public required List<string> Tags { get; set; }
}
IAsyncEnumerable<VectorSearchResult<Glossary>> results = collection.SearchAsync(
"Some term",
top: 3,
new()
{
Filter = r => r.Category == "External Definitions" && r.Tags.Contains("memory")
});
在結果中包含向量
預設情況下,向量屬性不會包含在搜尋結果中,這會減少資料傳輸。 你可以設定搜尋內容以包含:
IAsyncEnumerable<VectorSearchResult<Product>> results = collection.SearchAsync(
"Green socks",
top: 3,
new() { IncludeVectors = true });
指定向量性質
在大多數情況下,資料模型中只定義單一向量屬性,並 SearchAsync 自動針對該屬性進行搜尋。 然而,當定義多個向量性質時,你必須指定應該使用哪一種:
class Product
{
// ...
// Multiple vector properties:
[VectorStoreVector(1536)]
public ReadOnlyMemory<float> DescriptionEmbedding { get; set; }
[VectorStoreVector(1536)]
public ReadOnlyMemory<float> FeatureListEmbedding { get; set; }
}
IAsyncEnumerable<VectorSearchResult<Hotel>> results = collection.SearchAsync(
"I'm looking for a product with a specific feature.",
top: 3,
new() { VectorProperty = r => r.FeatureListEmbedding });
混合式搜尋
混合式搜尋結合向量相似度搜尋與傳統關鍵字搜尋,兩者同時執行並回傳兩種結果組合。 這能提升搜尋品質,因為關鍵字匹配能捕捉到向量相似度可能錯過的精確詞彙匹配,反之亦然。
備註
混合式搜尋僅在支援它的資料庫中提供。 只有這些資料庫的提供者實作該 IKeywordHybridSearchable<TRecord> 介面。
要使用混合式搜尋,您的資料模型需要一個已通過 IsFullTextIndexed 啟用全文搜尋的字串欄位。
class Hotel
{
[VectorStoreKey]
public ulong Key { get; set; }
[VectorStoreData(IsFullTextIndexed = true)]
public required string Description { get; set; }
[VectorStoreVector(1536)]
public string DescriptionEmbedding { get; set; }
}
接著呼叫 HybridSearchAsync,傳遞搜尋文字和關鍵字:
var hybridCollection = (IKeywordHybridSearchable<Hotel>)collection;
IAsyncEnumerable<VectorSearchResult<Hotel>> results = hybridCollection.HybridSearchAsync(
"I'm looking for a hotel where customer happiness is the priority.",
["happiness", "hotel", "customer"],
top: 3);
所有描述的向量搜尋選項(top, Skip, FilterIncludeVectors, , VectorProperty)也可用於混合搜尋。HybridSearchOptions<TRecord>
此外,混合式搜尋支援 AdditionalProperty 指定要鎖定的全文搜尋屬性的選項。 如果你的資料模型只有一個屬性且 IsFullTextIndexed = true,則會自動使用;如果有多個屬性,你必須指定是哪一個:
IAsyncEnumerable<VectorSearchResult<Hotel>> results = hybridCollection.HybridSearchAsync(
"I'm looking for a hotel where customer happiness is the priority.",
["happiness", "hotel", "customer"],
top: 3,
new()
{
VectorProperty = r => r.DescriptionEmbedding,
AdditionalProperty = r => r.Description
});