Freigeben über


Was sind Semantic Kernel Vector Store Connectors? (Vorschau)

Warnung

Die Funktionalität des semantischen Kernelvektorspeichers befindet sich in der Vorschau, und Verbesserungen, die fehlerhafte Änderungen erfordern, können unter begrenzten Umständen noch vor der Veröffentlichung auftreten.

Warnung

Die Funktionalität des semantischen Kernelvektorspeichers befindet sich in der Vorschau, und Verbesserungen, die fehlerhafte Änderungen erfordern, können unter begrenzten Umständen noch vor der Veröffentlichung auftreten.

Tipp

Wenn Sie nach Informationen zu den älteren Memory Store-Konnektoren suchen, lesen Sie die Seite "Memory Stores".

Vektordatenbanken haben viele Anwendungsfälle in verschiedenen Domänen und Anwendungen, die die Verarbeitung natürlicher Sprachen (Natural Language Processing, NLP), Computer vision (CV), Empfehlungssysteme (RS) und andere Bereiche umfassen, die semantisches Verständnis und Abgleich von Daten erfordern.

Ein Anwendungsfall zum Speichern von Informationen in einer Vektordatenbank besteht darin, großen Sprachmodellen (LLMs) die Generierung relevanterer und kohärenterer Antworten zu ermöglichen. Große Sprachmodelle stellen sich häufig vor Herausforderungen, z. B. das Generieren ungenauer oder irrelevanter Informationen; fehlende sachliche Konsistenz oder Allgemeinverstand; sich wiederholen oder widersprechen; sie sind voreingenommen oder anstößig. Um diese Herausforderungen zu überwinden, können Sie eine Vektordatenbank verwenden, um Informationen zu verschiedenen Themen, Schlüsselwörtern, Fakten, Meinungen und/oder Quellen im Zusammenhang mit Ihrer gewünschten Domäne oder Ihrem Genre zu speichern. Mit der Vektordatenbank können Sie die Teilmenge der Informationen, die sich auf eine bestimmte Frage oder ein bestimmtes Thema beziehen, effizient finden. Anschließend können Sie Informationen aus der Vektordatenbank mit Ihrem Prompt an Ihr großes Sprachmodell weitergeben, um genauere und relevantere Inhalte zu generieren.

Wenn Sie beispielsweise einen Blogbeitrag zu den neuesten Trends in KI schreiben möchten, können Sie eine Vektordatenbank verwenden, um die neuesten Informationen zu diesem Thema zu speichern und die Informationen zusammen mit der Anforderung an eine LLM zu übergeben, um einen Blogbeitrag zu generieren, der die neuesten Informationen nutzt.

Der Semantic Kernel und .NET bieten eine Abstraktion für die Interaktion mit Vector Stores sowie eine Liste von sofort einsatzbereiten Connectors, die diese Abstraktionen implementieren. Zu den Features gehören das Erstellen, Auflisten und Löschen von Auflistungen von Datensätzen sowie das Hochladen, Abrufen und Löschen von Datensätzen. Die Abstraktion erleichtert das Experimentieren mit einem kostenlosen oder lokal gehosteten Vector Store und ermöglicht bei Bedarf ein Wechsel zu einem Dienst, wenn eine Skalierung erforderlich ist.

Wiederabruf-unterstützte Generierung (RAG) mit Vektorspeichern

Die Vektorspeicherabstraktionen sind eine API auf niedriger Ebene zum Hinzufügen und Abrufen von Daten aus Vektorspeichern. Der Semantische Kernel bietet integrierte Unterstützung für die Verwendung einer der Vector Store-Implementierungen für RAG. Dies wird erreicht, indem IVectorSearchable<TRecord> umbrochen wird und als Textsuchimplementierung bereitgestellt wird.

Tipp

Weitere Informationen zur Verwendung von Vektorspeichern für RAG finden Sie unter Verwenden von Vektorspeichern mit semantischer Kernel-Textsuche.

Tipp

Weitere Informationen zur Textsuche finden Sie unter Was ist die semantische Kerneltextsuche?

Abstraktion des Vektorspeichers

Die wichtigsten abstrakten Basisklassen und Schnittstellen in der Vektorspeicher-Abstraktion sind die folgenden:

Microsoft.Extensions.VectorData.VectorStore

VectorStore enthält Vorgänge, die sich über alle Auflistungen im Vektorspeicher erstrecken, z. B. ListCollectionNames. Es bietet auch die Möglichkeit, VectorStoreCollection<TKey, TRecord>-Instanzen abzurufen.

Microsoft.Extensions.VectorData.VectorStoreCollection<TKey, TRecord>

VectorStoreCollection<TKey, TRecord> stellt eine Auflistung dar. Diese Auflistung ist möglicherweise vorhanden oder nicht vorhanden, und die abstrakte Basisklasse stellt Methoden bereit, um zu überprüfen, ob die Auflistung vorhanden ist, sie zu erstellen oder zu löschen. Die abstrakte Basisklasse stellt außerdem Methoden zum Upsert-, Abrufen und Löschen von Datensätzen bereit. Schließlich erbt die abstrakte Basisklasse von der Bereitstellung von IVectorSearchable<TRecord> Vektorsuchfunktionen.

