Usando o conector Redis (Visualização)
Aviso
A funcionalidade Semantic Kernel Vetor Store está em pré-visualização, e melhorias que exigem alterações de quebra ainda podem ocorrer em circunstâncias limitadas antes do lançamento.
Descrição geral
O conector Redis Vetor Store pode ser usado para acessar e gerenciar dados no Redis. O conector suporta os modos Hashes e JSON e qual modo você escolher determinará quais outros recursos são suportados.
O conector tem as seguintes características.
Área de funcionalidades | Suporte |
---|---|
Mapas da coleção para | Índice Redis com prefixo definido como <collectionname>: |
Tipos de propriedade de chave suportados | string |
Tipos de propriedade de dados suportados | Ao usar Hashes:
Qualquer tipo serializável para JSON |
Tipos de propriedade vetorial suportados |
|
Tipos de índice suportados |
|
Funções de distância suportadas |
|
Suporta vários vetores em um registro | Sim |
IsFilterable suportado? | Sim |
IsFullTextSearchable suportado? | Sim |
StoragePropertyName suportado? | Ao usar Hashes: Sim Ao usar JSON: Não, use JsonSerializerOptions e JsonPropertyNameAttribute em vez disso. Veja aqui mais informações. |
Introdução
Adicione o pacote nuget do conector Redis Vetor Store ao seu projeto.
dotnet add package Microsoft.SemanticKernel.Connectors.Redis --prerelease
Você pode adicionar o armazenamento vetorial ao contêiner de injeção de dependência disponível no KernelBuilder
ou ao contêiner de IServiceCollection
injeção de dependência usando métodos de extensão fornecidos pelo Semantic Kernel.
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");
Métodos de extensão que não usam parâmetros também são fornecidos. Isso requer que uma instância do Redis IDatabase
seja registrada separadamente com o contêiner de injeção de dependência.
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();
Você pode construir uma instância do Redis Vetor Store diretamente.
using Microsoft.SemanticKernel.Connectors.Redis;
using StackExchange.Redis;
var vectorStore = new RedisVectorStore(ConnectionMultiplexer.Connect("localhost:6379").GetDatabase());
É possível construir uma referência direta a uma coleção nomeada. Ao fazer isso, você tem que escolher entre a instância JSON ou Hashes, dependendo de como você deseja armazenar dados no 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");
Ao construir ou RedisVectorStore
registrá-lo com o contêiner de injeção de dependência, é possível passar uma RedisVectorStoreOptions
instância que configura o tipo/modo de armazenamento preferencial usado: Hashes ou JSON. Se não for especificado, o padrão será JSON.
using Microsoft.SemanticKernel.Connectors.Redis;
using StackExchange.Redis;
var vectorStore = new RedisVectorStore(
ConnectionMultiplexer.Connect("localhost:6379").GetDatabase(),
new() { StorageType = RedisStorageType.HashSet });
Introdução
Instale o kernel semântico com os extras do redis, que inclui o cliente redis.
pip install semantic-kernel[redis]
Você pode então criar uma instância de armazenamento de vetores usando a RedisStore
classe, isso usará as variáveis REDIS_CONNECTION_STRING
de ambiente para se conectar a uma instância do Redis, esses valores também podem ser fornecidos diretamente.
from semantic_kernel.connectors.memory.redis import RedisStore
vector_store = RedisStore()
Você também pode criar o repositório de vetores com sua própria instância do cliente de banco de dados 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)
Você também pode criar uma coleção diretamente, mas há dois tipos de coleções, uma para Hashes e outra 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)
Ao criar uma coleção a partir do repositório de vetores, você pode passar o tipo de coleção, como um enum: RedisCollectionTypes
, o padrão é uma coleção de 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,
)
Serialização
As coleções redis usam um ditado como o formato de dados ao atualizar, no entanto, a estrutura dos ditames é diferente entre eles.
Para coleções JSON, consulte redis docs para obter um exemplo.
Para coleções de Hashset, ele usa o comando hset com o campo de chave como name
, campos de dados como mapping -> metadata
e vetores como mapping -> [vector_field_name]
, veja aqui para obter mais informações.
Para obter mais detalhes sobre esse conceito, consulte a documentação de serialização.
Introdução
Inclua a versão mais recente do conector de dados Redis do kernel semântico em seu projeto Maven adicionando a seguinte dependência ao seu pom.xml
:
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-data-redis</artifactId>
<version>[LATEST]</version>
</dependency>
Em seguida, você pode criar uma instância de armazenamento de vetores usando a RedisVectorStore
classe, tendo o cliente 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();
}
}
Você também pode recuperar uma coleção diretamente.
var collection = vectorStore.getCollection("skhotels",
RedisJsonVectorStoreRecordCollectionOptions.<Hotel>builder()
.withRecordClass(Hotel.class)
.build());
Prefixos de índice
O Redis usa um sistema de prefixo de chave para associar um registro a um índice. Ao criar um índice, você pode especificar um ou mais prefixos para usar com esse índice. Se quiser associar um registo a esse índice, tem de adicionar o prefixo à chave desse registo.
Por exemplo, se você criar um índice chamado skhotelsjson
com um prefixo de , ao definir um registro com chaveh1
, a chave de registro precisará ser prefixada como esta skhotelsjson:h1
para ser adicionada skhotelsjson:
ao índice.
Ao criar uma nova coleção usando o conector Redis, o conector criará um índice no Redis com um prefixo que consiste no nome da coleção e dois pontos, como este <collectionname>:
.
Por padrão, o conector também prefixará todas as chaves com o prefixo this ao fazer operações de registro como Get, Upsert e Delete.
Se você não quiser usar um prefixo que consiste no nome da coleção e dois pontos, é possível desativar o comportamento de prefixo e passar a chave totalmente prefixada para as operações 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();
Mapeamento de dados
O Redis suporta dois modos de armazenamento de dados: JSON e Hashes. O conector Redis suporta ambos os tipos de armazenamento e o mapeamento difere dependendo do tipo de armazenamento escolhido.
Mapeamento de dados ao usar o tipo de armazenamento JSON
Ao usar o tipo de armazenamento JSON, o conector Redis será usado System.Text.Json.JsonSerializer
para fazer o mapeamento.
Como o Redis armazena registros com uma chave e um valor separados, o mapeador serializará todas as propriedades, exceto a chave para um objeto JSON, e usará isso como o valor.
O uso do é suportado se for necessário um nome de armazenamento diferente para o nome da propriedade do modelo de JsonPropertyNameAttribute
dados. Também é possível usar uma instância personalizada JsonSerializerOptions
com uma política de nomenclatura de propriedade personalizada. Para permitir isso, o JsonSerializerOptions
deve ser passado para a RedisJsonVectorStoreRecordCollection
construção on.
var jsonSerializerOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseUpper };
var collection = new RedisJsonVectorStoreRecordCollection<Hotel>(
ConnectionMultiplexer.Connect("localhost:6379").GetDatabase(),
"skhotelsjson",
new() { JsonSerializerOptions = jsonSerializerOptions });
Como uma política de nomenclatura de maiúsculas e minúsculas foi escolhida, aqui está um exemplo de como esse tipo de dados será definido no Redis.
Observe também o uso de on the Description
property para personalizar ainda mais a nomenclatura do JsonPropertyNameAttribute
armazenamento.
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] }'
Mapeamento de dados ao usar o tipo de armazenamento Hashes
Ao usar o tipo de armazenamento Hashes, o conector Redis fornece seu próprio mapeador para fazer mapeamento.
Esse mapeador mapeará cada propriedade para um par campo-valor, conforme suportado pelo comando Redis HSET
.
Para propriedades de dados e propriedades de vetor, você pode fornecer nomes de campo de substituição para uso no armazenamento que sejam diferentes dos nomes de propriedade no modelo de dados. Isso não é suportado para chaves, uma vez que as chaves não podem ser nomeadas no Redis.
A substituição do nome da propriedade é feita definindo a StoragePropertyName
opção por meio dos atributos do modelo de dados ou da definição do registro.
Aqui está um exemplo de um modelo de dados com StoragePropertyName
atributos definidos e como eles são definidos no 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>