Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Warnung
Die Funktionalität des Semantic Kernel Vector Store ist RC, und Verbesserungen, die Änderungen mit sich bringen, können in begrenzten Fällen vor der Veröffentlichung noch auftreten.
Warnung
Die Funktionalität des Semantic Kernel Vector Store befindet sich in der Vorschau, und Verbesserungen, die Änderungen erfordern, können in begrenzten Fällen vor der Veröffentlichung noch 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 semantische Kernel und .net bietet eine Abstraktion für die Interaktion mit Vector Stores und eine Liste von out-of-the-box-Implementierungen, die diese Abstraktionen für verschiedene Datenbanken 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.
Die sofort einsatzbereiten Implementierungen können mit semantischem Kernel verwendet werden, hängen aber nicht vom kernigen semantischen Kernelstapel ab und können daher auch bei Bedarf vollständig unabhängig verwendet werden. Die von Semantic Kernel bereitgestellten Implementierungen werden als "Konnektoren" bezeichnet.
Retrieval Augmented Generation (RAG) mit Vektorspeichern
Die Abstraktion des Vektorspeichers ist eine API auf niedriger Ebene zum Hinzufügen und Abrufen von Daten aus Vektorspeichern.
Semantic Kernel bietet integrierte Unterstützung für die Verwendung einer der Vector Store-Implementierungen für RAG.
Dies wird erreicht, indem „IVectorSearchable<TRecord>“ umschlossen und als Textsuche-Implementierung bereitgestellt wird.
Tipp
Um mehr darüber zu erfahren, wie Sie Vektorspeicher für RAG verwenden können, sehen Sie sich Vektorspeicher mit semantischer Kernel-Textsuche nutzen an.
Tipp
Weitere Informationen zur Textsuche finden Sie unter Was ist die semantische Kerneltextsuche?
Tipp
Weitere Informationen zum schnellen Hinzufügen von RAG zu Ihrem Agent finden Sie unter Hinzufügen von "Retrieval Augmented Generation (RAG)" zu semantischen Kernel-Agents.
Die Vektor-Store-Abstraktion
Die Vektorspeicherabstraktionen werden im Microsoft.Extensions.VectorData.Abstractions Nuget-Paket bereitgestellt.
Im Folgenden sind die wichtigsten abstrakten Basisklassen und Schnittstellen aufgeführt.
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 einige Eingaben annehmen, die durch einen registrierten Einbettungsgenerator oder durch die Vektordatenbank vektorisiert werden können, wenn die Datenbank dies unterstützt.
- Vektorsuchen, die einen Vektor als Eingabe übernehmen.
Retrieval Augmented Generation (RAG) mit Vektorspeichern
Die Vektorspeicherabstraktionen sind eine API auf niedriger Ebene zum Hinzufügen und Abrufen von Daten aus Vektorspeichern.
Semantic 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 und als Textsuche-Implementierung bereitgestellt wird.
Tipp
Um mehr darüber zu erfahren, wie Sie Vektorspeicher für RAG verwenden können, sehen Sie sich Vektorspeicher mit semantischer Kernel-Textsuche nutzen an.
Tipp
Weitere Informationen zur Textsuche finden Sie unter Was ist die semantische Kerneltextsuche?
Die Vektor-Store-Abstraktion
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<Schlüssel, Datensatz>
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 auch Methoden zum Upsert, Abrufen und Löschen von Datensätzen.
Schließlich erbt die Schnittstelle von „VectorizedSearch<Record>“ und bietet Vektorsuchfunktionen.
com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<Datensatz>
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.VectorizableTextSearch<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 Stores
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 Vektorspeicherabstraktionen 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 Implementierungen 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.vector import (
DistanceFunction,
IndexKind,
VectorStoreField,
vectorstoremodel,
)
@vectorstoremodel
@dataclass
class Hotel:
hotel_id: Annotated[str, VectorStoreField('key')] = field(default_factory=lambda: str(uuid4()))
hotel_name: Annotated[str, VectorStoreField('data', is_filterable=True)]
description: Annotated[str, VectorStoreField('data', is_full_text_searchable=True)]
description_embedding: Annotated[list[float], VectorStoreField('vector', dimensions=4, distance_function=DistanceFunction.COSINE, index_kind=IndexKind.HNSW)]
tags: Annotated[list[str], VectorStoreField('data', 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.qdrant import QdrantCollection
# Create a collection specify the type of key and record stored in it via Generic parameters.
collection: QdrantCollection[str, Hotel] = QdrantCollection(
record_type=Hotel,
collection_name="skhotels" # this is optional, you can also specify the collection_name in the vectorstoremodel decorator.
)
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 jede Vector Store-Implementierung unterstützt, finden Sie in der Dokumentation für jede Implementierung.
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.ensure_collection_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".
Durchführen einer Vektorsuche
// 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
Die Suchmethode kann verwendet werden, um nach Datensätzen in der Auflistung zu suchen. Sie verwendet entweder eine Zeichenkette, die dann mit Hilfe der Einbettungsgenerierung im Modell oder der Sammlung vektorisiert wird, oder einen bereits generierten Vektor.
# Do a search.
search_result = await collection.search("I'm looking for a hotel where customer happiness is the priority.", vector_property_name="description_embedding", top=3)
# Inspect the returned hotels.
async for result in search_result.results:
print(f"Found hotel description: {result.record.description}")
Erstellen einer Suchfunktion
Um eine einfache Suchfunktion zu erstellen, die zum Suchen nach Hotels verwendet werden kann, können Sie die create_search_function Methode für die Sammlung verwenden.
Der Name und die Beschreibung sowie die Namen und Beschreibungen der Parameter werden verwendet, um eine Funktionssignatur zu generieren, die beim Aufrufen von Funktionen an die LLM gesendet wird. Das bedeutet, dass das Anpassen dieser Einstellung hilfreich sein kann, damit das LLM den richtigen Funktionsaufruf erzeugt.
collection.create_search_function(
function_name="hotel_search",
description="A hotel search engine, allows searching for hotels in specific cities, "
"you do not have to specify that you are searching for hotels, for all, use `*`."
)
Es gibt viele andere Parameter, z. B. wie eine komplexere Version aussieht, beachten Sie die Anpassung der Parameter und die string_mapper Funktion, die zum Konvertieren des Datensatzes in eine Zeichenfolge verwendet wird.
from semantic_kernel.function import KernelParameterMetadata
collection.create_search_function(
function_name="hotel_search",
description="A hotel search engine, allows searching for hotels in specific cities, "
"you do not have to specify that you are searching for hotels, for all, use `*`.",
search_type="keyword_hybrid", # default is "vector"
parameters=[
KernelParameterMetadata(
name="query",
description="The terms you want to search for in the hotel database.",
type="str",
is_required=True,
type_object=str,
),
KernelParameterMetadata(
name="tags",
description="The tags you want to search for in the hotel database, use `*` to match all.",
type="str",
type_object=str,
default_value="*",
),
KernelParameterMetadata(
name="top",
description="Number of results to return.",
type="int",
default_value=5,
type_object=int,
),
],
# finally, we specify the `string_mapper` function that is used to convert the record to a string.
# This is used to make sure the relevant information from the record is passed to the LLM.
string_mapper=lambda x: f"Hotel {x.record.hotel_name}: {x.record.description}. Tags: {x.record.tags} (hotel_id: {x.record.hotel_id}) ",
)
Tipp
Weitere Beispiele, einschließlich End-to-End-Beispiele, finden Sie im Repository für semantische Kernelbeispiele.
// 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".