Wat zijn Semantische Kernel Vector Store-connectors? (Preview)
Waarschuwing
De Semantische Kernel Vector Store-functionaliteit is in preview en verbeteringen waarvoor wijzigingen die fouten veroorzaken, kunnen nog steeds in beperkte omstandigheden optreden voordat ze worden uitgebracht.
Tip
Als u op zoek bent naar informatie over de verouderde geheugenopslagconnectors, raadpleegt u de pagina Geheugenarchieven.
Vectordatabases hebben veel gebruiksvoorbeelden voor verschillende domeinen en toepassingen die betrekking hebben op verwerking van natuurlijke taal (NLP), computer vision (CV), aanbevelingssystemen (RS) en andere gebieden waarvoor semantisch begrip en afstemming van gegevens nodig zijn.
Een gebruiksvoorbeeld voor het opslaan van informatie in een vectordatabase is om grote taalmodellen (LLM's) in staat te stellen relevantere en coherentere antwoorden te genereren. Grote taalmodellen hebben vaak te maken met uitdagingen zoals het genereren van onnauwkeurige of irrelevante informatie; gebrek aan feitelijke consistentie of gezond verstand; zichzelf herhalen of tegenspreken; bevooroordeeld of aanstootgevend zijn. Om deze uitdagingen te overwinnen, kunt u een vectordatabase gebruiken om informatie op te slaan over verschillende onderwerpen, trefwoorden, feiten, meningen en/of bronnen die betrekking hebben op uw gewenste domein of genre. Met de vectordatabase kunt u de subset van informatie met betrekking tot een specifieke vraag of onderwerp efficiënt vinden. Vervolgens kunt u informatie uit de vectordatabase doorgeven met uw prompt aan uw grote taalmodel om nauwkeurigere en relevante inhoud te genereren.
Als u bijvoorbeeld een blogbericht wilt schrijven over de nieuwste trends in AI, kunt u een vectordatabase gebruiken om de meest recente informatie over dat onderwerp op te slaan en de informatie samen met de vraag door te geven aan een LLM om een blogbericht te genereren dat gebruikmaakt van de meest recente informatie.
Semantische kernel en .net bieden een abstractie voor interactie met Vector Stores en een lijst met out-of-the-box connectors die deze abstracties implementeren. Functies zijn onder andere het maken, weergeven en verwijderen van verzamelingen records en het uploaden, ophalen en verwijderen van records. Met de abstractie kunt u eenvoudig experimenteren met een gratis of lokaal gehost Vector Store en vervolgens overschakelen naar een service wanneer u omhoog wilt schalen.
De vectoropslagabstractie
De belangrijkste interfaces in de Vector Store-abstractie zijn het volgende.
Microsoft.Extensions.VectorData.IVectorStore
IVectorStore
bevat bewerkingen die alle verzamelingen in het vectorarchief omvatten, bijvoorbeeld ListCollectionNames.
Het biedt ook de mogelijkheid om exemplaren op te halen IVectorStoreRecordCollection<TKey, TRecord>
.
Microsoft.Extensions.VectorData.IVectorStoreRecordCollection<TKey, TRecord>
IVectorStoreRecordCollection<TKey, TRecord>
vertegenwoordigt een verzameling.
Deze verzameling bestaat al dan niet en de interface biedt methoden om te controleren of de verzameling bestaat, deze te maken of te verwijderen.
De interface biedt ook methoden voor upsert, ophalen en verwijderen van records.
Ten slotte neemt de interface over van het bieden van IVectorizedSearch<TRecord>
vectorzoekmogelijkheden.
Microsoft.Extensions.VectorData.IVectorizedSearch<TRecord>
IVectorizedSearch<TRecord>
bevat een methode voor het uitvoeren van vectorzoekopdrachten.
IVectorStoreRecordCollection<TKey, TRecord>
neemt over van IVectorizedSearch<TRecord>
het zelf gebruiken van het gebruik IVectorizedSearch<TRecord>
ervan in gevallen waarin alleen zoeken nodig is en er geen record- of verzamelingsbeheer nodig is.
IVectorizableTextSearch<TRecord>
IVectorizableTextSearch<TRecord>
bevat een methode voor het uitvoeren van vectorzoekopdrachten waarbij de vectordatabase de mogelijkheid heeft om automatisch insluitingen te genereren. U kunt deze methode bijvoorbeeld aanroepen met een tekenreeks en de database genereert de insluiting voor u en zoekt op basis van een vectorveld. Dit wordt niet ondersteund door alle vectordatabases en wordt daarom alleen geïmplementeerd door selecte connectors.
De vectoropslagabstractie
De belangrijkste interfaces in de Vector Store-abstractie zijn het volgende.
com.microsoft.semantickernel.data.vectorstorage.VectorStore
VectorStore
bevat bewerkingen die alle verzamelingen in het vectorarchief omvatten, bijvoorbeeld listCollectionNames.
Het biedt ook de mogelijkheid om exemplaren op te halen VectorStoreRecordCollection<Key, Record>
.
com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection<Key, Record>
VectorStoreRecordCollection<Key, Record>
vertegenwoordigt een verzameling.
Deze verzameling bestaat al dan niet en de interface biedt methoden om te controleren of de verzameling bestaat, deze te maken of te verwijderen.
De interface biedt ook methoden voor upsert, ophalen en verwijderen van records.
Ten slotte neemt de interface over van het bieden van VectorizedSearch<Record>
vectorzoekmogelijkheden.
com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<Record>
VectorizedSearch<Record>
bevat een methode voor het uitvoeren van vectorzoekopdrachten.
VectorStoreRecordCollection<Key, Record>
neemt over van VectorizedSearch<Record>
het zelf gebruiken van het gebruik VectorizedSearch<Record>
ervan in gevallen waarin alleen zoeken nodig is en er geen record- of verzamelingsbeheer nodig is.
com.microsoft.semantickernel.data.vectorsearch.VectorizableTextSearch<Record>
VectorizableTextSearch<Record>
bevat een methode voor het uitvoeren van vectorzoekopdrachten waarbij de vectordatabase de mogelijkheid heeft om automatisch insluitingen te genereren. U kunt deze methode bijvoorbeeld aanroepen met een tekenreeks en de database genereert de insluiting voor u en zoekt op basis van een vectorveld. Dit wordt niet ondersteund door alle vectordatabases en wordt daarom alleen geïmplementeerd door selecte connectors.
Aan de slag met Vector Store-connectors
De benodigde nuget-pakketten importeren
Alle vector store-interfaces en eventuele abstractiegerelateerde klassen zijn beschikbaar in het Microsoft.Extensions.VectorData.Abstractions
nuget-pakket.
Elke vector store-implementatie is beschikbaar in een eigen nuget-pakket. Zie de pagina Out-of-the-box connectors voor een lijst met bekende implementaties.
Het abstractiespakket kan als volgt worden toegevoegd.
dotnet add package Microsoft.Extensions.VectorData.Abstractions --prerelease
Waarschuwing
Vanaf versie 1.23.0 van Semantische kernel zijn de Vector Store-abstracties verwijderd uit Microsoft.SemanticKernel.Abstractions
en zijn ze beschikbaar in het nieuwe toegewezen Microsoft.Extensions.VectorData.Abstractions
pakket.
Houd er rekening mee dat vanaf versie 1.23.0 een Microsoft.SemanticKernel.Abstractions
afhankelijkheid is, Microsoft.Extensions.VectorData.Abstractions
daarom is het niet nodig om naar extra pakketten te verwijzen.
De abstracties bevinden zich nu echter in de nieuwe Microsoft.Extensions.VectorData
naamruimte.
Wanneer u een upgrade uitvoert van 1.22.0 of eerder naar 1.23.0 of hoger, moet u een extra using Microsoft.Extensions.VectorData;
component toevoegen in bestanden waarin een van de Vector Store-abstractietypen wordt gebruikt, bijvoorbeeld IVectorStore
, IVectorStoreRecordCollection
, VectorStoreRecordDataAttribute
, VectorStoreRecordKeyProperty
, enzovoort.
Deze wijziging is aangebracht om vectorstoreproviders te ondersteunen bij het maken van hun eigen implementaties. Een provider hoeft alleen naar het Microsoft.Extensions.VectorData.Abstractions
pakket te verwijzen. Dit vermindert mogelijke versieconflicten en stelt Semantische kernel in staat om snel te blijven evolueren zonder dat dit van invloed is op vectorstoreproviders.
Uw gegevensmodel definiëren
De Semantische Kernel Vector Store-connectors maken gebruik van een model dat eerst met databases communiceert. Dit betekent dat de eerste stap is het definiëren van een gegevensmodel dat is toegewezen aan het opslagschema. Om de connectors te helpen verzamelingen records te maken en toe te wijzen aan het opslagschema, kan het model worden geannoteerd om de functie van elke eigenschap aan te geven.
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; }
}
Tip
Raadpleeg het definiëren van uw gegevensmodel voor meer informatie over het maken van aantekeningen bij uw gegevensmodel.
Tip
Raadpleeg voor een alternatief voor het maken van aantekeningen bij uw gegevensmodel het definiëren van uw schema met een recorddefinitie.
Verbinding maken met uw database en een verzameling selecteren
Zodra u uw gegevensmodel hebt gedefinieerd, is de volgende stap het maken van een VectorStore-exemplaar voor de database van uw keuze en het selecteren van een verzameling records.
In dit voorbeeld gebruiken we Qdrant. U moet daarom het Qdrant nuget-pakket importeren.
dotnet add package Microsoft.SemanticKernel.Connectors.Qdrant --prerelease
Omdat databases veel verschillende typen sleutels en records ondersteunen, kunt u het type sleutel en record voor uw verzameling opgeven met behulp van generics.
In ons geval is het type record de Hotel
klasse die we al hebben gedefinieerd en is het type sleutel ulong
, omdat de HotelId
eigenschap een ulong
is en Qdrant alleen ondersteuning biedt Guid
voor of ulong
sleutels ondersteunt.
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");
Omdat databases veel verschillende typen sleutels en records ondersteunen, kunt u het type sleutel en record voor uw verzameling opgeven met behulp van generics.
In ons geval is het type record de Hotel
klasse die we al hebben gedefinieerd en is het type sleutel str
, omdat de HotelId
eigenschap een str
is en Qdrant alleen ondersteuning biedt str
voor of int
sleutels ondersteunt.
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
)
Omdat databases veel verschillende typen sleutels en records ondersteunen, kunt u het type sleutel en record voor uw verzameling opgeven met behulp van generics.
In ons geval is het type record de Hotel
klasse die we al hebben gedefinieerd en het type sleutel is String
, omdat de hotelId
eigenschap een String
en JDBC-archief alleen sleutels ondersteunt String
.
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()
);
}
}
Tip
Raadpleeg de documentatie voor elke connector voor meer informatie over welke sleutel- en veldtypen elke Vector Store-connector ondersteunt.
De verzameling maken en records toevoegen
// 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);
De verzameling maken en records toevoegen
# 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();
Een vectorzoekopdracht uitvoeren
// 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());