Создание внедренных модулей для соединителей хранилища векторов семантического ядра

Предупреждение

Функциональность хранилища векторов семантического ядра доступна в предварительной версии, и улучшения, требующие значительных изменений, всё ещё могут возникнуть в ограниченных обстоятельствах перед выпуском.

Предупреждение

Функциональность хранилища векторов семантического ядра доступна в предварительной версии, и улучшения, требующие значительных изменений, всё ещё могут возникнуть в ограниченных обстоятельствах перед выпуском.

Соединители семантического векторного хранилища поддерживают несколько способов создания встраивания. Представления могут быть созданы разработчиком и переданы как часть записи при использовании VectorStoreCollection, или создано VectorStoreCollection внутренним образом.

Позволить векторному хранилищу генерировать эмбеддинги

Вы можете настроить генератор эмбеддингов в хранилище векторов, что позволяет автоматически создавать эмбеддинги во время операций обновления и вставки, а также поиска, устраняя необходимость предварительной обработки вручную.

Чтобы включить автоматическое создание векторов при upsert, свойство vector в вашей модели данных определяется как исходный тип, например строка, но все равно оформлено с помощью VectorStoreVectorPropertyAttribute.

    [VectorStoreVector(1536)]
    public string Embedding { get; set; }

Перед upsert Embedding свойство должно содержать строку, из которой должен быть создан вектор. Тип вектора, хранящегося в базе данных (например, float32, float16 и т. д.), будет производным от настроенного генератора внедрения.

Это важно

Эти свойства вектора не поддерживают получение созданного вектора или исходного текста, из который был создан вектор. Они также не хранят исходный текст. Если исходный текст должен храниться, для его хранения необходимо добавить отдельное свойство Data.

Внедренные генераторы, реализующие Microsoft.Extensions.AI абстракции, поддерживаются и могут быть настроены на различных уровнях.

  1. В векторном хранилище: можно задать генератор внедрения по умолчанию для всего хранилища векторов. Этот генератор будет использоваться для всех коллекций и свойств, если не будет указан другой.

    using Microsoft.Extensions.AI;
    using Microsoft.SemanticKernel.Connectors.Qdrant;
    using OpenAI;
    using Qdrant.Client;
    
    var embeddingGenerator = new OpenAIClient("your key")
        .GetEmbeddingClient("your chosen model")
        .AsIEmbeddingGenerator();
    
    var vectorStore = new QdrantVectorStore(
        new QdrantClient("localhost"),
        ownsClient: true,
        new QdrantVectorStoreOptions
        {
             EmbeddingGenerator = embeddingGenerator
        });
    
  2. Для коллекции: вы можете настроить генератор встраивания для конкретной коллекции, переопределив генератор на уровне хранилища.

    using Microsoft.Extensions.AI;
    using Microsoft.SemanticKernel.Connectors.Qdrant;
    using OpenAI;
    using Qdrant.Client;
    
    var embeddingGenerator = new OpenAIClient("your key")
        .GetEmbeddingClient("your chosen model")
        .AsIEmbeddingGenerator();
    
    var collectionOptions = new QdrantCollectionOptions
    {
        EmbeddingGenerator = embeddingGenerator
    };
    var collection = new QdrantCollection<ulong, MyRecord>(
        new QdrantClient("localhost"),
        "myCollection",
        ownsClient: true,
        collectionOptions);
    
  3. В определении записи: при программной настройке свойств с помощью VectorStoreCollectionDefinition можно указать генератор интеграции для всех свойств.

    using Microsoft.Extensions.AI;
    using Microsoft.Extensions.VectorData;
    using Microsoft.SemanticKernel.Connectors.Qdrant;
    using OpenAI;
    using Qdrant.Client;
    
    var embeddingGenerator = new OpenAIClient("your key")
        .GetEmbeddingClient("your chosen model")
        .AsIEmbeddingGenerator();
    
    var definition = new VectorStoreCollectionDefinition
    {
        EmbeddingGenerator = embeddingGenerator,
        Properties = new List<VectorStoreProperty>
        {
            new VectorStoreKeyProperty("Key", typeof(ulong)),
            new VectorStoreVectorProperty("DescriptionEmbedding", typeof(string), dimensions: 1536)
        }
    };
    
    var collectionOptions = new QdrantCollectionOptions
    {
        Definition = definition
    };
    var collection = new QdrantCollection<ulong, MyRecord>(
        new QdrantClient("localhost"),
        "myCollection",
        ownsClient: true,
        collectionOptions);
    
  4. При определении векторного свойства: при программном определении свойств можно задать генератор встраивания прямо в свойство.

    using Microsoft.Extensions.AI;
    using Microsoft.Extensions.VectorData;
    using OpenAI;
    
    var embeddingGenerator = new OpenAIClient("your key")
        .GetEmbeddingClient("your chosen model")
        .AsIEmbeddingGenerator();
    
    var vectorProperty = new VectorStoreVectorProperty("DescriptionEmbedding", typeof(string), dimensions: 1536)
    {
         EmbeddingGenerator = embeddingGenerator
    };
    

Пример использования

В следующем примере показано, как использовать генератор встраивания для автоматического создания векторов во время операций обновления-вставки и поиска. Этот подход упрощает рабочие процессы, устраняя необходимость предварительной компиляции внедрения вручную.


