Compartir a través de


Uso del conector de Redis (versión preliminar)

Advertencia

La funcionalidad Almacén de vectores de kernel semántico está en versión preliminar y las mejoras que requieren cambios importantes pueden producirse en circunstancias limitadas antes de la versión.

Información general

El conector del almacén de vectores de Redis se puede usar para acceder a los datos y administrarlos en Redis. El conector admite los modos Hash y JSON y el modo que elija determinará qué otras características se admiten.

El conector tiene las siguientes características.

Área de características Soporte técnico
La colección se asigna a Índice de Redis con prefijo establecido en <collectionname>:
Tipos de propiedades de clave admitidos string
Tipos de propiedad de datos admitidos Al usar hashes:
  • string
  • int
  • uint
  • long
  • ulong
  • double
  • FLOAT
  • bool
Al usar JSON:
Cualquier tipo serializable en JSON
Tipos de propiedades vectoriales admitidos
  • ReadOnlyMemory<float>
  • ReadOnlyMemory<double>
Tipos de índice admitidos
  • Hnsw
  • Plano
Funciones de distancia admitidas
  • CosineSimilarity
  • DotProductSimilarity
  • EuclideanDistance
Admite varios vectores en un registro
¿Se admite IsFilterable?
¿Se admite IsFullTextSearchable?
¿Se admite StoragePropertyName? Al usar hashes:
Al usar JSON: No, use JsonSerializerOptions y JsonPropertyNameAttribute en su lugar. Consulta aquí para obtener más información.

Introducción

Agregue el paquete nuget del conector del almacén de vectores de Redis al proyecto.

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

Puede agregar el almacén de vectores al contenedor de inserción de dependencias disponible en KernelBuilder o al IServiceCollection contenedor de inserción de dependencias mediante métodos de extensión proporcionados por kernel semántico.

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");

También se proporcionan métodos de extensión que no toman parámetros. Estos requieren que una instancia de Redis IDatabase se registre por separado con el contenedor de inserción de dependencias.

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();

Puede construir una instancia de Redis Vector Store directamente.

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

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

Es posible construir una referencia directa a una colección con nombre. Al hacerlo, debe elegir entre la instancia JSON o Hashes en función de cómo desea almacenar datos en 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");

Al construir RedisVectorStore o registrarlo con el contenedor de inserción de dependencias, es posible pasar una RedisVectorStoreOptions instancia que configure el tipo de almacenamiento o modo preferido usado: Hashes o JSON. Si no se especifica, el valor predeterminado es JSON.

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

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

Introducción

Instale el kernel semántico con los extras de redis, que incluye el cliente de redis.

pip install semantic-kernel[redis]

A continuación, puede crear una instancia de almacén de vectores mediante la RedisStore clase , que usará las variables REDIS_CONNECTION_STRING de entorno para conectarse a una instancia de Redis, esos valores también se pueden proporcionar directamente.


from semantic_kernel.connectors.memory.redis import RedisStore

vector_store = RedisStore()

También puede crear el almacén de vectores con su propia instancia del cliente de base de datos 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)

También puede crear una colección directamente, pero hay dos tipos de colecciones, una para Hashes y otra para 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)

Al crear una colección a partir del almacén de vectores, puede pasar el tipo de colección como enumeración: RedisCollectionTypes, el valor predeterminado es una colección hash.

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,
)

Serialización

Las colecciones redis usan un dict como formato de datos al subir, pero la estructura de los dicts son diferentes entre ellas.

Para las colecciones JSON, consulte la documentación de redis para obtener un ejemplo.

En el caso de las colecciones hashset, usa el comando hset con el campo de clave como name, los campos de datos como mapping -> metadata y los vectores como mapping -> [vector_field_name] , consulte aquí para obtener más información.

Para obtener más información sobre este concepto, consulte la documentación de serialización.

Introducción

Incluya la versión más reciente del conector de datos Semantic Kernel Redis en el proyecto de Maven agregando la siguiente dependencia a pom.xml:

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

A continuación, puede crear una instancia de almacén de vectores mediante la RedisVectorStore clase , teniendo el cliente de Redis (JedisPooled) como parámetro.

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();
    }
}

También puede recuperar una colección directamente.

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

Prefijos de índice

Redis usa un sistema de prefijos de clave para asociar un registro a un índice. Al crear un índice, puede especificar uno o varios prefijos para usarlos con ese índice. Si desea asociar un registro a ese índice, debe agregar el prefijo a la clave de ese registro.

Por ejemplo, si crea un índice denominado skhotelsjson con un prefijo de skhotelsjson:, al establecer un registro con clave h1, la clave de registro tendrá que tener como prefijo como este skhotelsjson:h1 para agregarlo al índice.

Al crear una nueva colección mediante el conector de Redis, el conector creará un índice en Redis con un prefijo que consta del nombre de la colección y de dos puntos, como este <collectionname>:. De forma predeterminada, el conector también prefijo todas las claves con este prefijo al realizar operaciones de registro como Get, Upsert y Delete.

Si no quería usar un prefijo formado por el nombre de la colección y dos puntos, es posible desactivar el comportamiento de prefijo y pasar la clave completamente prefijo a las operaciones de registro.

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();

Asignación de datos

Redis admite dos modos para almacenar datos: JSON y Hashes. El conector de Redis admite ambos tipos de almacenamiento y la asignación difiere en función del tipo de almacenamiento elegido.

Asignación de datos al usar el tipo de almacenamiento JSON

Al usar el tipo de almacenamiento JSON, el conector de Redis usará System.Text.Json.JsonSerializer para realizar la asignación. Dado que Redis almacena registros con una clave y un valor independientes, el asignador serializará todas las propiedades excepto la clave en un objeto JSON y la usará como valor.

Se admite el JsonPropertyNameAttribute uso de si se requiere un nombre de almacenamiento diferente al nombre de la propiedad del modelo de datos. También es posible usar una instancia personalizada JsonSerializerOptions con una directiva de nomenclatura de propiedades personalizada. Para habilitar esto, JsonSerializerOptions debe pasarse a la RedisJsonVectorStoreRecordCollection construcción en .

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

Dado que se eligió una directiva de nomenclatura de mayúsculas y minúsculas de serpiente, este es un ejemplo de cómo se establecerá este tipo de datos en Redis. Tenga en cuenta también el uso de JsonPropertyNameAttribute en la Description propiedad para personalizar aún más la nomenclatura del almacenamiento.

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] }'

Asignación de datos al usar el tipo de almacenamiento Hashes

Al usar el tipo de almacenamiento Hashes, el conector de Redis proporciona su propio asignador para realizar la asignación. Este asignador asignará cada propiedad a un par de valores de campo como admite el comando redis HSET .

En el caso de las propiedades de datos y las propiedades vectoriales, puede proporcionar nombres de campo de invalidación para usarlos en el almacenamiento que es diferente a los nombres de propiedad del modelo de datos. Esto no se admite para las claves, ya que las claves no se pueden denominar en Redis.

La invalidación del nombre de propiedad se realiza estableciendo la StoragePropertyName opción a través de los atributos del modelo de datos o la definición de registro.

Este es un ejemplo de un modelo de datos con StoragePropertyName establecido en sus atributos y cómo se establecen en 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>