Číst v angličtině

Sdílet prostřednictvím


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

Upozornění

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 odporování si; projevují zaujatost nebo urážlivost. 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 úložišti vektorů a seznam standardní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.

Generace rozšířená o vyhledávání (RAG) s vektorovými databázemi

Abstrakce vektorového úložiště jsou rozhraní API nízké úrovně pro přidávání a načítání dat z úložišť vektorů. Sémantické jádro má integrovanou podporu pro použití jakékoli implementace Vector Store pro RAG. Toho dosáhnete tak, že zabalíte IVectorizedSearch<TRecord> a zobrazíte ho jako implementaci vyhledávání textu.

Tip

Další informace o použití vektorových úložišť pro RAG najdete v tématu "Jak používat vektorová úložiště se sémantickým vyhledáváním textu jádra".

Tip

Další informace o hledání textu najdete v tématu Co je vyhledávání textu v sémantickém jádru?

Abstrakce vektorového úložiště

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. Také umožňuje získat instance IVectorStoreRecordCollection<TKey, TRecord>.

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 vložení nebo aktualizaci, získání a odstranění záznamů. Nakonec rozhraní dědí z IVectorizedSearch<TRecord>, čímž zajišťuje možnosti 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í. Například tuto metodu můžete zavolat s textovým řetězcem, a databáze za vás vygeneruje embedování a prohledá vektorové pole. Tato funkce není podporována všemi vektorovými databázemi a proto je implementována pouze pomocí vybraných konektorů.

Generace rozšířená o vyhledávání (RAG) s vektorovými databázemi

Abstrakce vektorového úložiště jsou rozhraní API nízké úrovně pro přidávání a načítání dat z úložišť vektorů. Sémantické jádro má integrovanou podporu pro použití jakékoli implementace Vector Store pro RAG. Toho dosáhnete zabalením VectorSearchBase[TKey, TModel] pomocí VectorizedSearchMixin[Tmodel], VectorizableTextSearchMixin[TModel] nebo VectorTextSearch[TModel] a prezentováním jako implementace vyhledávání v textu.

Tip

Další informace o použití vektorových úložišť pro RAG najdete v tématu "Jak používat vektorová úložiště se sémantickým vyhledáváním textu jádra".

Tip

Další informace o hledání textu najdete v tématu Co je vyhledávání textu v sémantickém jádru?

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 vložení nebo aktualizaci, získání a odstranění záznamů. Nakonec rozhraní dědí z VectorizedSearch<Record>, což poskytuje funkce 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 použít s textovým řetězcem a databáze automaticky vygeneruje embedding a prohledá 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. Navštivte stránku Hotové konektory pro seznam známých implementací.

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

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

Upozornění

Od verze 1.23.0 sémantického jádra byly abstrakce Vector Store odebrány z Microsoft.SemanticKernel.Abstractions a jsou k dispozici v novém speciálním balíčku Microsoft.Extensions.VectorData.Abstractions.

Všimněte si, že od verze 1.23.0 má Microsoft.SemanticKernel.Abstractions 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.CosineSimilarity, 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

Alternativou k přidání poznámek k vašemu datovému modelu je definování schématu pomocí definice 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

Pokud chcete spustit Qdrant místně pomocí Dockeru, pomocí následujícího příkazu spusťte kontejner Qdrant s nastavením použitým v tomto příkladu.

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

Pokud chcete ověřit, že je vaše instance Qdrant spuštěná a funguje správně, přejděte na řídicí panel Qdrant, který je integrovaný do kontejneru Dockeru Qdrant: http://localhost:6333/dashboard

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 typem záznamu třída Hotel, kterou jsme již definovali, a typem klíče bude ulong, protože vlastnost HotelId je ulong a Qdrant podporuje pouze klíče typu Guid nebo ulong.

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 třídou Hotel, kterou jsme již definovali, a typ klíče bude str, protože vlastnost HotelId je str a Qdrant podporuje pouze klíče typu str nebo int.

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ů

// 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.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.
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 generovat embeddingy, najdete v sekci vytváření embeddingů.

// 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 = await collection.VectorizedSearchAsync(searchVector, new() { Top = 1 });

// Inspect the returned hotel.
await foreach (var record in searchResult.Results)
{
    Console.WriteLine("Found hotel description: " + record.Record.Description);
    Console.WriteLine("Found record score: " + record.Score);
}

Hledání vektorů

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

Tip

Další informace o tom, jak generovat embeddingy, najdete v tématu generování embeddingů.

Další kroky