Microsoft.Extensions.VectorData.IVectorSearchable<TRecord>

  • SearchAsync<TRecord> kann für eine der folgenden Aktionen verwendet werden:
    • Vektorsuchen, die Eingaben annehmen, die von einem registrierten Einbettungsgenerator oder von der Vektordatenbank vektorisiert werden können, sofern die Datenbank dies unterstützt.
    • Vektorsuchen, die einen Vektor als Eingabe übernehmen.

Wiederabruf-unterstützte Generierung (RAG) mit Vektorspeichern

Die Vektorspeicherabstraktionen sind eine API auf niedriger Ebene zum Hinzufügen und Abrufen von Daten aus Vektorspeichern. Der Semantische Kernel bietet integrierte Unterstützung für die Verwendung einer der Vector Store-Implementierungen für RAG. Dies wird erreicht, indem VectorSearchBase[TKey, TModel] entweder mit VectorizedSearchMixin[Tmodel], VectorizableTextSearchMixin[TModel] oder VectorTextSearch[TModel] umschlossen wird und als Textsuche-Implementierung verfügbar gemacht wird.

Tipp

Weitere Informationen zur Verwendung von Vektorspeichern für RAG finden Sie unter Verwenden von Vektorspeichern mit semantischer Kernel-Textsuche.

Tipp

Weitere Informationen zur Textsuche finden Sie unter Was ist die semantische Kerneltextsuche?

Abstraktion des Vektorspeichers

Die wichtigsten Schnittstellen in der Vektorspeicher-Abstraktion sind die folgenden.

com.microsoft.semantickernel.data.vectorstorage.VectorStore

VectorStore enthält Vorgänge, die sich über alle Auflistungen im Vektorspeicher erstrecken, z. B. listCollectionNames. Es bietet auch die Möglichkeit, VectorStoreRecordCollection<Key, Record>-Instanzen abzurufen.

com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection<Key, Record>

VectorStoreRecordCollection<Key, Record> stellt eine Auflistung dar. Diese Auflistung ist möglicherweise vorhanden oder nicht vorhanden, und die Schnittstelle stellt Methoden bereit, um zu überprüfen, ob die Auflistung vorhanden ist, sie zu erstellen oder zu löschen. Die Schnittstelle bietet außerdem Methoden zum Hinzufügen oder Aktualisieren, Abrufen und Löschen von Datensätzen. Schließlich erbt die Schnittstelle von der Bereitstellung von VectorizedSearch<Record> Vektorsuchfunktionen.

com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<Record>

VectorizedSearch<Record> enthält eine Methode zum Ausführen von Vektorsuchen. VectorStoreRecordCollection<Key, Record> erbt von VectorizedSearch<Record>, wodurch es möglich ist, VectorizedSearch<Record> eigenständig in Fällen zu verwenden, in denen nur eine Suche erforderlich ist und keine Datensatz- oder Sammlungsverwaltung benötigt wird.

com.microsoft.semantickernel.data.vectorsearch.VectorisierbarerTextSuche<Datensatz>

VectorizableTextSearch<Record> enthält eine Methode zum Ausführen von Vektorsuchen, bei denen die Vektordatenbank die Möglichkeit hat, Einbettungen automatisch zu generieren. Sie können diese Methode z. B. mit einer Textzeichenfolge aufrufen, und die Datenbank generiert die Einbettung für Sie und sucht nach einem Vektorfeld. Dies wird nicht von allen Vektordatenbanken unterstützt und wird daher nur von ausgewählten Connectors implementiert.

Erste Schritte mit Vector Store-Connectors

Importieren der erforderlichen Nuget-Pakete

Alle Vektorspeicherschnittstellen und alle zugehörigen Abstraktionsklassen sind im Microsoft.Extensions.VectorData.Abstractions Nuget-Paket verfügbar. Jede Vektorspeicherimplementierung ist in einem eigenen Nuget-Paket verfügbar. Eine Liste bekannter Implementierungen finden Sie auf der Seite "Out-of-the-box connectors".

Das Abstraktionspaket kann wie folgt hinzugefügt werden.

dotnet add package Microsoft.Extensions.VectorData.Abstractions

Definieren des Datenmodells

Die Connectors für den semantischen Kernelvektorspeicher verwenden zunächst einen Modellansatz für die Interaktion mit Datenbanken. Dies bedeutet, dass der erste Schritt darin besteht, ein Datenmodell zu definieren, das dem Speicherschema zugeordnet ist. Damit die Connectors Sammlungen von Datensätzen erstellen und dem Speicherschema zugeordnet werden können, kann das Modell kommentiert werden, um die Funktion jeder Eigenschaft anzugeben.

