Что такое соединители хранилища векторов семантического ядра? (Предварительная версия)
Предупреждение
Функции хранилища векторов семантического ядра доступны в предварительной версии и улучшения, требующие критических изменений, могут по-прежнему возникать в ограниченных обстоятельствах перед выпуском.
Совет
Если вы ищете сведения о устаревших соединителях хранилища памяти, перейдите на страницу хранилища памяти.
Векторные базы данных имеют множество вариантов использования в разных доменах и приложениях, которые включают обработку естественного языка (NLP), компьютерное зрение (CV), системы рекомендаций (RS) и другие области, требующие семантического понимания и сопоставления данных.
Одним из вариантов использования для хранения информации в векторной базе данных является включение больших языковых моделей (LLM) для создания более релевантных и согласованных ответов. Крупные языковые модели часто сталкиваются с проблемами, такими как создание неточных или неуместных сведений; отсутствие фактической согласованности или здравого смысла; повторение или противоречие себе; быть предвзятым или оскорбительным. Чтобы устранить эти проблемы, можно использовать векторную базу данных для хранения информации о различных темах, ключевых словах, фактах, мнениях и/или источниках, связанных с нужным доменом или жанром. База данных векторов позволяет эффективно находить подмножество информации, связанной с определенным вопросом или разделом. Затем вы можете передать информацию из векторной базы данных с запросом на большую языковую модель, чтобы создать более точное и соответствующее содержимое.
Например, если вы хотите написать запись блога о последних тенденциях ВИ, можно использовать векторную базу данных для хранения последних сведений об этом разделе и передачи информации вместе с запросом на LLM, чтобы создать запись блога, которая использует последнюю информацию.
Семантический ядро и .net предоставляют абстракцию для взаимодействия с векторными хранилищами и список встроенных соединителей, реализующих эти абстракции. Функции включают создание, перечисление и удаление коллекций записей, а также отправку, извлечение и удаление записей. Абстракции позволяет легко экспериментировать с бесплатным или локально размещенным векторным хранилищем, а затем переключиться на службу при необходимости увеличения масштаба.
Извлечение дополненной генерации (RAG) с векторными хранилищами
Абстракции хранилища векторов — это api низкого уровня для добавления и получения данных из векторных хранилищ.
Семантическое ядро имеет встроенную поддержку использования любой из реализаций векторного хранилища для RAG.
Это достигается путем упаковки IVectorizedSearch<TRecord>
и представления его в качестве реализации текстового поиска.
Совет
Дополнительные сведения об использовании векторных хранилищ для RAG см. в Использование векторных хранилищ с семантическим поиском текста ядра.
Совет
Дополнительные сведения о поиске текста см. в статье Что такое поиск текста семантического ядра?
Абстракция хранилища векторов
Ниже приведены основные интерфейсы абстракции векторного хранилища.
Microsoft.Extensions.VectorData.IVectorStore
IVectorStore
содержит операции, охватывающие все коллекции в хранилище векторов, например ListCollectionNames.
Он также предоставляет возможность получения IVectorStoreRecordCollection<TKey, TRecord>
экземпляров.
Microsoft.Extensions.VectorData.IVectorStoreRecordCollection<TKey, TRecord>
IVectorStoreRecordCollection<TKey, TRecord>
представляет коллекцию.
Эта коллекция может существовать или не существовать, и интерфейс предоставляет методы для проверки наличия коллекции, создания или удаления.
Интерфейс также предоставляет методы для upsert, получения и удаления записей.
Наконец, интерфейс наследует от IVectorizedSearch<TRecord>
предоставления возможностей поиска векторов.
Microsoft.Extensions.VectorData.IVectorizedSearch<TRecord>
IVectorizedSearch<TRecord>
содержит метод для выполнения векторного поиска.
IVectorStoreRecordCollection<TKey, TRecord>
наследует от IVectorizedSearch<TRecord>
того, чтобы можно было использовать IVectorizedSearch<TRecord>
самостоятельно в тех случаях, когда требуется только поиск, а управление записями или коллекциями не требуется.
IVectorizableTextSearch<TRecord>
IVectorizableTextSearch<TRecord>
содержит метод для выполнения векторного поиска, в котором база данных векторов имеет возможность автоматически создавать внедрения. Например, можно вызвать этот метод с текстовой строкой, и база данных создаст внедрение для вас и выполните поиск в поле вектора. Это не поддерживается всеми базами данных векторов и поэтому реализуется только с помощью соединителей выбора.
Получение дополненного поколения (RAG) с векторными хранилищами
Абстракции хранилища векторов — это api низкого уровня для добавления и получения данных из векторных хранилищ.
Semantic Kernel имеет встроенную поддержку использования любой из реализаций векторных хранилищ для RAG.
Это достигается, обернув VectorSearchBase[TKey, TModel]
с помощью VectorizedSearchMixin[Tmodel]
, VectorizableTextSearchMixin[TModel]
или VectorTextSearch[TModel]
и представляя его в виде реализации поиска текста.
Совет
Дополнительные сведения об использовании векторных хранилищ для RAG см. в статье Использование векторных хранилищ с семантического ядра текстового поиска.
Совет
Дополнительные сведения о поиске текста см. в статье Что такое поиск текста семантического ядра?
Абстракция хранилища векторов
Ниже приведены основные интерфейсы абстракции векторного хранилища.
com.microsoft.semantickernel.data.vectorstorage.VectorStore
VectorStore
содержит операции, охватывающие все коллекции в векторном хранилище, например listCollectionNames.
Он также предоставляет возможность получения VectorStoreRecordCollection<Key, Record>
экземпляров.
com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection<Key, Record>
VectorStoreRecordCollection<Key, Record>
представляет коллекцию.
Эта коллекция может существовать или не существовать, и интерфейс предоставляет методы для проверки наличия коллекции, создания или удаления.
Интерфейс также предоставляет методы для upsert, получения и удаления записей.
Наконец, интерфейс наследует от VectorizedSearch<Record>
предоставления возможностей поиска векторов.
com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<Record>
VectorizedSearch<Record>
содержит метод для выполнения векторного поиска.
VectorStoreRecordCollection<Key, Record>
наследует от VectorizedSearch<Record>
того, чтобы можно было использовать VectorizedSearch<Record>
самостоятельно в тех случаях, когда требуется только поиск, а управление записями или коллекциями не требуется.
com.microsoft.semantickernel.data.vectorsearch.VectorizableTextSearch<Record>
VectorizableTextSearch<Record>
содержит метод для выполнения векторного поиска, в котором база данных векторов имеет возможность автоматически создавать внедрения. Например, можно вызвать этот метод с текстовой строкой, и база данных создаст внедрение для вас и выполните поиск в поле вектора. Это не поддерживается всеми базами данных векторов и поэтому реализуется только с помощью соединителей выбора.
Начало работы с соединителями Vector Store
Импорт необходимых пакетов nuget
Все интерфейсы хранилища векторов и все связанные с абстракцией классы доступны в пакете Microsoft.Extensions.VectorData.Abstractions
nuget.
Каждая реализация хранилища векторов доступна в собственном пакете nuget. Список известных реализаций см. на странице соединителей вне поля.
Пакет абстракций можно добавить следующим образом.
dotnet add package Microsoft.Extensions.VectorData.Abstractions --prerelease
Предупреждение
Из версии 1.23.0 семантического ядра абстракции векторного хранилища были удалены Microsoft.SemanticKernel.Abstractions
и доступны в новом выделенном Microsoft.Extensions.VectorData.Abstractions
пакете.
Обратите внимание, что от версии 1.23.0 зависитMicrosoft.SemanticKernel.Abstractions
, Microsoft.Extensions.VectorData.Abstractions
поэтому нет необходимости ссылаться на дополнительные пакеты.
Абстракции, однако, теперь будут находиться в новом Microsoft.Extensions.VectorData
пространстве имен.
При обновлении с версии 1.22.0 или более поздней версии до версии 1.23.0 или более поздней версии необходимо добавить дополнительное using Microsoft.Extensions.VectorData;
предложение в файлы, в которых используются любые типы абстракции векторного хранилища, например IVectorStore
, IVectorStoreRecordCollection
, VectorStoreRecordDataAttribute
и VectorStoreRecordKeyProperty
т. д.
Это изменение было внесено для поддержки поставщиков хранилища векторов при создании собственных реализаций. Поставщик должен ссылаться только на Microsoft.Extensions.VectorData.Abstractions
пакет. Это снижает потенциальные конфликты версий и позволяет семантике ядра продолжать развиваться быстро, не влияя на поставщиков хранилища векторов.
Определение модели данных
Соединители хранилища векторов семантического ядра используют модель первого подхода к взаимодействию с базами данных. Это означает, что первым шагом является определение модели данных, которая сопоставляется со схемой хранения. Чтобы помочь соединителям создавать коллекции записей и сопоставляться со схемой хранилища, модель может быть аннотирована, чтобы указать функцию каждого свойства.
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; }
}
Совет
Дополнительные сведения о том, как означать модель данных, см. в определении модели данных.
Совет
Для альтернативы аннотации модели данных см . определение схемы с определением записи.
Подключение к базе данных и выбор коллекции
После определения модели данных необходимо создать экземпляр VectorStore для выбранной базы данных и выбрать коллекцию записей.
В этом примере мы будем использовать Qdrant. Поэтому необходимо импортировать пакет nuget Qdrant.
dotnet add package Microsoft.SemanticKernel.Connectors.Qdrant --prerelease
Если вы хотите запустить Qdrant локально с помощью Docker, используйте следующую команду, чтобы запустить контейнер Qdrant с параметрами, используемыми в этом примере.
docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant:latest
Чтобы убедиться, что экземпляр Qdrant работает правильно, посетите панель мониторинга Qdrant, встроенную в контейнер Docker: http://localhost:6333/dashboard
Так как базы данных поддерживают множество различных типов ключей и записей, мы можем указать тип ключа и записи для коллекции с помощью универсальных шаблонов.
В нашем случае тип записи будет классом Hotel
, который мы уже определили, и тип ключа будет ulong
, так как HotelId
свойство является ulong
и Qdrant поддерживает Guid
только ключ или 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");
Так как базы данных поддерживают множество различных типов ключей и записей, мы можем указать тип ключа и записи для коллекции с помощью универсальных шаблонов.
В нашем случае тип записи будет классом Hotel
, который мы уже определили, и тип ключа будет str
, так как HotelId
свойство является str
и Qdrant поддерживает str
только ключ или 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
)
Так как базы данных поддерживают множество различных типов ключей и записей, мы можем указать тип ключа и записи для коллекции с помощью универсальных шаблонов.
В нашем случае тип записи будет классом Hotel
, который мы уже определили, и тип ключа будет String
, так как hotelId
свойство является хранилищем String
JDBC только поддерживает 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()
);
}
}
Совет
Дополнительные сведения о том, какие ключи и типы полей поддерживает каждый соединитель Vector Store, см . в документации по каждому соединителю.
Создание коллекции и добавление записей
// 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);
Создание коллекции и добавление записей
# 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();
Совет
Дополнительные сведения о создании внедрения см . в разделе "Создание внедрения".
Выполнить векторный поиск
// 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);
}
Выполнить векторный поиск
# 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());
Совет
Дополнительные сведения о создании внедрения см . в разделе "Создание внедрения".