Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ostrzeżenie
Funkcjonalność semantycznego magazynu wektorów jądra znajduje się w wersji RC, a ulepszenia wymagające przełomowych zmian mogą nadal występować w ograniczonych okolicznościach przed wydaniem.
Ostrzeżenie
Funkcja semantyczna magazynu wektorowego w jądrze jest dostępna w wersji zapoznawczej, a ulepszenia wymagające istotnych zmian mogą nadal wystąpić w ograniczonych okolicznościach przed ostatecznym wydaniem.
Napiwek
Jeśli szukasz informacji o starszych łącznikach Memory Store, zapoznaj się ze stroną Memory Stores.
Bazy danych wektorów mają wiele przypadków użycia w różnych domenach i aplikacjach, które obejmują przetwarzanie języka naturalnego (NLP), przetwarzanie obrazów (CV), systemy rekomendacji (RS) i inne obszary, które wymagają semantycznego zrozumienia i dopasowywania danych.
Jednym z przypadków użycia przechowywania informacji w bazie danych wektorów jest umożliwienie dużych modeli językowych (LLM) generowania bardziej odpowiednich i spójnych odpowiedzi. Duże modele językowe często napotykają wyzwania takie jak generowanie niedokładnych lub nieistotnych informacji, brak spójności faktycznej lub zdrowego rozsądku, powtarzanie się lub sprzeczność, a także są stronnicze lub obraźliwe. Aby pomóc w pokonaniu tych wyzwań, możesz użyć wektorowej bazy danych do przechowywania informacji o różnych tematach, słowach kluczowych, faktach, opiniach i/lub źródłach związanych z żądaną domeną lub gatunkiem. Baza danych wektorów umożliwia efektywne znajdowanie podzestawu informacji związanych z konkretnym pytaniem lub tematem. Następnie możesz przekazać informacje z bazy danych wektorów wraz z podpowiedzią do dużego modelu językowego, aby wygenerować dokładniejszą i bardziej odpowiednią treść.
Jeśli na przykład chcesz napisać wpis w blogu na temat najnowszych trendów w sztucznej inteligencji, możesz użyć bazy danych wektorów do przechowywania najnowszych informacji o tym temacie i przekazać informacje wraz z prośbą do llM w celu wygenerowania wpisu w blogu, który wykorzystuje najnowsze informacje.
Semantic Kernel i platforma .net zapewniają abstrakcję interakcji z magazynami wektorów oraz listę wbudowanych implementacji, które implementują te abstrakcje dla różnych baz danych. Funkcje obejmują tworzenie, wyświetlanie i usuwanie kolekcji rekordów oraz przekazywanie, pobieranie i usuwanie rekordów. Abstrakcja ułatwia eksperymentowanie z bezpłatnym lub lokalnie hostowanym magazynem wektorów, a następnie przełączanie się do usługi w razie potrzeby skalowania w górę.
Gotowe implementacje mogą być używane z jądrem semantycznym, ale nie zależą od podstawowego stosu jądra semantycznego i dlatego mogą być używane całkowicie niezależnie, jeśli jest to wymagane. Semantyczne jądro dostarczone implementacje są określane jako "łączniki".
Generacja wspomagana wyszukiwaniem (RAG) z magazynami wektorów
Abstrakcja magazynu wektorów to interfejs API niskiego poziomu umożliwiający dodawanie i pobieranie danych z magazynów wektorów.
Kernel semantyczny ma wbudowaną obsługę korzystania z dowolnej implementacji magazynu wektorów dla RAG.
Jest to osiągane przez zawijanie IVectorSearchable<TRecord> i uwidacznianie go jako implementacji wyszukiwania tekstu.
Napiwek
Aby dowiedzieć się więcej na temat używania magazynów wektorów dla programu RAG, zobacz Jak używać magazynów wektorów z semantycznym wyszukiwaniem tekstu jądra.
Napiwek
Aby dowiedzieć się więcej na temat wyszukiwania tekstu, zobacz Co to jest wyszukiwanie tekstu jądra semantycznego?
Napiwek
Aby dowiedzieć się więcej na temat szybkiego dodawania RAG do agenta, zobacz Dodawanie Retrieval Augmented Generation (RAG) do agentów jądra semantycznego.
Abstrakcja przechowywania wektorów
Abstrakcje Magazynu Wektorów są udostępniane w pakiecie Microsoft.Extensions.VectorData.Abstractions NuGet.
Poniżej przedstawiono główne abstrakcyjne klasy bazowe i interfejsy.
Microsoft.Extensions.VectorData.VectorStore
VectorStore zawiera operacje obejmujące wszystkie kolekcje w magazynie wektorów, np. ListCollectionNames.
Zapewnia opcję pobierania wystąpień VectorStoreCollection<TKey, TRecord>.
Microsoft.Extensions.VectorData.VectorStoreCollection<TKey, TRecord>
VectorStoreCollection<TKey, TRecord> reprezentuje kolekcję.
Ta kolekcja może lub nie istnieje, a abstrakcyjna klasa bazowa udostępnia metody sprawdzania, czy kolekcja istnieje, utwórz ją lub usuń.
Abstrakcyjna klasa bazowa udostępnia również metody dodawania i aktualizacji, pobierania oraz usuwania rekordów.
Na koniec abstrakcyjna klasa bazowa dziedziczy z IVectorSearchable<TRecord>, zapewniając możliwości wyszukiwania wektorowego.
Microsoft.Extensions.VectorData.IVectorSearchable<TRecord>
-
SearchAsync<TRecord>można użyć do wykonania jednej z następujących czynności:- wyszukiwania wektorowe pobierają dane wejściowe, które można wektorować za pomocą zarejestrowanego generatora wektorów osadzania lub bazy danych wektorów, jeśli baza ta obsługuje te funkcjonalności.
- wyszukiwanie wektorów biorące wektor jako dane wejściowe.
Generacja wspomagana wyszukiwaniem (RAG) z magazynami wektorów
Abstrakcje magazynów wektorów to interfejs API niskiego poziomu służący do dodawania i pobierania danych z magazynów wektorów.
Kernel semantyczny ma wbudowaną obsługę korzystania z dowolnej implementacji magazynu wektorów dla RAG.
Jest to osiągane przez zawijanie VectorSearchBase[TKey, TModel] za pomocą VectorizedSearchMixin[Tmodel], VectorizableTextSearchMixin[TModel] lub VectorTextSearch[TModel] i uwidacznianie go jako implementacji wyszukiwania tekstu.
Napiwek
Aby dowiedzieć się więcej na temat używania magazynów wektorów dla programu RAG, zobacz Jak używać magazynów wektorów z semantycznym wyszukiwaniem tekstu jądra.
Napiwek
Aby dowiedzieć się więcej na temat wyszukiwania tekstu, zobacz Co to jest wyszukiwanie tekstu jądra semantycznego?
Abstrakcja przechowywania wektorów
Główne interfejsy w abstrakcji magazynu wektorów są następujące.
com.microsoft.semantickernel.data.vectorstorage.VectorStore
VectorStore zawiera operacje obejmujące wszystkie kolekcje w magazynie wektorów, np. listCollectionNames.
Zapewnia opcję pobierania wystąpień VectorStoreRecordCollection<Key, Record>.
com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection<Key, Record>
VectorStoreRecordCollection<Key, Record> reprezentuje kolekcję.
Ta kolekcja może lub nie istnieje, a interfejs udostępnia metody sprawdzania, czy kolekcja istnieje, utwórz ją lub usuń.
Interfejs udostępnia również metody aktualizowania lub dodawania, pobierania i usuwania rekordów.
Na koniec interfejs dziedziczy z VectorizedSearch<Record>, zapewniając możliwości wyszukiwania wektorowego.
com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<Record>
VectorizedSearch<Record> zawiera metodę wykonywania wyszukiwań wektorowych.
VectorStoreRecordCollection<Key, Record> dziedziczy z VectorizedSearch<Record>, co umożliwia użycie VectorizedSearch<Record> samodzielnie w sytuacjach, gdy konieczne jest jedynie wyszukiwanie i nie jest potrzebne zarządzanie rekordami lub kolekcjami.
com.microsoft.semantickernel.data.vectorsearch.WyszukiwanieTekstuMożliwegoDoWektoryzacji<Zapis>
VectorizableTextSearch<Record> zawiera metodę wyszukiwania wektorowego, gdzie baza danych wektorów ma możliwość automatycznego generowania wbudowanych wektorów. Na przykład można wywołać tę metodę za pomocą ciągu tekstowego, a baza danych wygeneruje osadzanie dla Ciebie i wyszuka pole wektora. Nie jest to obsługiwane przez wszystkie wektorowe bazy danych i dlatego jest implementowane tylko przez wybrane łączniki.
Wprowadzenie do repozytoriów wektorów
Importowanie niezbędnych pakietów NuGet
Wszystkie interfejsy magazynu wektorów i wszystkie klasy powiązane z abstrakcją są dostępne w pakiecie Microsoft.Extensions.VectorData.Abstractions NuGet.
Każda implementacja magazynu wektorów jest dostępna we własnym pakiecie NuGet. Aby uzyskać listę znanych implementacji, zobacz stronę Łączniki dostępne od ręki.
Pakiet abstrakcji można dodać w ten sposób.
dotnet add package Microsoft.Extensions.VectorData.Abstractions
Definiowanie modelu danych
Abstrakcje magazynu wektorów używają podejścia opartego na modelu do interakcji z bazami danych. Oznacza to, że pierwszym krokiem jest zdefiniowanie modelu danych mapującego na schemat magazynowania. Aby ułatwić implementacjom tworzenie kolekcji rekordów i mapowanie do schematu magazynu, model może być oznaczony adnotacjami, aby wskazać funkcję każdej właściwości.
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; }
}
Napiwek
Aby uzyskać więcej informacji na temat dodawania adnotacji do modelu danych, zobacz Definiowanie modelu danych.
Napiwek
Alternatywą dla dodawania adnotacji do modelu danych jest definiowanie schematu przy użyciu definicji rekordu.
Nawiązywanie połączenia z bazą danych i wybieranie kolekcji
Po zdefiniowaniu modelu danych następnym krokiem jest utworzenie instancji VectorStore dla wybranej bazy danych i wybranie kolekcji rekordów.
W tym przykładzie użyjemy funkcji Qdrant. W związku z tym należy zaimportować pakiet nuget Qdrant.
dotnet add package Microsoft.SemanticKernel.Connectors.Qdrant --prerelease
Jeśli chcesz uruchomić usługę Qdrant lokalnie przy użyciu platformy Docker, użyj następującego polecenia, aby uruchomić kontener Qdrant z ustawieniami używanymi w tym przykładzie.
docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant:latest
Aby sprawdzić, czy wystąpienie usługi Qdrant działa prawidłowo, odwiedź pulpit nawigacyjny Qdrant wbudowany w kontener Docker Qdrant: http://localhost:6333/dashboard
Ponieważ bazy danych obsługują wiele różnych typów kluczy i rekordów, umożliwiamy określenie typu klucza i rekordu dla kolekcji przy użyciu typów ogólnych.
W naszym przypadku typ rekordu będzie klasą Hotel, którą już zdefiniowaliśmy, a typem klucza będzie ulong, ponieważ właściwość HotelId jest typu ulong, a Qdrant obsługuje tylko klucze typu Guid lub 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");
Ponieważ bazy danych obsługują wiele różnych typów kluczy i rekordów, umożliwiamy określenie typu klucza i rekordu dla kolekcji przy użyciu typów ogólnych.
W naszym przypadku typ rekordu będzie klasą Hotel, którą już zdefiniowaliśmy, a typem klucza będzie str, ponieważ właściwość HotelId jest typu str, a Qdrant obsługuje tylko klucze typu str lub 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.
)
Ponieważ bazy danych obsługują wiele różnych typów kluczy i rekordów, umożliwiamy określenie typu klucza i rekordu dla kolekcji przy użyciu typów ogólnych.
W naszym przypadku typ rekordu będzie klasą Hotel, którą już zdefiniowaliśmy, a typem klucza będzie String, ponieważ właściwość hotelId jest typu String, a magazyn JDBC obsługuje tylko klucze typu String.
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()
);
}
}
Napiwek
Aby uzyskać więcej informacji na temat typów kluczy i pól, które obsługuje implementacja magazynu wektorów, zapoznaj się z dokumentacją każdej implementacji.
Tworzenie kolekcji i dodawanie rekordów
// 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);
Tworzenie kolekcji i dodawanie rekordów
# 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();
Napiwek
Aby uzyskać więcej informacji na temat generowania embeddingów, zobacz generowanie embeddingów.
Wykonywanie wyszukiwania wektorowego
// 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);
}
Wykonywanie wyszukiwania wektorowego
Metoda wyszukiwania może służyć do wyszukiwania rekordów w kolekcji. Pobiera on ciąg, który następnie jest wektoryzowany przy użyciu konfiguracji generacji osadzania w modelu lub kolekcji albo wektora, który jest już wygenerowany.
# 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}")
Tworzenie funkcji wyszukiwania
Aby utworzyć prostą funkcję wyszukiwania, która może służyć do wyszukiwania hoteli, możesz użyć metody create_search_function na kolekcji.
Nazwa i opis, a także nazwy i opisy parametrów, są używane do generowania podpisu funkcji wysyłanego do usługi LLM podczas wywoływania funkcji. Oznacza to, że dostosowanie może być przydatne, aby program LLM wygenerował poprawne wywołanie funkcji.
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 `*`."
)
Istnieje wiele innych parametrów, na przykład jest to, jak wygląda bardziej złożona wersja, zwróć uwagę na dostosowanie parametrów i string_mapper funkcję, która jest używana do konwertowania rekordu na ciąg.
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}) ",
)
Napiwek
Aby uzyskać więcej przykładów, w tym kompleksowe przykłady, zobacz repozytorium Semantic Kernel Samples (Przykłady jądra semantycznego).
// 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());
Napiwek
Aby uzyskać więcej informacji na temat generowania embeddingów, zobacz generowanie embeddingów.