Dela via


Vad är Semantic Kernel Vector Store-anslutningsappar? (Förhandsversion)

Varning

Funktionen Semantic Kernel Vector Store är i förhandsversion, och förbättringar som kräver icke-bakåtkompatibla ändringar kan fortfarande ske under begränsade omständigheter före lanseringen.

Dricks

Om du letar efter information om de äldre minneslagringsanslutningarna kan du gå till sidan Minneslager.

Vektordatabaser har många användningsfall i olika domäner och program som omfattar bearbetning av naturligt språk (NLP), visuellt innehåll (CV), rekommendationssystem (RS) och andra områden som kräver semantisk förståelse och matchning av data.

Ett användningsfall för att lagra information i en vektordatabas är att göra det möjligt för stora språkmodeller att generera mer relevanta och sammanhängande svar. Stora språkmodeller står ofta inför utmaningar som att generera felaktig eller irrelevant information. bristande faktisk konsekvens eller sunt förnuft. upprepa eller motsäga sig själva. partisk eller stötande. För att lösa dessa utmaningar kan du använda en vektordatabas för att lagra information om olika ämnen, nyckelord, fakta, åsikter och/eller källor relaterade till din önskade domän eller genre. Med vektordatabasen kan du effektivt hitta den delmängd av information som är relaterad till en viss fråga eller ett visst ämne. Du kan sedan skicka information från vektordatabasen med din uppmaning till din stora språkmodell för att generera mer exakt och relevant innehåll.

Om du till exempel vill skriva ett blogginlägg om de senaste trenderna inom AI kan du använda en vektordatabas för att lagra den senaste informationen om det ämnet och skicka informationen tillsammans med begäran till en LLM för att generera ett blogginlägg som utnyttjar den senaste informationen.

Semantisk kernel och .net tillhandahåller en abstraktion för interaktion med Vector Stores och en lista över färdiga anslutningsappar som implementerar dessa abstraktioner. Funktionerna omfattar att skapa, lista och ta bort samlingar av poster och ladda upp, hämta och ta bort poster. Abstraktionen gör det enkelt att experimentera med ett kostnadsfritt eller lokalt värdbaserat Vector Store och sedan växla till en tjänst när du behöver skala upp.

Abstraktion av vektorlager

Huvudgränssnitten i abstraktionen för Vector Store är följande.

Microsoft.Extensions.VectorData.IVectorStore

IVectorStore innehåller åtgärder som sträcker sig över alla samlingar i vektorarkivet, t.ex. ListCollectionNames. Det ger också möjlighet att hämta IVectorStoreRecordCollection<TKey, TRecord> instanser.

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

IVectorStoreRecordCollection<TKey, TRecord> representerar en samling. Den här samlingen kanske eller kanske inte finns, och gränssnittet innehåller metoder för att kontrollera om samlingen finns, skapa den eller ta bort den. Gränssnittet innehåller också metoder för att öka, hämta och ta bort poster. Slutligen ärver gränssnittet från IVectorizedSearch<TRecord> att tillhandahålla vektorsökningsfunktioner.

Microsoft.Extensions.VectorData.IVectorizedSearch<TRecord>

IVectorizedSearch<TRecord> innehåller en metod för att göra vektorsökningar. IVectorStoreRecordCollection<TKey, TRecord> ärver från IVectorizedSearch<TRecord> att göra det möjligt att använda IVectorizedSearch<TRecord> på egen hand i fall där endast sökning behövs och ingen hantering av poster eller samling behövs.

IVectorizableTextSearch<TRecord>

IVectorizableTextSearch<TRecord> innehåller en metod för att göra vektorsökningar där vektordatabasen har möjlighet att generera inbäddningar automatiskt. Du kan till exempel anropa den här metoden med en textsträng och databasen genererar inbäddningen åt dig och söker mot ett vektorfält. Detta stöds inte av alla vektordatabaser och implementeras därför endast av utvalda anslutningsappar.

Abstraktion av vektorlager

Huvudgränssnitten i abstraktionen för Vector Store är följande.

com.microsoft.semantickernel.data.vectorstorage.VectorStore

VectorStore innehåller åtgärder som sträcker sig över alla samlingar i vektorarkivet, t.ex. listCollectionNames. Det ger också möjlighet att hämta VectorStoreRecordCollection<Key, Record> instanser.

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

VectorStoreRecordCollection<Key, Record> representerar en samling. Den här samlingen kanske eller kanske inte finns, och gränssnittet innehåller metoder för att kontrollera om samlingen finns, skapa den eller ta bort den. Gränssnittet innehåller också metoder för att öka, hämta och ta bort poster. Slutligen ärver gränssnittet från VectorizedSearch<Record> att tillhandahålla vektorsökningsfunktioner.

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

