Поделиться через


Использование соединителя Redis (предварительная версия)

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

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

Обзор

Соединитель Redis Vector Store можно использовать для доступа к данным и управления ими в Redis. Соединитель поддерживает режимы хэшей и JSON, а также выбранный режим определяет, какие другие функции поддерживаются.

Соединитель имеет следующие характеристики.

Область функций Поддержка
Коллекция сопоставляется с Индекс Redis с префиксом, равным <collectionname>:
Поддерживаемые типы свойств ключей строка
Поддерживаемые типы свойств данных При использовании хэшей:
  • строка
  • INT
  • uint
  • длинный
  • ulong
  • двойной точности
  • с плавающей запятой
  • bool
При использовании JSON:
Все типы, сериализуемые в JSON
Поддерживаемые типы свойств вектора
  • ReadOnlyMemory<float>
  • ReadOnlyMemory<double>
Поддерживаемые типы индексов
  • Hnsw
  • Фиксированная
Поддерживаемые функции расстояния
  • CosineSimilarity
  • DotProductSimilarity
  • EuclideanDistance
Поддержка нескольких векторов в записи Да
Поддерживается IsFilterable? Да
Поддерживается ЛиFullTextSearchable? Да
Поддерживается StoragePropertyName? При использовании хэшей: Да
При использовании JSON: нет, используйте JsonSerializerOptions и JsonPropertyNameAttribute вместо этого. Дополнительные сведения см. здесь.

Начало работы

Добавьте в проект пакет nuget соединителя Redis Vector Store.

dotnet add package Microsoft.SemanticKernel.Connectors.Redis --prerelease

Хранилище векторов можно добавить в контейнер внедрения зависимостей, доступный в KernelBuilder контейнере внедрения зависимостей или в IServiceCollection контейнер внедрения зависимостей, используя методы расширения, предоставляемые семантического ядра.

using Microsoft.SemanticKernel;

// Using Kernel Builder.
var kernelBuilder = Kernel
    .CreateBuilder()
    .AddRedisVectorStore("localhost:6379");
using Microsoft.SemanticKernel;

// Using IServiceCollection with ASP.NET Core.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRedisVectorStore("localhost:6379");

Методы расширения, которые не принимают параметров, также предоставляются. Для них требуется, чтобы экземпляр Redis IDatabase был отдельно зарегистрирован в контейнере внедрения зависимостей.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using StackExchange.Redis;

// Using Kernel Builder.
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.Services.AddSingleton<IDatabase>(sp => ConnectionMultiplexer.Connect("localhost:6379").GetDatabase());
kernelBuilder.AddRedisVectorStore();
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using StackExchange.Redis;

// Using IServiceCollection with ASP.NET Core.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IDatabase>(sp => ConnectionMultiplexer.Connect("localhost:6379").GetDatabase());
builder.Services.AddRedisVectorStore();

Экземпляр Redis Vector Store можно создать напрямую.

using Microsoft.SemanticKernel.Connectors.Redis;
using StackExchange.Redis;

var vectorStore = new RedisVectorStore(ConnectionMultiplexer.Connect("localhost:6379").GetDatabase());

Можно создать прямую ссылку на именованную коллекцию. При этом необходимо выбрать экземпляр JSON или Hashes в зависимости от способа хранения данных в Redis.

using Microsoft.SemanticKernel.Connectors.Redis;
using StackExchange.Redis;

// Using Hashes.
var hashesCollection = new RedisHashSetVectorStoreRecordCollection<Hotel>(
    ConnectionMultiplexer.Connect("localhost:6379").GetDatabase(),
    "skhotelshashes");
using Microsoft.SemanticKernel.Connectors.Redis;
using StackExchange.Redis;

// Using JSON.
var jsonCollection = new RedisJsonVectorStoreRecordCollection<Hotel>(
    ConnectionMultiplexer.Connect("localhost:6379").GetDatabase(),
    "skhotelsjson");

При создании RedisVectorStore или регистрации в контейнере внедрения зависимостей можно передать RedisVectorStoreOptions экземпляр, который настраивает предпочтительный тип хранилища или используемый режим: Hashes или JSON. Если значение не указано, значение по умолчанию — JSON.

using Microsoft.SemanticKernel.Connectors.Redis;
using StackExchange.Redis;

