Qu’est-ce que les connecteurs de magasin de vecteurs du noyau sémantique ? (Préversion)
Avertissement
La fonctionnalité de magasin de vecteurs du noyau sémantique est en préversion et des améliorations nécessitant des modifications cassants peuvent toujours se produire dans des circonstances limitées avant la mise en production.
Conseil
Si vous recherchez des informations sur les connecteurs de magasin de mémoire hérités, reportez-vous à la page Magasins de mémoire.
Les bases de données vectorielles ont de nombreux cas d’usage dans différents domaines et applications qui impliquent le traitement du langage naturel (NLP), la vision par ordinateur (CV), les systèmes de recommandation (RS) et d’autres domaines qui nécessitent une compréhension sémantique et une correspondance des données.
Un cas d’usage pour stocker des informations dans une base de données vectorielle consiste à permettre aux modèles de langage volumineux (LLMs) de générer des réponses plus pertinentes et cohérentes. Les grands modèles linguistiques sont souvent confrontés à des défis tels que la génération d’informations inexactes ou non pertinentes ; absence de cohérence factuelle ou de bon sens ; répéter ou contredire eux-mêmes ; être biaisé ou offensif. Pour vous aider à surmonter ces défis, vous pouvez utiliser une base de données vectorielle pour stocker des informations sur différentes rubriques, mots clés, faits, opinions et/ou sources liées à votre domaine ou genre souhaité. La base de données vectorielle vous permet de trouver efficacement le sous-ensemble d’informations relatives à une question ou une rubrique spécifique. Vous pouvez ensuite transmettre des informations de la base de données vectorielle avec votre invite à votre modèle de langage volumineux pour générer du contenu plus précis et pertinent.
Par exemple, si vous souhaitez écrire un billet de blog sur les dernières tendances de l’IA, vous pouvez utiliser une base de données vectorielle pour stocker les dernières informations sur cette rubrique et transmettre les informations avec la demande à un LLM afin de générer un billet de blog qui tire parti des dernières informations.
Le noyau sémantique et .net fournissent une abstraction permettant d’interagir avec les magasins de vecteurs et une liste de connecteurs prêtes à l’emploi qui implémentent ces abstractions. Les fonctionnalités incluent la création, la liste et la suppression de collections d’enregistrements et le chargement, la récupération et la suppression d’enregistrements. L’abstraction facilite l’expérimentation d’un magasin vectoriel gratuit ou hébergé localement, puis de basculer vers un service lorsque vous avez besoin d’effectuer un scale-up.
Abstraction du magasin de vecteurs
Les principales interfaces de l’abstraction Vector Store sont les suivantes.
Microsoft.Extensions.VectorData.IVectorStore
IVectorStore
contient des opérations qui s’étendent sur toutes les collections du magasin vectoriel, par exemple ListCollectionNames.
Il offre également la possibilité d’obtenir IVectorStoreRecordCollection<TKey, TRecord>
des instances.
Microsoft.Extensions.VectorData.IVectorStoreRecordCollection<TKey, TRecord>
IVectorStoreRecordCollection<TKey, TRecord>
représente une collection.
Cette collection peut ou non exister et l’interface fournit des méthodes pour vérifier si la collection existe, la créer ou la supprimer.
L’interface fournit également des méthodes pour upsert, obtenir et supprimer des enregistrements.
Enfin, l’interface hérite de la fourniture de fonctionnalités de IVectorizedSearch<TRecord>
recherche vectorielle.
Microsoft.Extensions.VectorData.IVectorizedSearch<TRecord>
IVectorizedSearch<TRecord>
contient une méthode pour effectuer des recherches vectorielles.
IVectorStoreRecordCollection<TKey, TRecord>
hérite de la possibilité d’utiliser IVectorizedSearch<TRecord>
IVectorizedSearch<TRecord>
elle-même dans les cas où seule la recherche est nécessaire et qu’aucune gestion des enregistrements ou des collections n’est nécessaire.
IVectorizableTextSearch<TRecord>
IVectorizableTextSearch<TRecord>
contient une méthode pour effectuer des recherches vectorielles où la base de données vectorielle a la possibilité de générer automatiquement des incorporations. Par exemple, vous pouvez appeler cette méthode avec une chaîne de texte et la base de données génère l’incorporation pour vous et effectue une recherche sur un champ vectoriel. Cela n’est pas pris en charge par toutes les bases de données vectorielles et est donc implémenté uniquement par les connecteurs sélectionnés.
Abstraction du magasin de vecteurs
Les principales interfaces de l’abstraction Vector Store sont les suivantes.
com.microsoft.semantickernel.data.vectorstorage.VectorStore
VectorStore
contient des opérations qui s’étendent sur toutes les collections du magasin vectoriel, par exemple listCollectionNames.
Il offre également la possibilité d’obtenir VectorStoreRecordCollection<Key, Record>
des instances.
com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection<Key, Record>
VectorStoreRecordCollection<Key, Record>
représente une collection.
Cette collection peut ou non exister et l’interface fournit des méthodes pour vérifier si la collection existe, la créer ou la supprimer.
L’interface fournit également des méthodes pour upsert, obtenir et supprimer des enregistrements.
Enfin, l’interface hérite de la fourniture de fonctionnalités de VectorizedSearch<Record>
recherche vectorielle.
com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<Record>
VectorizedSearch<Record>
contient une méthode pour effectuer des recherches vectorielles.
VectorStoreRecordCollection<Key, Record>
hérite de la possibilité d’utiliser VectorizedSearch<Record>
VectorizedSearch<Record>
elle-même dans les cas où seule la recherche est nécessaire et qu’aucune gestion des enregistrements ou des collections n’est nécessaire.
com.microsoft.semantickernel.data.vectorsearch.VectorizableTextSearch<Record>
VectorizableTextSearch<Record>
contient une méthode pour effectuer des recherches vectorielles où la base de données vectorielle a la possibilité de générer automatiquement des incorporations. Par exemple, vous pouvez appeler cette méthode avec une chaîne de texte et la base de données génère l’incorporation pour vous et effectue une recherche sur un champ vectoriel. Cela n’est pas pris en charge par toutes les bases de données vectorielles et est donc implémenté uniquement par les connecteurs sélectionnés.
Prise en main des connecteurs Vector Store
Importer les packages nuget nécessaires
Toutes les interfaces de magasin de vecteurs et toutes les classes associées à l’abstraction sont disponibles dans le Microsoft.Extensions.VectorData.Abstractions
package nuget.
Chaque implémentation de magasin de vecteurs est disponible dans son propre package nuget. Pour obtenir la liste des implémentations connues, consultez la page connecteurs out-of-the-box.
Le package d’abstractions peut être ajouté comme suit.
dotnet add package Microsoft.Extensions.VectorData.Abstractions --prerelease
Avertissement
À partir de la version 1.23.0 du noyau sémantique, les abstractions du magasin de vecteurs ont été supprimées Microsoft.SemanticKernel.Abstractions
et sont disponibles dans le nouveau package dédié Microsoft.Extensions.VectorData.Abstractions
.
Notez que, à partir de la version 1.23.0, Microsoft.SemanticKernel.Abstractions
il Microsoft.Extensions.VectorData.Abstractions
n’est donc pas nécessaire de référencer des packages supplémentaires.
Toutefois, les abstractions se trouveront dans le nouvel Microsoft.Extensions.VectorData
espace de noms.
Lors de la mise à niveau de la version 1.22.0 ou antérieure vers la version 1.23.0 ou ultérieure, vous devez ajouter une clause supplémentaire using Microsoft.Extensions.VectorData;
dans les fichiers où l’un des types d’abstraction vector Store est utilisé, par exemple IVectorStore
, , IVectorStoreRecordCollection
, VectorStoreRecordDataAttribute
, VectorStoreRecordKeyProperty
etc.
Cette modification a été apportée pour prendre en charge les fournisseurs de magasin de vecteurs lors de la création de leurs propres implémentations. Un fournisseur doit uniquement référencer le Microsoft.Extensions.VectorData.Abstractions
package. Cela réduit les conflits de version potentiels et permet au noyau sémantique de continuer à évoluer rapidement sans affecter les fournisseurs de magasin de vecteurs.
Définir votre modèle de données
Les connecteurs de magasin de vecteurs de noyau sémantique utilisent une première approche de modèle pour interagir avec les bases de données. Cela signifie que la première étape consiste à définir un modèle de données mappé au schéma de stockage. Pour aider les connecteurs à créer des collections d’enregistrements et à mapper au schéma de stockage, le modèle peut être annoté pour indiquer la fonction de chaque propriété.
using Microsoft.Extensions.VectorData;
public class Hotel
{
[VectorStoreRecordKey]
public ulong HotelId { get; set; }
[VectorStoreRecordData(IsFilterable = true)]
public string HotelName { get; set; }
[VectorStoreRecordData(IsFullTextSearchable = true)]
public string Description { get; set; }
[VectorStoreRecordVector(Dimensions: 4, DistanceFunction.CosineDistance, IndexKind.Hnsw)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
[VectorStoreRecordData(IsFilterable = true)]
public string[] Tags { get; set; }
}
from dataclasses import dataclass, field
from typing import Annotated
from semantic_kernel.data import (
DistanceFunction,
IndexKind,
VectorStoreRecordDataField,
VectorStoreRecordDefinition,
VectorStoreRecordKeyField,
VectorStoreRecordVectorField,
vectorstoremodel,
)
@vectorstoremodel
@dataclass
class Hotel:
hotel_id: Annotated[str, VectorStoreRecordKeyField()] = field(default_factory=lambda: str(uuid4()))
hotel_name: Annotated[str, VectorStoreRecordDataField(is_filterable=True)]
description: Annotated[str, VectorStoreRecordDataField(is_full_text_searchable=True)]
description_embedding: Annotated[list[float], VectorStoreRecordVectorField(dimensions=4, distance_function=DistanceFunction.COSINE, index_kind=IndexKind.HNSW)]
tags: Annotated[list[str], VectorStoreRecordDataField(is_filterable=True)]
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.definition.DistanceFunction;
import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind;
import java.util.Collections;
import java.util.List;
public class Hotel {
@VectorStoreRecordKey
private String hotelId;
@VectorStoreRecordData(isFilterable = true)
private String name;
@VectorStoreRecordData(isFullTextSearchable = true)
private String description;
@VectorStoreRecordVector(dimensions = 4, indexKind = IndexKind.HNSW, distanceFunction = DistanceFunction.COSINE_DISTANCE)
private List<Float> descriptionEmbedding;
@VectorStoreRecordData(isFilterable = true)
private List<String> tags;
public Hotel() { }
public Hotel(String hotelId, String name, String description, List<Float> descriptionEmbedding, List<String> tags) {
this.hotelId = hotelId;
this.name = name;
this.description = description;
this.descriptionEmbedding = Collections.unmodifiableList(descriptionEmbedding);
this.tags = Collections.unmodifiableList(tags);
}
public String getHotelId() { return hotelId; }
public String getName() { return name; }
public String getDescription() { return description; }
public List<Float> getDescriptionEmbedding() { return descriptionEmbedding; }
public List<String> getTags() { return tags; }
}
Conseil
Pour plus d’informations sur la façon d’annoter votre modèle de données, reportez-vous à la définition de votre modèle de données.
Conseil
Pour une alternative à l’annotation de votre modèle de données, reportez-vous à la définition de votre schéma avec une définition d’enregistrement.
Se connecter à votre base de données et sélectionner une collection
Une fois que vous avez défini votre modèle de données, l’étape suivante consiste à créer une instance VectorStore pour la base de données de votre choix et à sélectionner une collection d’enregistrements.
Dans cet exemple, nous allons utiliser Qdrant. Vous devez donc importer le package nuget Qdrant.
dotnet add package Microsoft.SemanticKernel.Connectors.Qdrant --prerelease
Étant donné que les bases de données prennent en charge de nombreux types de clés et d’enregistrements différents, nous vous permettent de spécifier le type de la clé et de l’enregistrement pour votre collection à l’aide de génériques.
Dans notre cas, le type d’enregistrement sera la Hotel
classe que nous avons déjà définie, et le type de clé sera ulong
, car la HotelId
propriété est un ulong
et Qdrant prend uniquement en charge Guid
ou ulong
clés.
using Microsoft.SemanticKernel.Connectors.Qdrant;
using Qdrant.Client;
// Create a Qdrant VectorStore object
var vectorStore = new QdrantVectorStore(new QdrantClient("localhost"));
// Choose a collection from the database and specify the type of key and record stored in it via Generic parameters.
var collection = vectorStore.GetCollection<ulong, Hotel>("skhotels");
Étant donné que les bases de données prennent en charge de nombreux types de clés et d’enregistrements différents, nous vous permettent de spécifier le type de la clé et de l’enregistrement pour votre collection à l’aide de génériques.
Dans notre cas, le type d’enregistrement sera la Hotel
classe que nous avons déjà définie, et le type de clé sera str
, car la HotelId
propriété est un str
et Qdrant prend uniquement en charge str
ou int
clés.
from semantic_kernel.connectors.memory.qdrant import QdrantStore
# Create a Qdrant VectorStore object, this will look in the environment for Qdrant related settings, and will fall back to the default, which is to run in-memory.
vector_store = QdrantStore()
# Choose a collection from the database and specify the type of key and record stored in it via Generic parameters.
collection = vector_store.get_collection(
collection_name="skhotels",
data_model_type=Hotel
)
Étant donné que les bases de données prennent en charge de nombreux types de clés et d’enregistrements différents, nous vous permettent de spécifier le type de la clé et de l’enregistrement pour votre collection à l’aide de génériques.
Dans notre cas, le type d’enregistrement sera la Hotel
classe que nous avons déjà définie, et le type de clé sera String
, car la hotelId
propriété est un String
magasin JDBC ne prend en charge String
que les clés.
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.mysql.MySQLVectorStoreQueryProvider;
import com.mysql.cj.jdbc.MysqlDataSource;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Create a MySQL data source
var dataSource = new MysqlDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/sk");
dataSource.setPassword("root");
dataSource.setUser("root");
// Create a JDBC vector store
var vectorStore = JDBCVectorStore.builder()
.withDataSource(dataSource)
.withOptions(
JDBCVectorStoreOptions.builder()
.withQueryProvider(MySQLVectorStoreQueryProvider.builder()
.withDataSource(dataSource)
.build())
.build()
)
.build();
// Get a collection from the vector store
var collection = vectorStore.getCollection("skhotels",
JDBCVectorStoreRecordCollectionOptions.<Hotel>builder()
.withRecordClass(Hotel.class)
.build()
);
}
}
Conseil
Pour plus d’informations sur les types de clés et de champs pris en charge par chaque connecteur Vector Store, reportez-vous à la documentation de chaque connecteur.
Créer la collection et ajouter des enregistrements
// Create the collection if it doesn't exist yet.
await collection.CreateCollectionIfNotExistsAsync();
// Upsert a record.
string descriptionText = "A place where everyone can be happy.";
ulong hotelId = 1;
// Create a record and generate a vector for the description using your chosen embedding generation implementation.
// Just showing a placeholder embedding generation method here for brevity.
await collection.UpsertAsync(new Hotel
{
HotelId = hotelId,
HotelName = "Hotel Happy",
Description = descriptionText,
DescriptionEmbedding = await GenerateEmbeddingAsync(descriptionText),
Tags = new[] { "luxury", "pool" }
});
// Retrieve the upserted record.
Hotel? retrievedHotel = await collection.GetAsync(hotelId);
Créer la collection et ajouter des enregistrements
# Create the collection if it doesn't exist yet.
await collection.create_collection_if_not_exists()
# Upsert a record.
description = "A place where everyone can be happy."
hotel_id = "1"
await collection.upsert(Hotel(
hotel_id = hotel_id,
hotel_name = "Hotel Happy",
description = description,
description_embedding = await GenerateEmbeddingAsync(description),
tags = ["luxury", "pool"]
))
# Retrieve the upserted record.
retrieved_hotel = await collection.get(hotel_id)
// Create the collection if it doesn't exist yet.
collection.createCollectionAsync().block();
// Upsert a record.
var description = "A place where everyone can be happy";
var hotelId = "1";
var hotel = new Hotel(
hotelId,
"Hotel Happy",
description,
generateEmbeddingsAsync(description).block(),
List.of("luxury", "pool")
);
collection.upsertAsync(hotel, null).block();
// Retrieve the upserted record.
var retrievedHotel = collection.getAsync(hotelId, null).block();
Conseil
Pour plus d’informations sur la génération d’incorporations, consultez la génération d’incorporation.
Effectuer une recherche vectorielle
// Generate a vector for your search text, using your chosen embedding generation implementation.
// Just showing a placeholder method here for brevity.
var searchVector = await GenerateEmbeddingAsync("I'm looking for a hotel where customer happiness is the priority.");
// Do the search.
var searchResult = await collection.VectorizedSearchAsync(searchVector, new() { Top = 1 }).Results.ToListAsync()
// Inspect the returned hotels.
Hotel hotel = searchResult.First().Record;
Console.WriteLine("Found hotel description: " + hotel.Description);
// 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.
var searchResult = collection.searchAsync(searchVector, VectorSearchOptions.builder()
.withTop(1).build()
).block();
Hotel record = searchResult.getResults().get(0).getRecord();
System.out.printf("Found hotel description: %s\n", record.getDescription());
Conseil
Pour plus d’informations sur la génération d’incorporations, consultez la génération d’incorporation.