VectorizedSearch<Record> innehåller en metod för att göra vektorsökningar. VectorStoreRecordCollection<Key, Record> ärver från VectorizedSearch<Record> att göra det möjligt att använda VectorizedSearch<Record> på egen hand i fall där endast sökning behövs och ingen hantering av poster eller samling behövs.

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

VectorizableTextSearch<Record> innehåller en metod för att göra vektorsökningar där vektordatabasen har möjlighet att generera inbäddningar automatiskt. Du kan till exempel anropa den här metoden med en textsträng och databasen genererar inbäddningen åt dig och söker mot ett vektorfält. Detta stöds inte av alla vektordatabaser och implementeras därför endast av utvalda anslutningsappar.

Komma igång med Vector Store-anslutningsappar

Importera nödvändiga nuget-paket

Alla gränssnitt för vektorlager och eventuella abstraktionsrelaterade klasser är tillgängliga i nuget-paketet Microsoft.Extensions.VectorData.Abstractions . Implementeringen av varje vektorlager är tillgänglig i ett eget nuget-paket. En lista över kända implementeringar finns på sidan Färdiga anslutningsappar.

Abstraktionspaketet kan läggas till så här.

dotnet add package Microsoft.Extensions.VectorData.Abstractions --prerelease

Varning

Från version 1.23.0 av Semantic Kernel har vector store-abstraktionerna tagits bort från Microsoft.SemanticKernel.Abstractions och är tillgängliga i det nya dedikerade Microsoft.Extensions.VectorData.Abstractions paketet.

Observera att från version 1.23.0 Microsoft.SemanticKernel.Abstractions har ett beroende av Microsoft.Extensions.VectorData.Abstractions, därför finns det inget behov av att referera till ytterligare paket. Abstraktionerna kommer dock nu att finnas i det nya Microsoft.Extensions.VectorData namnområdet.

När du uppgraderar från 1.22.0 eller tidigare till 1.23.0 eller senare måste du lägga till ytterligare en using Microsoft.Extensions.VectorData; sats i filer där någon av abstraktionstyperna för Vector Store används, t.ex. IVectorStore, IVectorStoreRecordCollection, VectorStoreRecordDataAttribute, VectorStoreRecordKeyPropertyosv.

Den här ändringen har gjorts för att stödja leverantörer av vektorlager när de skapar sina egna implementeringar. En provider behöver bara referera Microsoft.Extensions.VectorData.Abstractions till paketet. Detta minskar potentiella versionskonflikter och gör att semantisk kernel kan fortsätta att utvecklas snabbt utan att påverka leverantörer av vektorlager.

Definiera din datamodell

Anslutningsappar för semantisk kernelvektorlagring använder en modell för att interagera med databaser. Det innebär att det första steget är att definiera en datamodell som mappar till lagringsschemat. För att hjälpa anslutningsapparna att skapa samlingar av poster och mappa till lagringsschemat kan modellen kommenteras för att ange funktionen för varje egenskap.

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

Dricks

Mer information om hur du kommenterar din datamodell finns i definiera datamodellen.

Dricks

Ett alternativ till att kommentera datamodellen finns i definiera schemat med en postdefinition.

Anslut till databasen och välj en samling

När du har definierat datamodellen är nästa steg att skapa en VectorStore-instans för valfri databas och välja en samling poster.

I det här exemplet använder vi Qdrant. Du måste därför importera Qdrant-nuget-paketet.

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

Eftersom databaser stöder många olika typer av nycklar och poster kan du ange typ av nyckel och post för din samling med hjälp av generiska objekt. I vårt fall är typen av post den Hotel klass som vi redan har definierat, och typen av nyckel blir ulong, eftersom HotelId egenskapen är en ulong och Qdrant endast stöder Guid eller ulong nycklar.

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

Eftersom databaser stöder många olika typer av nycklar och poster kan du ange typ av nyckel och post för din samling med hjälp av generiska objekt. I vårt fall är typen av post den Hotel klass som vi redan har definierat, och typen av nyckel blir str, eftersom HotelId egenskapen är en str och Qdrant endast stöder str eller int nycklar.

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
)

Eftersom databaser stöder många olika typer av nycklar och poster kan du ange typ av nyckel och post för din samling med hjälp av generiska objekt. I vårt fall är typen av post den Hotel klass som vi redan har definierat, och typen av nyckel blir String, eftersom hotelId egenskapen är ett String och JDBC-arkivet endast stöder String nycklar.

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

Dricks

Mer information om vilka nyckel- och fälttyper som varje Vector Store-anslutningsprogram stöder finns i dokumentationen för varje anslutningsapp.

Skapa samlingen och lägg till poster

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

Skapa samlingen och lägg till poster

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

Dricks

Mer information om hur du genererar inbäddningar finns i generering av inbäddning.

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

Dricks

Mer information om hur du genererar inbäddningar finns i generering av inbäddning.

Nästa steg