Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Upozornění
Funkce sémantického úložiště vektorů jádra je RC a vylepšení, která vyžadují zásadní změny, se můžou vyskytovat za omezených okolností před vydáním.
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.
Návod
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 poskytuje abstrakci pro interakci s Vector Stores a seznam implementací připravených k použití, které implementují tyto abstrakce pro různé databáze. 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.
Standardní implementace lze použít se sémantickým jádrem, ale nezávisí na základním sémantickém zásobníku a lze je proto v případě potřeby použít zcela nezávisle. Sémantickým jádrem poskytnuté implementace se označují jako "konektory".
Generace rozšířená o vyhledávání (RAG) s vektorovými databázemi
Abstrakce úložiště vektorů je 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 IVectorSearchable<TRecord> a zobrazíte ho jako implementaci vyhledávání textu.
Návod
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".
Návod
Další informace o hledání textu najdete v tématu Co je vyhledávání textu v sémantickém jádru?
Návod
Další informace o tom, jak rychle přidat RAG do agenta, najdete v tématu Přidání funkce Retrieval Augmented Generation (RAG) do sémantických agentů jádra.
Abstrakce vektorového úložiště
Abstrakce vektorového Microsoft.Extensions.VectorData.Abstractions úložiště jsou k dispozici v balíčku NuGet.
Následuje hlavní abstraktní základní třídy a rozhraní.
Microsoft.Extensions.VectorData.VectorStore
VectorStore obsahuje operace, které pokrývají všechny kolekce v úložišti vektorů, například ListCollectionNames.
Také umožňuje získat instance VectorStoreCollection<TKey, TRecord>.
Microsoft.Extensions.VectorData.VectorStoreCollection<TKey, TRecord>
VectorStoreCollection<TKey, TRecord> představuje kolekci.
Tato kolekce může nebo nemusí existovat a abstraktní základní třída poskytuje metody pro kontrolu, zda kolekce existuje, vytvořit ji nebo odstranit.
Abstraktní základní třída také poskytuje metody pro upsertování, získání a odstranění záznamů.
Abstraktní základní třída nakonec dědí z IVectorSearchable<TRecord> s funkcemi vektorového vyhledávání.
Microsoft.Extensions.VectorData.IVectorSearchable<TRecord>
-
SearchAsync<TRecord>lze použít k některým z těchto akcí:- Vektorové vyhledávání přebírá určitý vstup, který může být vektorizován registrovaným generátorem vkládání nebo vektorovou databází, kde to databáze podporuje.
- Vektorové vyhledávání používá vektor jako vstup.
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.
Návod
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".
Návod
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í.
com.microsoft.semantickernel.data.vectorstorage.VectorStore
VectorStore obsahuje operace, které pokrývají všechny kolekce v úložišti vektorů, například listCollectionNames.
Také umožňuje získat instance VectorStoreRecordCollection<Key, Record>.
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>, čímž zajišťuje možnosti 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í. 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ů.
Začínáme se službou Vector Stores
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
Definování datového modelu
Abstrakce Vector Store 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 implementace 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 každé vlastnosti.
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; }
}
Návod
Další informace o tom, jak anotovat datový model, najdete v tématu definování datového modelu.
Návod
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"), 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");
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 str, protože vlastnost HotelId je str a Qdrant podporuje pouze klíče typu str nebo int.
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.
)
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()
);
}
}
Návod
Další informace o tom, jaký klíč a typy polí každá implementace Vector Store podporuje, najdete v dokumentaci pro každou implementaci.
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.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);
Vytvoření kolekce a přidání záznamů
# 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();
Návod
Další informace o tom, jak generovat embeddingy, najdete v sekci vytváření embeddingů.
Hledání vektorů
// 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);
}
Hledání vektorů
Metodu vyhledávání lze použít k vyhledání záznamů v kolekci. Buď vezme řetězec, který se pak vektorizuje pomocí nastavení generování vkládání v modelu nebo kolekci, nebo vektor, který je již vygenerován.
# 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}")
Vytvoření vyhledávací funkce
Pokud chcete vytvořit jednoduchou funkci vyhledávání, která se dá použít k vyhledání hotelů, můžete použít metodu create_search_function v kolekci.
Název a popis, stejně jako názvy a popisy parametrů, se používají k vygenerování podpisu funkce, který se odešle do LLM při volání funkce. To znamená, že úprava této může být užitečná pro přimět LLM k vygenerování správného volání funkce.
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 `*`."
)
Existuje mnoho dalších parametrů, například to, jak vypadá složitější verze, všimněte si přizpůsobení parametrů a string_mapper funkce, která se používá k převodu záznamu na řetězec.
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}) ",
)
Návod
Další ukázky, včetně kompletních příkladů, najdete v úložišti sémantických ukázek jádra.
// 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());
Návod
Další informace o tom, jak generovat embeddingy, najdete v sekci vytváření embeddingů.