Sdílet prostřednictvím


Co jsou konektory sémantického úložiště vektorů jádra? (Preview)

Upozorňující

Funkce sémantického úložiště vektorů jádra je ve verzi Preview a vylepšení, která vyžadují zásadní změny, se můžou vyskytovat za omezených okolností před vydáním.

Tip

Pokud hledáte informace o starších konektorech úložiště paměti, podívejte se na stránku Úložiště paměti.

Vektorové databáze mají mnoho případů použití v různých doménách a aplikacích, které zahrnují zpracování přirozeného jazyka (NLP), počítačové zpracování obrazu (CV), systémy doporučení (RS) a další oblasti, které vyžadují sémantické porozumění a porovnávání dat.

Jedním z případů použití pro ukládání informací do vektorové databáze je umožnit velkým jazykovým modelům (LLM) generovat relevantnější a koherentní odpovědi. Velké jazykové modely často čelí výzvám, jako je generování nepřesných nebo irelevantních informací; nedostatek faktické konzistence nebo běžného rozumu; opakování nebo v rozporu se sebou; být zkreslený nebo urážlivý. Pokud chcete tyto výzvy překonat, můžete pomocí vektorové databáze ukládat informace o různých tématech, klíčových slovech, faktech, názorech a zdrojích souvisejících s požadovanou doménou nebo žánrem. Vektorová databáze umožňuje efektivně najít podmnožinu informací souvisejících s konkrétní otázkou nebo tématem. Pak můžete předat informace z vektorové databáze s výzvou k vytvoření přesnějšího a relevantnějšího obsahu ve velkém jazykovém modelu.

Pokud například chcete napsat blogový příspěvek o nejnovějších trendech v AI, můžete použít vektorovou databázi k uložení nejnovějších informací o tomto tématu a předání informací spolu s dotazem na LLM, aby se vygeneroval blogový příspěvek, který využívá nejnovější informace.

Sémantické jádro a .net poskytují abstrakci pro interakci s vektorovými úložišti a seznam předpočinkových konektorů, které tyto abstrakce implementují. Mezi funkce patří vytváření, výpis a odstraňování kolekcí záznamů a nahrávání, načítání a odstraňování záznamů. Abstrakce usnadňuje experimentování s bezplatným nebo místně hostovaným Vector Storem a následným přepnutím na službu, když potřebujete vertikálně navýšit kapacitu.

Abstrakce úložiště vektorů

Hlavní rozhraní abstrakce vektorového úložiště jsou následující.

Microsoft.Extensions.VectorData.IVectorStore

IVectorStore obsahuje operace, které pokrývají všechny kolekce v úložišti vektorů, například ListCollectionNames. Poskytuje také možnost získat IVectorStoreRecordCollection<TKey, TRecord> instance.

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

IVectorStoreRecordCollection<TKey, TRecord> představuje kolekci. Tato kolekce může nebo nemusí existovat a rozhraní poskytuje metody pro kontrolu, zda kolekce existuje, vytvořit ji nebo odstranit. Rozhraní také poskytuje metody pro upsertování, získání a odstranění záznamů. Nakonec rozhraní dědí z IVectorizedSearch<TRecord> poskytování funkcí vektorového vyhledávání.

Microsoft.Extensions.VectorData.IVectorizedSearch<TRecord>

IVectorizedSearch<TRecord> obsahuje metodu pro provádění vektorových hledání. IVectorStoreRecordCollection<TKey, TRecord> dědí od IVectorizedSearch<TRecord> toho, aby bylo možné použít IVectorizedSearch<TRecord> samostatně v případech, kdy je potřeba pouze hledat a není potřeba žádná správa záznamů nebo kolekcí.

IVectorizableTextSearch<TRecord>

IVectorizableTextSearch<TRecord> obsahuje metodu pro vyhledávání vektorů, ve kterých má vektorová databáze schopnost automaticky generovat vkládání. Tuto metodu můžete například volat s textovým řetězcem a databáze vygeneruje vkládání za vás a prohledává vektorové pole. Tato funkce není podporována všemi vektorovými databázemi a proto je implementována pouze pomocí vybraných konektorů.

Abstrakce úložiště vektorů

Hlavní rozhraní abstrakce vektorového úložiště jsou následující.

com.microsoft.semantickernel.data.vectorstorage.VectorStore

VectorStore obsahuje operace, které pokrývají všechny kolekce v úložišti vektorů, například listCollectionNames. Poskytuje také možnost získat VectorStoreRecordCollection<Key, Record> instance.

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

VectorStoreRecordCollection<Key, Record> představuje kolekci. Tato kolekce může nebo nemusí existovat a rozhraní poskytuje metody pro kontrolu, zda kolekce existuje, vytvořit ji nebo odstranit. Rozhraní také poskytuje metody pro upsertování, získání a odstranění záznamů. Nakonec rozhraní dědí z VectorizedSearch<Record> poskytování funkcí vektorového vyhledávání.

com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<– záznam>