using Microsoft.Extensions.VectorData;

public class Hotel
{
    [VectorStoreKey]
    public ulong HotelId { get; set; }

    [VectorStoreData(IsIndexed = true)]
    public string HotelName { get; set; }

    [VectorStoreData(IsFullTextIndexed = true)]
    public string Description { get; set; }

    [VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
    public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }

    [VectorStoreData(IsIndexed = 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; }
}

Tipp

Weitere Informationen zum Kommentieren des Datenmodells finden Sie unter Definieren des Datenmodells.

Tipp

Eine Alternative zum Kommentieren des Datenmodells finden Sie unter Definieren des Schemas mit einer Datensatzdefinition.

Stellen Sie eine Verbindung mit Ihrer Datenbank her, und wählen Sie eine Sammlung aus.

Nachdem Sie Das Datenmodell definiert haben, besteht der nächste Schritt darin, eine VectorStore-Instanz für die Datenbank Ihrer Wahl zu erstellen und eine Sammlung von Datensätzen auszuwählen.

In diesem Beispiel verwenden wir Qdrant. Daher müssen Sie das Qdrant Nuget-Paket importieren.

dotnet add package Microsoft.SemanticKernel.Connectors.Qdrant --prerelease

Wenn Sie Qdrant lokal mit Docker ausführen möchten, verwenden Sie den folgenden Befehl, um den Qdrant-Container mit den in diesem Beispiel verwendeten Einstellungen zu starten.

docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant:latest

Um zu überprüfen, ob Ihre Qdrant-Instanz ordnungsgemäß ausgeführt wird, besuchen Sie das Qdrant-Dashboard, das in den Qdrant-Docker-Container integriert ist: http://localhost:6333/dashboard

Da Datenbanken viele verschiedene Arten von Schlüsseln und Datensätzen unterstützen, können Sie den Schlüssel- und Datensatztyp für Ihre Sammlung mithilfe von Generika angeben. In unserem Fall ist der Typ des Datensatzes die Hotel Klasse, die wir bereits definiert haben, und der Schlüsseltyp ist ulong, da die HotelId Eigenschaft ein ulong ist und Qdrant nur Guid oder ulong Schlüssel unterstützt.

using Microsoft.SemanticKernel.Connectors.Qdrant;
using Qdrant.Client;

// Create a Qdrant VectorStore object
var vectorStore = new QdrantVectorStore(new QdrantClient("localhost"), ownsClient: true);

// 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");

Da Datenbanken viele verschiedene Arten von Schlüsseln und Datensätzen unterstützen, können Sie den Schlüssel- und Datensatztyp für Ihre Sammlung mithilfe von Generika angeben. In unserem Fall ist der Typ des Datensatzes die Hotel Klasse, die wir bereits definiert haben, und der Schlüsseltyp ist str, da die HotelId Eigenschaft ein str ist und Qdrant nur str oder int Schlüssel unterstützt.

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
)

Da Datenbanken viele verschiedene Arten von Schlüsseln und Datensätzen unterstützen, können Sie den Schlüssel- und Datensatztyp für Ihre Sammlung mithilfe von Generika angeben. In unserem Fall ist der Typ des Datensatzes die Hotel Klasse, die wir bereits definiert haben, und der Schlüsseltyp lautet String, da die hotelId Eigenschaft ein String ist und JDBC-Speicher nur String-Schlüssel unterstützt.

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()
        );
    }
}

Tipp

Weitere Informationen dazu, welche Schlüssel- und Feldtypen jeder Vector Store-Connector unterstützt, finden Sie in der Dokumentation für jeden Connector.

Erstellen der Sammlung und Hinzufügen von Datensätzen

// Placeholder embedding generation method.
async Task<ReadOnlyMemory<float>> GenerateEmbeddingAsync(string textToVectorize)
{
    // your logic here
}

// Create the collection if it doesn't exist yet.
await collection.EnsureCollectionExistsAsync();

// 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.
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);

Erstellen der Sammlung und Hinzufügen von Datensätzen

# 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();

Tipp

Weitere Informationen zum Generieren von Einbettungen finden Sie unter "Einbettungsgenerierung".

// Placeholder embedding generation method.
async Task<ReadOnlyMemory<float>> GenerateEmbeddingAsync(string textToVectorize)
{
    // your logic here
}

// 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.
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);
}

Durchführen einer Vektorsuche

# Generate a vector for your search text, using your chosen embedding generation implementation.
# Just showing a placeholder method here for brevity.
search_vector = await GenerateEmbedding("I'm looking for a hotel where customer happiness is the priority.");
# Do the search.
search_result = await collection.vectorized_search(vector=searchVector, VectorSearchOptions(top = 1 ))

# Inspect the returned hotels.
async for result in search_result.results:
    print(f"Found hotel description: {result.record.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());

Tipp

Weitere Informationen zum Generieren von Einbettungen finden Sie unter "Einbettungsgenerierung".

Nächste Schritte