var vectorStore = new RedisVectorStore(
    ConnectionMultiplexer.Connect("localhost:6379").GetDatabase(),
    new() { StorageType = RedisStorageType.HashSet });

Начало работы

Установите семантические ядра с дополнительными компонентами Redis, включая клиент Redis.

pip install semantic-kernel[redis]

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


from semantic_kernel.connectors.memory.redis import RedisStore

vector_store = RedisStore()

Вы также можете создать хранилище векторов с собственным экземпляром клиента базы данных Redis.

from redis.asyncio.client import Redis
from semantic_kernel.connectors.memory.redis import RedisStore

redis_database = Redis.from_url(url="https://<your-redis-service-name>")
vector_store = RedisStore(redis_database=redis_database)

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

from semantic_kernel.connectors.memory.redis import RedisHashsetCollection, RedisJsonCollection

hash_collection = RedisHashsetCollection(collection_name="skhotels", data_model_type=Hotel)
json_collection = RedisJsonCollection(collection_name="skhotels", data_model_type=Hotel)

При создании коллекции из векторного хранилища можно передать тип коллекции в виде перечисления: RedisCollectionTypesпо умолчанию используется хэш-коллекция.

from semantic_kernel.connectors.memory.redis import RedisStore, RedisCollectionTypes

vector_store = RedisStore()
collection = vector_store.get_collection(
    collection_name="skhotels", 
    data_model_type=Hotel, 
    collection_type=RedisCollectionTypes.JSON,
)

Сериализация

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

Пример для коллекций JSON см . в документации redis.

Для коллекций Hashset используется команда hset с ключевым полем как nameполя данных как mapping -> metadata и векторы, как mapping -> [vector_field_name] , см . здесь дополнительные сведения.

Дополнительные сведения об этой концепции см. в документации по сериализации.

Начало работы

Включите последнюю версию соединителя данных Redis семантического ядра в проект Maven, добавив в проект pom.xmlMaven следующую зависимость:

<dependency>
    <groupId>com.microsoft.semantic-kernel</groupId>
    <artifactId>semantickernel-data-redis</artifactId>
    <version>[LATEST]</version>
</dependency>

Затем можно создать экземпляр векторного хранилища с помощью RedisVectorStore класса, имея клиент Redis (JedisPooled) в качестве параметра.

import com.microsoft.semantickernel.data.redis.RedisJsonVectorStoreRecordCollectionOptions;
import com.microsoft.semantickernel.data.redis.RedisStorageType;
import com.microsoft.semantickernel.data.redis.RedisVectorStore;
import com.microsoft.semantickernel.data.redis.RedisVectorStoreOptions;
import redis.clients.jedis.JedisPooled;

public class Main {
    public static void main(String[] args) {
        JedisPooled jedis = new JedisPooled("<your-redis-url>");

        // Build a Redis Vector Store
        // Available storage types are JSON and HASHSET. Default is JSON.
        var vectorStore = RedisVectorStore.builder()
            .withClient(jedis)
            .withOptions(
                RedisVectorStoreOptions.builder()
                    .withStorageType(RedisStorageType.HASH_SET).build())
            .build();
    }
}

Вы также можете получить коллекцию напрямую.

var collection = vectorStore.getCollection("skhotels",
    RedisJsonVectorStoreRecordCollectionOptions.<Hotel>builder()
        .withRecordClass(Hotel.class)
        .build());

Префиксы индекса

Redis использует систему префикса ключа для связывания записи с индексом. При создании индекса можно указать один или несколько префиксов, используемых с этим индексом. Если вы хотите связать запись с этим индексом, необходимо добавить префикс в ключ этой записи.

Например, если вы создаете индекс, вызываемый skhotelsjson префиксом skhotelsjson:, при настройке записи с ключом h1, ключ записи должен быть префиксирован так, как это skhotelsjson:h1 будет добавлено в индекс.

При создании новой коллекции с помощью соединителя Redis соединитель создаст индекс в Redis с префиксом, состоящим из имени коллекции и двоеточия, как показано ниже <collectionname>:. По умолчанию соединитель также будет префиксировать все ключи с этим префиксом при выполнении операций записи, таких как Get, Upsert и Delete.

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

using Microsoft.SemanticKernel.Connectors.Redis;
using StackExchange.Redis;