VectorizedSearch<Record> obsahuje metodu pro provádění vektorových hledání. VectorStoreRecordCollection<Key, Record> dědí od VectorizedSearch<Record> toho, aby bylo možné použít VectorizedSearch<Record> samostatně v případech, kdy je potřeba pouze hledat a není potřeba žádná správa záznamů nebo kolekcí.

com.microsoft.semantickernel.data.vectorsearch.VectorizableTextSearch<– záznam>

VectorizableTextSearch<Record> obsahuje metodu pro vyhledávání vektorů, ve kterých má vektorová databáze schopnost automaticky generovat vkládání. Tuto metodu můžete například volat s textovým řetězcem a databáze vygeneruje vkládání za vás a prohledává vektorové pole. Tato funkce není podporována všemi vektorovými databázemi a proto je implementována pouze pomocí vybraných konektorů.

Začínáme s konektory služby Vector Store

Import potřebných balíčků NuGet

Všechna rozhraní úložiště vektorů a všechny abstrakce související třídy jsou k dispozici v Microsoft.Extensions.VectorData.Abstractions balíčku nuget. Každá implementace úložiště vektorů je k dispozici ve vlastním balíčku NuGet. Seznamznámýchch

Balíček abstrakcí lze přidat takto.

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

Upozorňující

Z verze 1.23.0 sémantického jádra byly abstrakce vektorového úložiště odebrány Microsoft.SemanticKernel.Abstractions a jsou k dispozici v novém vyhrazeném Microsoft.Extensions.VectorData.Abstractions balíčku.

Všimněte si, Microsoft.SemanticKernel.Abstractions že od verze 1.23.0 je závislost na Microsoft.Extensions.VectorData.Abstractions, a proto není nutné odkazovat na další balíčky. Abstrakce ale budou v novém Microsoft.Extensions.VectorData oboru názvů.

Při upgradu z verze 1.22.0 nebo starší na verzi 1.23.0 nebo novější budete muset do souborů přidat další using Microsoft.Extensions.VectorData; klauzuli, ve které se používají některé typy abstrakce služby Vector Store, například IVectorStore, IVectorStoreRecordCollection, VectorStoreRecordDataAttribute, VectorStoreRecordKeyProperty, atd.

Tato změna byla provedena kvůli podpoře poskytovatelů vektorových úložiště při vytváření vlastních implementací. Zprostředkovatel musí odkazovat pouze na Microsoft.Extensions.VectorData.Abstractions balíček. To snižuje potenciální konflikty verzí a umožňuje sémantickému jádru pokračovat v rychlém vývoji, aniž by to mělo vliv na zprostředkovatele úložiště vektorů.

Definování datového modelu

Konektory sémantického úložiště vektorů jádra používají první přístup modelu k interakci s databázemi. To znamená, že prvním krokem je definování datového modelu, který se mapuje na schéma úložiště. Aby konektory pomohly vytvářet kolekce záznamů a mapovat na schéma úložiště, může být model opatřen poznámkami k označení funkce jednotlivých vlastností.

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

Další informace o tom, jak anotovat datový model, najdete v tématu definování datového modelu.

Tip

Alternativu k přidávání poznámek k datovému modelu najdete v definování schématu s definicí záznamu.

Připojte se k databázi a vyberte kolekci.

Jakmile definujete datový model, dalším krokem je vytvoření instance VectorStore pro databázi podle vašeho výběru a výběr kolekce záznamů.

V tomto příkladu použijeme Qdrant. Proto budete muset importovat balíček nuget Qdrant.

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

Vzhledem k tomu, že databáze podporují mnoho různých typů klíčů a záznamů, umožňujeme určit typ klíče a záznamu pro vaši kolekci pomocí obecných typů. V našem případě bude typ záznamu Hotel třídou, již jsme definovali, a typ klíče bude ulong, protože HotelId vlastnost je ulong a Qdrant podporuje Guid pouze nebo ulong klíče.

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

Vzhledem k tomu, že databáze podporují mnoho různých typů klíčů a záznamů, umožňujeme určit typ klíče a záznamu pro vaši kolekci pomocí obecných typů. V našem případě bude typ záznamu Hotel třídou, již jsme definovali, a typ klíče bude str, protože HotelId vlastnost je str a Qdrant podporuje str pouze nebo int klíče.

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
)

Vzhledem k tomu, že databáze podporují mnoho různých typů klíčů a záznamů, umožňujeme určit typ klíče a záznamu pro vaši kolekci pomocí obecných typů. V našem případě bude typ záznamu Hotel třídou, již jsme definovali, a typ klíče bude String, protože hotelId vlastnost je String a úložiště JDBC podporuje String pouze klíče.

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

Další informace o tom, jaké typy klíčů a polí každý konektor Vector Store podporuje, najdete v dokumentaci ke každému konektoru.

Vytvoření kolekce a přidání záznamů

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

Vytvoření kolekce a přidání záznamů

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

Tip

Další informace o tom, jak vygenerovat vkládání, najdete v tématu generování vkládání.

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

Tip

Další informace o tom, jak vygenerovat vkládání, najdete v tématu generování vkládání.

Další kroky