Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La Microsoft.Extensions.VectorData libreria fornisce funzionalità di ricerca vettoriale come parte delle astrazioni dell'archivio vettoriale. Queste funzionalità includono il filtro e molte altre opzioni.
Suggerimento
Per informazioni su come eseguire ricerche senza generare incorporamenti manualmente, vedere Consentire all'archivio vettoriale di generare incorporamenti.
Ricerca vettoriale
Il SearchAsync metodo consente di eseguire ricerche usando dati già vettorializzati. Questo metodo accetta un vettore e una classe facoltativa VectorSearchOptions<TRecord> come input. SearchAsync è disponibile nei tipi seguenti:
Si noti che VectorStoreCollection<TKey,TRecord> implementa IVectorSearchable<TRecord>.
Supponendo di avere una raccolta che contiene già dati, è possibile cercarli facilmente. Di seguito è riportato un esempio di uso di Qdrant.
public async Task SearchAsync()
{
// Create a Qdrant VectorStore object and choose
// an existing collection that already contains records.
VectorStore vectorStore = new QdrantVectorStore(new QdrantClient("localhost"), ownsClient: true);
VectorStoreCollection<ulong, Hotel> collection =
vectorStore.GetCollection<ulong, Hotel>("skhotels");
// Generate a vector for your search text, using
// your chosen embedding generation implementation.
ReadOnlyMemory<float> searchVector =
await GenerateAsync("I'm looking for a hotel where customer happiness is the priority.");
// Do the search, passing an options object with
// a Top value to limit results to the single top match.
IAsyncEnumerable<VectorSearchResult<Hotel>> searchResult =
collection.SearchAsync(searchVector, top: 1);
// Inspect the returned hotel.
await foreach (VectorSearchResult<Hotel> record in searchResult)
{
Console.WriteLine("Found hotel description: " + record.Record.Description);
Console.WriteLine("Found record score: " + record.Score);
}
}
Suggerimento
Per altre informazioni su come generare incorporamenti, vedere Generazione di incorporamenti.
Eseguire ricerche con incorporamenti generati automaticamente
Se hai configurato un IEmbeddingGenerator<TInput,TEmbedding> nel tuo archivio vettoriale o nella raccolta, puoi passare direttamente string a SearchAsync anziché un vettore precomputato. L'archivio vettoriale genera automaticamente l'incorporamento della ricerca:
public async Task SearchWithAutoEmbeddingAsync()
{
// If an IEmbeddingGenerator is configured on the vector store or collection,
// you can pass a string directly to SearchAsync. The store generates
// the search embedding for you.
VectorStore vectorStore = new QdrantVectorStore(new QdrantClient("localhost"), ownsClient: true);
VectorStoreCollection<ulong, Hotel> collection =
vectorStore.GetCollection<ulong, Hotel>("skhotels");
// Pass the search text directly — no manual embedding generation required.
IAsyncEnumerable<VectorSearchResult<Hotel>> searchResult =
collection.SearchAsync("I'm looking for a hotel where customer happiness is the priority.", top: 1);
await foreach (VectorSearchResult<Hotel> record in searchResult)
{
Console.WriteLine("Found hotel description: " + record.Record.Description);
Console.WriteLine("Found record score: " + record.Score);
}
}
Per informazioni su come configurare un generatore di incorporamento nell'archivio vettoriale, vedere Consentire all'archivio vettoriale di generare incorporamenti.
Tipi di vettore supportati
SearchAsync accetta un tipo generico come parametro vector. I tipi di vettori supportati da ogni archivio dati variano.
È anche importante che il tipo di vettore di ricerca corrisponda al vettore di destinazione in cui viene eseguita la ricerca, ad esempio se si dispone di due vettori nello stesso record con tipi di vettore diversi, assicurarsi che il vettore di ricerca fornito corrisponda al tipo del vettore specifico di destinazione. Per informazioni su come selezionare un vettore di destinazione nel caso ci siano più vettori per ciascun record, vedere VectorProperty.
Opzioni di ricerca vettoriale
È possibile specificare le opzioni seguenti usando la VectorSearchOptions<TRecord> classe .
VectorProperty
Usare l'opzione VectorProperty per specificare la proprietà vector di destinazione durante la ricerca. Se non viene specificato nessuno e il modello di dati contiene un solo vettore, verrà usato tale vettore. Se il modello di dati non contiene vettori o più vettori e VectorProperty non viene fornito, il metodo di ricerca genera un'eccezione.
public async Task VectorPropertySearch()
{
var vectorStore = new InMemoryVectorStore();
InMemoryCollection<int, Product> collection =
vectorStore.GetCollection<int, Product>("skproducts");
// Create the vector search options and indicate that you want to search the FeatureListEmbedding property.
var vectorSearchOptions = new VectorSearchOptions<Product>
{
VectorProperty = r => r.FeatureListEmbedding
};
// This snippet assumes searchVector is already provided, having been created using the embedding model of your choice.
IAsyncEnumerable<VectorSearchResult<Product>> searchResult =
collection.SearchAsync(searchVector, top: 3, vectorSearchOptions);
}
public sealed class Product
{
[VectorStoreKey]
public int Key { get; set; }
[VectorStoreData]
public required string Description { get; set; }
[VectorStoreData]
public required List<string> FeatureList { get; set; }
[VectorStoreVector(1536)]
public ReadOnlyMemory<float> DescriptionEmbedding { get; set; }
[VectorStoreVector(1536)]
public ReadOnlyMemory<float> FeatureListEmbedding { get; set; }
}
Ignorare i risultati o selezionare i risultati principali
Il top parametro su SearchAsync<TInput>(TInput, Int32, VectorSearchOptions<TRecord>, CancellationToken) e l'opzione VectorSearchOptions<TRecord>.Skip consentono di limitare il numero di risultati. Il top parametro limita i risultati ai risultati principali n . L'opzione Skip ignora un certo numero di risultati dall'inizio del set di risultati. È possibile usare questi controlli per eseguire il paging se si desidera recuperare un numero elevato di risultati usando chiamate separate.
// Create the vector search options and indicate
// that you want to skip the first 40 results.
VectorSearchOptions<Product> vectorSearchOptions = new()
{
Skip = 40
};
// This snippet assumes searchVector is already provided,
// having been created using the embedding model of your choice.
// Pass 'top: 20' to indicate that you want to retrieve
// the next 20 results after skipping the first 40.
IAsyncEnumerable<VectorSearchResult<Product>> searchResult =
collection.SearchAsync(searchVector, top: 20, vectorSearchOptions);
// Iterate over the search results.
await foreach (VectorSearchResult<Product> result in searchResult)
{
Console.WriteLine(result.Record.FeatureList);
}
Il valore predefinito per Skip è 0.
IncludeVectors
L'opzione VectorSearchOptions<TRecord>.IncludeVectors consente di specificare se si desidera restituire vettori nei risultati della ricerca. Se false, le proprietà vettoriali nel modello restituito vengono lasciate null. L'uso false di può ridurre significativamente la quantità di dati recuperati dall'archivio vettoriale durante la ricerca, rendendo le ricerche più efficienti.
Il valore predefinito per IncludeVectors è false.
// Create the vector search options and indicate that you want to include vectors in the search results.
var vectorSearchOptions = new VectorSearchOptions<Product>
{
IncludeVectors = true
};
// This snippet assumes searchVector is already provided,
// having been created using the embedding model of your choice.
IAsyncEnumerable<VectorSearchResult<Product>> searchResult =
collection.SearchAsync(searchVector, top: 3, vectorSearchOptions);
// Iterate over the search results.
await foreach (VectorSearchResult<Product> result in searchResult)
{
Console.WriteLine(result.Record.FeatureList);
}
Filter
Usare l'opzione VectorSearchOptions<TRecord>.Filter per filtrare i record nella raccolta scelta prima di applicare la ricerca vettoriale. Questo offre diversi vantaggi:
- Riduce la latenza e i costi di elaborazione, poiché è necessario confrontare solo i record rimanenti dopo il filtro con il vettore di ricerca e quindi è necessario eseguire un minor numero di confronti vettoriali.
- Limita il set di risultati. Ad esempio, è possibile implementare il controllo di accesso escludendo i dati a cui l'utente non deve avere accesso.
Per i campi da usare per filtrare, molti archivi vettoriali richiedono prima di tutto l'indicizzazione di tali campi. Alcuni archivi vettoriali consentiranno di filtrare usando qualsiasi campo, ma potrebbe facoltativamente consentire l'indicizzazione per migliorare le prestazioni di filtro.
Se si crea una raccolta tramite le astrazioni dell'archivio vettoriali e si vuole abilitare il filtro in un campo, impostare la IsIndexed proprietà su true quando si definisce il modello di dati o quando si crea la definizione del record.
Suggerimento
Per altre informazioni su come abilitare IsIndexed, vedere VectorStoreDataAttribute o VectorStoreDataProperty.
I filtri vengono espressi usando espressioni LINQ in base al tipo del modello di dati. Il set di espressioni LINQ supportate varia a seconda delle funzionalità supportate da ogni database, ma tutti i database supportano un'ampia base di espressioni comuni, ad esempio uguali, non uguali, ande or.
public static async Task FilteredSearchAsync()
{
// Create the vector search options and set the filter on the options.
VectorSearchOptions<Glossary> vectorSearchOptions = new()
{
Filter = r => r.Category == "External Definitions" && r.Tags.Contains("memory")
};
// This snippet assumes searchVector is already provided,
// having been created using the embedding model of your choice.
IAsyncEnumerable<VectorSearchResult<Glossary>> searchResult =
collection.SearchAsync(searchVector, top: 3, vectorSearchOptions);
// Iterate over the search results.
await foreach (VectorSearchResult<Glossary> result in searchResult)
{
Console.WriteLine(result.Record.Definition);
}
}
sealed class Glossary
{
[VectorStoreKey]
public ulong Key { get; set; }
// 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; }
[VectorStoreData]
public required string Term { get; set; }
[VectorStoreData]
public required string Definition { get; set; }
[VectorStoreVector(1536)]
public ReadOnlyMemory<float> DefinitionEmbedding { get; set; }
}