var collection = new RedisJsonVectorStoreRecordCollection<Hotel>(
    ConnectionMultiplexer.Connect("localhost:6379").GetDatabase(),
    "skhotelsjson",
    new() { PrefixCollectionNameToKeyNames = false });

await collection.GetAsync("myprefix_h1");
from semantic_kernel.connectors.memory.redis import RedisJsonCollection

collection = RedisJsonCollection(collection_name="skhotels", data_model_type=hotel, prefix_collection_name_to_key_names=False)

await collection.get("myprefix_h1")
var collection = vectorStore.getCollection("skhotels",
    RedisJsonVectorStoreRecordCollectionOptions.<Hotel>builder()
        .withRecordClass(Hotel.class)
        .withPrefixCollectionName(false)
        .build());

collection.getAsync("myprefix_h1", null).block();

Сопоставление данных

Redis поддерживает два режима хранения данных: JSON и Hashes. Соединитель Redis поддерживает как типы хранилища, так и сопоставление отличается в зависимости от выбранного типа хранилища.

Сопоставление данных при использовании типа хранилища JSON

При использовании типа хранилища JSON соединитель Redis будет использовать System.Text.Json.JsonSerializer для сопоставления. Так как Redis хранит записи с отдельным ключом и значением, приложение mapper сериализует все свойства, кроме ключа в объект JSON, и использует его в качестве значения.

JsonPropertyNameAttribute Использование поддерживается, если требуется другое имя хранилища для имени свойства модели данных. Также можно использовать пользовательский JsonSerializerOptions экземпляр с настраиваемой политикой именования свойств. Чтобы включить это, JsonSerializerOptions необходимо передать в RedisJsonVectorStoreRecordCollection строительство.

var jsonSerializerOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseUpper };
var collection = new RedisJsonVectorStoreRecordCollection<Hotel>(
    ConnectionMultiplexer.Connect("localhost:6379").GetDatabase(),
    "skhotelsjson",
    new() { JsonSerializerOptions = jsonSerializerOptions });

Так как выбрана политика именования верхнего регистра змеи, вот пример того, как этот тип данных будет установлен в Redis. Кроме того, обратите внимание на использование JsonPropertyNameAttribute Description свойства для дальнейшей настройки именования хранилища.

using System.Text.Json.Serialization;
using Microsoft.Extensions.VectorData;

public class Hotel
{
    [VectorStoreRecordKey]
    public ulong HotelId { get; set; }

    [VectorStoreRecordData(IsFilterable = true)]
    public string HotelName { get; set; }

    [JsonPropertyName("HOTEL_DESCRIPTION")]
    [VectorStoreRecordData(IsFullTextSearchable = true)]
    public string Description { get; set; }

    [VectorStoreRecordVector(Dimensions: 4, DistanceFunction.CosineDistance, IndexKind.Hnsw)]
    public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
}
JSON.SET skhotelsjson:h1 $ '{ "HOTEL_NAME": "Hotel Happy", "HOTEL_DESCRIPTION": "A place where everyone can be happy.", "DESCRIPTION_EMBEDDING": [0.9, 0.1, 0.1, 0.1] }'

Сопоставление данных при использовании типа хранилища Hashes

При использовании типа хранилища Hashes соединитель Redis предоставляет собственную схему для сопоставления. Это приложение mapper сопоставляет каждое свойство с парой "поле-значение", как поддерживается командой Redis HSET .

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

Переопределение имени свойства выполняется путем задания StoragePropertyName параметра с помощью атрибутов модели данных или определения записи.

Ниже приведен пример модели данных с StoragePropertyName набором атрибутов и их настройке в Redis.

using Microsoft.Extensions.VectorData;

public class Hotel
{
    [VectorStoreRecordKey]
    public ulong HotelId { get; set; }

    [VectorStoreRecordData(IsFilterable = true, StoragePropertyName = "hotel_name")]
    public string HotelName { get; set; }

    [VectorStoreRecordData(IsFullTextSearchable = true, StoragePropertyName = "hotel_description")]
    public string Description { get; set; }

    [VectorStoreRecordVector(Dimensions: 4, DistanceFunction.CosineDistance, IndexKind.Hnsw, StoragePropertyName = "hotel_description_embedding")]
    public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
}
HSET skhotelshashes:h1 hotel_name "Hotel Happy" hotel_description 'A place where everyone can be happy.' hotel_description_embedding <vector_bytes>