使用 Redis 连接器 (预览版)
警告
语义内核向量存储功能目前处于预览阶段,在发布前仍可能在有限情况下进行需要重大变更的改进。
概述
Redis 矢量存储连接器可用于访问和管理 Redis 中的数据。 连接器同时支持哈希和 JSON 模式,选择的模式将确定支持哪些其他功能。
连接器具有以下特征。
功能区域 | 支持 |
---|---|
集合映射到 | 前缀设置为 <collectionname>: 的 Redis 索引 |
支持的键属性类型 | 字符串 |
支持的数据属性类型 |
使用哈希时:
任何可序列化为 JSON 的类型 |
支持的向量属性类型 |
|
支持的索引类型 |
|
支持的距离函数 |
|
支持的过滤条件 |
|
支持记录中的多个向量 | 是 |
是否支持Filterable? | 是 |
是否支持FullTextSearchable? | 是 |
StoragePropertyName 支持吗? |
使用哈希时: 是 使用 JSON 时:不要,用 JsonSerializerOptions 和JsonPropertyNameAttribute 替代。
有关详细信息,请参阅此处。 |
支持 HybridSearch? | 否 |
入门
将 Redis Vector Store 连接器 nuget 包添加到项目。
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 矢量存储实例。
using Microsoft.SemanticKernel.Connectors.Redis;
using StackExchange.Redis;
var vectorStore = new RedisVectorStore(ConnectionMultiplexer.Connect("localhost:6379").GetDatabase());
可以构造对命名集合的直接引用。 执行此操作时,必须在 JSON 或哈希实例之间进行选择,具体取决于要在 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
使用的首选存储类型/模式的实例:哈希或 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]
。有关更多信息,请参阅 此处。
有关此概念的更多详细信息,请参阅 序列化文档。
入门
在 Maven 项目中添加以下依赖项 pom.xml
,以包括最新版本的语义内核 Redis 数据连接器:
<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 和哈希。 Redis 连接器支持这两种存储类型,映射因所选存储类型而异。
使用 JSON 存储类型时的数据映射
使用 JSON 存储类型时,Redis 连接器将使用 System.Text.Json.JsonSerializer
进行映射。
由于 Redis 存储具有单独键和值的记录,因此映射器将序列化除 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 中设置此数据类型的示例。
另请注意在 Description
属性上使用 JsonPropertyNameAttribute
,以进一步自定义存储命名。
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.CosineSimilarity, 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] }'
使用哈希存储类型时的数据映射
使用哈希存储类型时,Redis 连接器提供自己的映射器来执行映射。
此映射器将每个属性映射到 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.CosineSimilarity, 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>