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.
Avviso
La funzionalità di store vettoriale del Semantic Kernel è in anteprima e i miglioramenti che richiedono cambiamenti significativi possono verificarsi ancora in circostanze limitate prima del rilascio.
Avviso
La funzionalità di store vettoriale del Semantic Kernel è in anteprima e i miglioramenti che richiedono cambiamenti significativi possono verificarsi ancora in circostanze limitate prima del rilascio.
Il kernel semantico fornisce funzionalità di ricerca vettoriale come parte delle astrazioni di Vector Store. Ciò supporta il filtro e molte altre opzioni, che questo articolo illustra in modo più dettagliato.
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.
Questo metodo è disponibile nei tipi seguenti:
IVectorSearchable<TRecord>VectorStoreCollection<TKey, TRecord>
Si noti che VectorStoreCollection<TKey, TRecord> implementa da IVectorSearchable<TRecord>.
Supponendo di avere una raccolta che contiene già dati, è possibile cercarli facilmente. Di seguito è riportato un esempio di uso di Qdrant.
using Microsoft.SemanticKernel.Connectors.Qdrant;
using Microsoft.Extensions.VectorData;
using Qdrant.Client;
// Placeholder embedding generation method.
async Task<ReadOnlyMemory<float>> GenerateEmbeddingAsync(string textToVectorize)
{
// your logic here
}
// 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 GenerateEmbeddingAsync("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.
var searchResult = collection.SearchAsync(searchVector, top: 1);
// Inspect the returned hotel.
await foreach (var 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.
Tipi di vettore supportati
SearchAsync accetta un tipo generico come parametro vector.
I tipi di vettori supportati da ogni archivio dati variano.
Vedere la documentazione per ogni connettore per l'elenco dei tipi di vettore supportati.
È 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. Vedi VectorProperty per sapere come selezionare un vettore di destinazione se hai più di un vettore per record.
Opzioni di ricerca vettoriale
È possibile specificare le opzioni seguenti usando la VectorSearchOptions<TRecord> classe .
VectorProperty
L'opzione VectorProperty può essere usata 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 alcun vettore o ne contiene più di uno e non viene fornito VectorProperty, il metodo di ricerca lancerà un'eccezione.
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.InMemory;
var vectorStore = new InMemoryVectorStore();
var collection = vectorStore.GetCollection<int, Product>("skproducts");
// Create the vector search options and indicate that we 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.
var searchResult = collection.SearchAsync(searchVector, top: 3, vectorSearchOptions);
public sealed class Product
{
[VectorStoreKey]
public int Key { get; set; }
[VectorStoreData]
public string Description { get; set; }
[VectorStoreData]
public List<string> FeatureList { get; set; }
[VectorStoreVector(1536)]
public ReadOnlyMemory<float> DescriptionEmbedding { get; set; }
[VectorStoreVector(1536)]
public ReadOnlyMemory<float> FeatureListEmbedding { get; set; }
}
Inizio e Salta
Le Top opzioni e Skip consentono di limitare il numero di risultati ai primi n risultati e di ignorare un numero di risultati dall'inizio del set di risultati.
È possibile usare Top e Skip per eseguire il paging se si desidera recuperare un numero elevato di risultati usando chiamate separate.
// Create the vector search options and indicate that we want to skip the first 40 results.
var vectorSearchOptions = new VectorSearchOptions<Product>
{
Skip = 40
};
// This snippet assumes searchVector is already provided, having been created using the embedding model of your choice.
// Here we pass top: 20 to indicate that we want to retrieve the next 20 results after skipping
// the first 40
var searchResult = collection.SearchAsync(searchVector, top: 20, vectorSearchOptions);
// Iterate over the search results.
await foreach (var result in searchResult)
{
Console.WriteLine(result.Record.FeatureList);
}
Il valore Skip predefinito è 0.
IncludiVettori
L'opzione IncludeVectors consente di specificare se si desidera restituire vettori nei risultati della ricerca.
Se false, le proprietà vettoriali nel modello restituito verranno 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 we 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.
var searchResult = collection.SearchAsync(searchVector, top: 3, vectorSearchOptions);
// Iterate over the search results.
await foreach (var result in searchResult)
{
Console.WriteLine(result.Record.FeatureList);
}
Filtro
L'opzione di filtro di ricerca vettoriale può essere usata per fornire un filtro per filtrare i record nella raccolta scelta prima di applicare la ricerca vettoriale.
Questo offre diversi vantaggi:
- Ridurre la latenza e i costi di elaborazione, poiché devono essere confrontati solo i record rimanenti dopo il filtro con il vettore di ricerca e quindi è necessario eseguire un minor numero di confronti vettoriali.
- Limitare il set di risultati per scopi di controllo di accesso, ad esempio, escludendo i dati a cui l'utente non deve avere accesso.
Si noti che affinché i campi vengano usati per filtrare, molti archivi vettoriali richiedono che tali campi vengano indicizzati per primi. Alcuni archivi vettoriali consentiranno di filtrare usando qualsiasi campo, ma possono facoltativamente consentire l'indicizzazione per migliorare le prestazioni di filtro.
Se si crea una raccolta tramite le astrazioni dell'archivio vettoriale del kernel semantico e si vuole abilitare il filtro in un campo, impostare la IsFilterable proprietà su true quando si definisce il modello di dati o quando si crea la definizione del record.
Suggerimento
Per altre informazioni su come impostare la IsFilterable proprietà, fare riferimento ai parametri VectorStoreDataAttribute o alle impostazioni di configurazione 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 e così via.
// Create the vector search options and set the filter on the options.
var vectorSearchOptions = new VectorSearchOptions<Glossary>
{
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.
var searchResult = collection.SearchAsync(searchVector, top: 3, vectorSearchOptions);
// Iterate over the search results.
await foreach (var result in searchResult)
{
Console.WriteLine(result.Record.Definition);
}
sealed class Glossary
{
[VectorStoreKey]
public ulong Key { get; set; }
// Category is marked as indexed, since we want to filter using this property.
[VectorStoreData(IsIndexed = true)]
public string Category { get; set; }
// Tags is marked as indexed, since we want to filter using this property.
[VectorStoreData(IsIndexed = true)]
public List<string> Tags { get; set; }
[VectorStoreData]
public string Term { get; set; }
[VectorStoreData]
public string Definition { get; set; }
[VectorStoreVector(1536)]
public ReadOnlyMemory<float> DefinitionEmbedding { get; set; }
}
Ricerca vettoriale
Esistono due ricerche attualmente supportate nelle astrazioni dell'archivio di vettori del Semantic Kernel.
-
search(ricerca vettoriale)- Si tratta di una ricerca basata su un valore che può essere vettorializzato, dal campo nel
embedding_generatormodello di dati o nella definizione di record o dall'archivio vettoriale stesso. Oppure specificando direttamente un vettore.
- Si tratta di una ricerca basata su un valore che può essere vettorializzato, dal campo nel
-
hybrid_search-> vedere Ricerca ibrida
Tutte le ricerche possono accettare un set facoltativo di parametri:
-
vector: Un vettore usato per la ricerca può essere fornito al posto dei valori o in aggiunta ai valori per una configurazione ibrida. -
top: numero di risultati da restituire, il valore predefinito è 3. -
skip: numero di risultati da ignorare, il valore predefinito è 0. -
include_vectors: indica se includere i vettori nei risultati, per impostazione predefinita èfalse. -
filter: filtro da applicare ai risultati prima dell'applicazione della ricerca vettoriale, il valore predefinito èNone, sotto forma di espressione lambda:lambda record: record.property == "value". -
vector_property_name: nome della proprietà vector da usare per la ricerca, per impostazione predefinita viene utilizzata la prima proprietà vettoriale presente nel modello di dati o nella definizione di record. -
include_total_count: indica se includere il conteggio totale dei risultati nel risultato della ricerca, per impostazione predefinita èfalse.
Supponendo di avere una raccolta che contiene già dati, è possibile cercarli facilmente. Di seguito è riportato un esempio di uso di Ricerca intelligenza artificiale di Azure.
from semantic_kernel.connectors.azure_ai_search import AzureAISearchCollection, AzureAISearchStore
# Create a Azure AI Search VectorStore object and choose an existing collection that already contains records.
# Hotels is the data model decorated class.
store = AzureAISearchStore()
collection: AzureAISearchCollection[str, Hotels] = store.get_collection(Hotels, collection_name="skhotels")
search_results = await collection.search(
query, vector_property_name="vector"
)
hotels = [record.record async for record in search_results.results]
print(f"Found hotels: {hotels}")
Suggerimento
Per altre informazioni su come generare incorporamenti, vedere Generazione di incorporamenti.
Filtri
Il filter parametro può essere usato per fornire un filtro per filtrare i record nella raccolta scelta. È definito come espressione lambda o stringa di un'espressione lambda, ad esempio lambda record: record.property == "value".
È importante comprendere che questi non vengono eseguiti direttamente, ma vengono analizzati nella sintassi corrispondente agli archivi vettoriali, l'unica eccezione a questo è che InMemoryCollection esegue direttamente il filtro.
Data questa flessibilità, è importante esaminare la documentazione di un archivio specifico per comprendere quali filtri sono supportati, ad esempio non tutti gli archivi vettoriali supportano filtri negativi (ad lambda x: not x.valueesempio ) e che non diventano evidenti fino a quando non viene eseguita la ricerca.
Ricerca vettoriale
Il searchAsync metodo consente di eseguire ricerche usando dati già vettorializzati. Questo metodo accetta un vettore e una classe facoltativa VectorSearchOptions come input.
Questo metodo è disponibile nelle interfacce seguenti:
VectorizedSearch<Record>VectorStoreRecordCollection<Key, Record>
Si noti che VectorStoreRecordCollection<Key, Record> eredita da VectorizedSearch<Record>.
Supponendo di avere una raccolta che contiene già dati, è possibile cercarli facilmente. Di seguito è riportato un esempio di uso di JDBC con PostgreSQL.
import com.microsoft.semantickernel.data.jdbc.JDBCVectorStore;
import com.microsoft.semantickernel.data.jdbc.JDBCVectorStoreOptions;
import com.microsoft.semantickernel.data.jdbc.JDBCVectorStoreRecordCollectionOptions;
import com.microsoft.semantickernel.data.jdbc.postgres.PostgreSQLVectorStoreQueryProvider;
import com.microsoft.semantickernel.data.vectorstorage.options.VectorSearchOptions;
import org.postgresql.ds.PGSimpleDataSource;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Configure the data source
PGSimpleDataSource dataSource = new PGSimpleDataSource();
dataSource.setUrl("jdbc:postgresql://localhost:5432/sk");
dataSource.setUser("postgres");
dataSource.setPassword("root");
// Create a JDBC vector store and choose an existing collection that already contains records.
var vectorStore = new JDBCVectorStore(dataSource, JDBCVectorStoreOptions.builder()
.withQueryProvider(PostgreSQLVectorStoreQueryProvider.builder()
.withDataSource(dataSource)
.build())
.build());
var collection = vectorStore.getCollection("skhotels", JDBCVectorStoreRecordCollectionOptions.<Hotel>builder()
.withRecordClass(Hotel.class)
.build());
// Generate a vector for your search text, using your chosen embedding generation implementation.
// Just showing a placeholder method here for brevity.
var searchVector = generateEmbeddingsAsync("I'm looking for a hotel where customer happiness is the priority.").block();
// Do the search, passing an options object with a Top value to limit results to the single top match.
var searchResult = collection.searchAsync(searchVector, VectorSearchOptions.builder()
.withTop(1).build()
).block();
// Inspect the returned hotel.
Hotel hotel = searchResult.getResults().get(0).getRecord();
System.out.printf("Found hotel description: %s\n", hotel.getDescription());
}
}
Suggerimento
Per altre informazioni su come generare incorporamenti, vedere Generazione di incorporamenti.
Opzioni di ricerca vettoriale
È possibile specificare le opzioni seguenti usando la VectorSearchOptions classe .
VectorFieldName
L'opzione VectorFieldName può essere usata per specificare il nome del campo vettore di destinazione durante la ricerca.
Se non viene specificato alcun valore, verrà usato il primo vettore trovato nel modello di dati o specificato nella definizione del record.
Si noti che quando si specifica il VectorFieldName, usare il nome del campo come definito nel modello di dati o nella definizione del record.
Usare questo nome di campo anche se il campo può essere archiviato con un nome diverso nell'archivio vettoriale. Il nome di archiviazione può essere diverso a causa delle impostazioni di serializzazione personalizzate.
import com.microsoft.semantickernel.data.VolatileVectorStore;
import com.microsoft.semantickernel.data.VolatileVectorStoreRecordCollectionOptions;
import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData;
import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey;
import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector;
import com.microsoft.semantickernel.data.vectorstorage.options.VectorSearchOptions;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Build a query provider
var vectorStore = new VolatileVectorStore();
var collection = vectorStore.getCollection("skproducts", VolatileVectorStoreRecordCollectionOptions.<Product>builder()
.withRecordClass(Product.class)
.build());
// Create the vector search options and indicate that we want to search the FeatureListEmbedding field.
var searchOptions = VectorSearchOptions.builder()
.withVectorFieldName("featureListEmbedding")
.build();
// Generate a vector for your search text, using the embedding model of your choice
var searchVector = generateEmbeddingsAsync().block();
// Do the search
var searchResult = collection.searchAsync(searchVector, searchOptions).block();
}
public static class Product {
@VectorStoreRecordKey
private int key;
@VectorStoreRecordData
private String description;
@VectorStoreRecordData
private List<String> featureList;
@VectorStoreRecordVector(dimensions = 1536)
public List<Float> descriptionEmbedding;
@VectorStoreRecordVector(dimensions = 1536)
public List<Float> featureListEmbedding;
public Product() {
}
public Product(int key, String description, List<String> featureList, List<Float> descriptionEmbedding, List<Float> featureListEmbedding) {
this.key = key;
this.description = description;
this.featureList = featureList;
this.descriptionEmbedding = Collections.unmodifiableList(descriptionEmbedding);
this.featureListEmbedding = Collections.unmodifiableList(featureListEmbedding);
}
public int getKey() { return key; }
public String getDescription() { return description; }
public List<String> getFeatureList() { return featureList; }
public List<Float> getDescriptionEmbedding() { return descriptionEmbedding; }
public List<Float> getFeatureListEmbedding() { return featureListEmbedding; }
}
}
Inizio e Salta
Le Top opzioni e Skip consentono di limitare il numero di risultati ai primi n risultati e di ignorare un numero di risultati dall'inizio del set di risultati.
È possibile usare Top e Skip per eseguire il paging se si desidera recuperare un numero elevato di risultati usando chiamate separate.
// Create the vector search options and indicate that we want to skip the first 40 results and then get the next 20.
var searchOptions = VectorSearchOptions.builder()
.withTop(20)
.withSkip(40)
.build();
// Generate a vector for your search text, using the embedding model of your choice
var searchVector = generateEmbeddingsAsync().block();
// Do the search
var searchResult = collection.searchAsync(searchVector, searchOptions).block();
I valori predefiniti per Top sono 3 e Skip sono 0.
IncludiVettori
L'opzione IncludeVectors consente di specificare se si desidera restituire vettori nei risultati della ricerca.
Se false, le proprietà vettoriali nel modello restituito verranno 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 we want to include vectors in the search results.
var searchOptions = VectorSearchOptions.builder()
.withIncludeVectors(true)
.build();
// Generate a vector for your search text, using the embedding model of your choice
var searchVector = generateEmbeddingsAsync().block();
// Do the search
var searchResult = collection.searchAsync(searchVector, searchOptions).block();
VectorSearchFilter
L'opzione VectorSearchFilter può essere usata per fornire un filtro per filtrare i record nella raccolta scelta prima di applicare la ricerca vettoriale.
Questo offre diversi vantaggi:
- Ridurre la latenza e i costi di elaborazione, poiché devono essere confrontati solo i record rimanenti dopo il filtro con il vettore di ricerca e quindi è necessario eseguire un minor numero di confronti vettoriali.
- Limitare il set di risultati per scopi di controllo di accesso, ad esempio, escludendo i dati a cui l'utente non deve avere accesso.
Si noti che affinché i campi vengano usati per filtrare, molti archivi vettoriali richiedono che tali campi vengano indicizzati per primi. Alcuni archivi vettoriali consentiranno di filtrare usando qualsiasi campo, ma possono facoltativamente consentire l'indicizzazione per migliorare le prestazioni di filtro.
Se si crea una raccolta tramite le astrazioni dell'archivio vettoriale del kernel semantico e si vuole abilitare il filtro in un campo, impostare il IsFilterable campo su true quando si definisce il modello di dati o quando si crea la definizione del record.
Suggerimento
Per altre informazioni su come impostare il IsFilterable campo, fare riferimento ai parametri VectorStoreRecordData o alle impostazioni di configurazione VectorStoreRecordDataField.
Per creare un filtro, usare la VectorSearchFilter classe . Si possono combinare più clausole di filtro in un unico oggetto VectorSearchFilter.
Tutte le clausole di filtro vengono combinate con and.
Si noti che quando si specifica un nome di campo quando si costruisce il filtro, usare il nome del campo come definito nel modello di dati o nella definizione del record.
Usare questo nome di campo anche se il campo può essere archiviato con un nome diverso nell'archivio vettoriale. Il nome di archiviazione può essere diverso a causa delle impostazioni di serializzazione personalizzate.
// Filter where category == 'External Definitions' and tags contain 'memory'.
var filter = VectorSearchFilter.builder()
.equalTo("category", "External Definitions")
.anyTagEqualTo("tags", "memory")
.build();
// Create the vector search options and indicate that we want to filter the search results by a specific field.
var searchOptions = VectorSearchOptions.builder()
.withVectorSearchFilter(filter)
.build();
// Generate a vector for your search text, using the embedding model of your choice
var searchVector = generateEmbeddingsAsync().block();
// Do the search
var searchResult = collection.searchAsync(searchVector, searchOptions).block();
public static class Glossary {
@VectorStoreRecordKey
private String key;
@VectorStoreRecordData(isFilterable = true)
private String category;
@VectorStoreRecordData(isFilterable = true)
private List<String> tags;
@VectorStoreRecordData
private String term;
@VectorStoreRecordData
private String definition;
@VectorStoreRecordVector(dimensions = 1536)
private List<Float> definitionEmbedding;
public Glossary() {
}
public Glossary(String key, String category, List<String> tags, String term, String definition, List<Float> definitionEmbedding) {
this.key = key;
this.category = category;
this.tags = tags;
this.term = term;
this.definition = definition;
this.definitionEmbedding = Collections.unmodifiableList(definitionEmbedding);
}
public String getKey() { return key; }
public String getCategory() { return category; }
public List<String> getTags() { return tags; }
public String getTerm() { return term; }
public String getDefinition() { return definition; }
public List<Float> getDefinitionEmbedding() { return definitionEmbedding; }
}
Clausola di filtro EqualTo
Usare equalTo per un confronto diretto tra campo e valore.
Clausola di filtro AnyTagEqualTo
Usare anyTagEqualTo per verificare se una delle stringhe, archiviata in un campo tag nell'archivio vettoriale, contiene un valore specificato.
Affinché un campo venga considerato un campo tag, deve essere un List<String>.