// The data model
internal class FinanceInfo
{
    [VectorStoreKey]
    public string Key { get; set; } = string.Empty;

    [VectorStoreData]
    public string Text { get; set; } = string.Empty;

    // Note that the vector property is typed as a string, and
    // its value is derived from the Text property. The string
    // value will however be converted to a vector on upsert and
    // stored in the database as a vector.
    [VectorStoreVector(1536)]
    public string Embedding => this.Text;
}

// Create an OpenAI embedding generator.
var embeddingGenerator = new OpenAIClient("your key")
    .GetEmbeddingClient("your chosen model")
    .AsIEmbeddingGenerator();

// Use the embedding generator with the vector store.
var vectorStore = new InMemoryVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
var collection = vectorStore.GetCollection<string, FinanceInfo>("finances");
await collection.EnsureCollectionExistsAsync();

// Create some test data.
string[] budgetInfo =
{
    "The budget for 2020 is EUR 100 000",
    "The budget for 2021 is EUR 120 000",
    "The budget for 2022 is EUR 150 000",
    "The budget for 2023 is EUR 200 000",
    "The budget for 2024 is EUR 364 000"
};

// Embeddings are generated automatically on upsert.
var records = budgetInfo.Select((input, index) => new FinanceInfo { Key = index.ToString(), Text = input });
await collection.UpsertAsync(records);

// Embeddings for the search is automatically generated on search.
var searchResult = collection.SearchAsync(
    "What is my budget for 2024?",
    top: 1);

// Output the matching result.
await foreach (var result in searchResult)
{
    Console.WriteLine($"Key: {result.Record.Key}, Text: {result.Record.Text}");
}

Создание внедрения самостоятельно

Создание генератора встраивания

Примеры создания экземпляров семантического ядра см. в разделе "Генерация встраиваний".

Дополнительные сведения о создании служб генерации внедрений см. в разделе Microsoft.Extensions.AI.Abstractions.

Создание эмбеддингов при upsert с помощью семантического ядра ITextEmbeddingGenerationService

public async Task GenerateEmbeddingsAndUpsertAsync(
    ITextEmbeddingGenerationService textEmbeddingGenerationService,
    VectorStoreCollection<ulong, Hotel> collection)
{
    // Upsert a record.
    string descriptionText = "A place where everyone can be happy.";
    ulong hotelId = 1;

    // Generate the embedding.
    ReadOnlyMemory<float> embedding =
        await textEmbeddingGenerationService.GenerateEmbeddingAsync(descriptionText);

    // Create a record and upsert with the already generated embedding.
    await collection.UpsertAsync(new Hotel
    {
        HotelId = hotelId,
        HotelName = "Hotel Happy",
        Description = descriptionText,
        DescriptionEmbedding = embedding,
        Tags = new[] { "luxury", "pool" }
    });
}

Создание эмбеддингов в поиске с помощью семантического ядра ITextEmbeddingGenerationService

public async Task GenerateEmbeddingsAndSearchAsync(
    ITextEmbeddingGenerationService textEmbeddingGenerationService,
    VectorStoreCollection<ulong, Hotel> collection)
{
    // Upsert a record.
    string descriptionText = "Find me a hotel with happiness in mind.";

    // Generate the embedding.
    ReadOnlyMemory<float> searchEmbedding =
        await textEmbeddingGenerationService.GenerateEmbeddingAsync(descriptionText);

    // Search using the already generated embedding.
    IAsyncEnumerable<VectorSearchResult<Hotel>> searchResult = collection.SearchAsync(searchEmbedding, top: 1);
    List<VectorSearchResult<Hotel>> resultItems = await searchResult.ToListAsync();

    // Print the first search result.
    Console.WriteLine("Score for first result: " + resultItems.FirstOrDefault()?.Score);
    Console.WriteLine("Hotel description for first result: " + resultItems.FirstOrDefault()?.Record.Description);
}

Совет

Дополнительную информацию о создании векторных представлений см. в Генерация векторных представлений в Сематическом Ядре.

Размерности встраивания

Для баз данных векторов обычно требуется указать количество измерений, которые каждый вектор имеет при создании коллекции. Различные модели внедрения обычно поддерживают создание векторов с различными размерами измерений. Например, OpenAI text-embedding-ada-002 создает векторы с 1536 измерениями. Некоторые модели также позволяют разработчику выбрать количество измерений, которые они хотят в выходном векторе. Например, Google text-embedding-004 создает векторы с 768 измерениями по умолчанию, но позволяет разработчику выбрать любое количество измерений от 1 до 768.

Важно убедиться, что векторы, созданные моделью внедрения, имеют то же количество измерений, что и соответствующий вектор в базе данных.

При создании коллекции с использованием абстракций хранилища векторов семантического ядра необходимо указать количество измерений, требуемое для каждого свойства вектора, либо через аннотации, либо через определение записи. Вот примеры обоих способов установки числа измерений на 1536.

[VectorStoreVector(Dimensions: 1536)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
new VectorStoreVectorProperty("DescriptionEmbedding", typeof(float), dimensions: 1536);

Совет

Для получения дополнительной информации о том, как аннотировать модель данных, см. в разделе определении модели данных.

Совет

Для получения дополнительной информации о создании определения записи см. определение вашей схемы с использованием определения записи.

Скоро

Дополнительные сведения в ближайшее время.

Скоро

Дополнительные сведения в ближайшее время.