Redis
本节将引导你设置 RedisVectorStore,用于存储文档向量(embeddings)并执行相似性搜索。
Redis 是一个开源(BSD 许可)的内存数据结构存储,可用作数据库、缓存、消息代理和流处理引擎。Redis 提供的数据结构包括字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、带范围查询的有序集合(sorted sets)、位图(bitmaps)、HyperLogLogs、地理空间索引(geospatial indexes)以及流(streams)。
Redis Search 和 Query 扩展了 Redis OSS 的核心功能,使你可以将 Redis 用作向量数据库:
- 在哈希或 JSON 文档中存储向量及其相关元数据
- 检索向量
- 执行向量搜索
前置条件
- 一个 Redis Stack 实例:
- Redis Cloud(推荐)
- Docker 镜像:
redis/redis-stack:latest
- 需要一个
EmbeddingModel实例来计算文档向量(embeddings),有多种选项可供选择:- 如果需要,还需为 EmbeddingModel 提供 API Key,用于生成存储在
RedisVectorStore中的向量嵌入。
- 如果需要,还需为 EmbeddingModel 提供 API Key,用于生成存储在
自动配置
Spring AI 为 Redis 向量存储提供了 Spring Boot 自动配置。要启用它,请在项目的 Maven pom.xml 文件中添加以下依赖:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-redis</artifactId>
</dependency>
或者在 Gradle 的 build.gradle 文件中添加:
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-vector-store-redis'
}
向量存储实现可以为你初始化所需的 schema,但你必须显式选择启用,通过在相应构造函数中指定 initializeSchema 布尔值,或在 application.properties 文件中设置:
spring.ai.vectorstore.redis.initialize-schema=true
请查看向量存储的 配置参数 列表,了解默认值及其他配置选项。
此外,你还需要配置一个 EmbeddingModel Bean,具体信息请参考 EmbeddingModel 章节。
现在,你可以在应用中自动注入 RedisVectorStore 并使用它:
@Autowired
VectorStore vectorStore;
// ...
List<Document> documents = List.of(
new Document("Spring AI 很棒!!Spring AI 很棒!!Spring AI 很棒!!Spring AI 很棒!!Spring AI 很棒!!", Map.of("meta1", "meta1")),
new Document("世界很大,救赎就在拐角处"),
new Document("你向前走面向过去,同时回望未来", Map.of("meta2", "meta2"))
);
// 将文档添加到 Redis
vectorStore.add(documents);
// 根据查询检索相似文档
List<Document> results = vectorStore.similaritySearch(
SearchRequest.builder().query("Spring").topK(5).build()
);
配置属性
要连接 Redis 并使用 RedisVectorStore,你需要提供实例的访问信息。可以通过 Spring Boot 的 application.yml 提供简单配置:
spring:
data:
redis:
url: <redis 实例 URL>
ai:
vectorstore:
redis:
initialize-schema: true
index-name: custom-index
prefix: custom-prefix
对于 Redis 连接配置,也可以通过 Spring Boot 的 application.properties 提供简单配置:
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.username=default
spring.data.redis.password=
以 spring.ai.vectorstore.redis.* 开头的属性用于配置 RedisVectorStore:
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.vectorstore.redis.initialize-schema | 是否初始化所需的 schema | false |
spring.ai.vectorstore.redis.index-name | 用于存储向量的索引名称 | spring-ai-index |
spring.ai.vectorstore.redis.prefix | Redis 键的前缀 | embedding: |
元数据过滤
你也可以在 Redis 中使用通用、可移植的 元数据过滤器。
例如,你可以使用文本表达式语言:
vectorStore.similaritySearch(
SearchRequest.builder()
.query("The World")
.topK(TOP_K)
.similarityThreshold(SIMILARITY_THRESHOLD)
.filterExpression("country in ['UK', 'NL'] && year >= 2020")
.build()
);
或者通过编程方式使用 Filter.Expression DSL:
FilterExpressionBuilder b = new FilterExpressionBuilder();
vectorStore.similaritySearch(
SearchRequest.builder()
.query("The World")
.topK(TOP_K)
.similarityThreshold(SIMILARITY_THRESHOLD)
.filterExpression(
b.and(
b.in("country", "UK", "NL"),
b.gte("year", 2020)
).build()
)
.build()
);
例如,这个可移植过滤表达式:
country in ['UK', 'NL'] && year >= 2020
会被转换为 Redis 专有格式:
@country:{UK | NL} @year:[2020 inf]
手动配置
你可以选择不使用 Spring Boot 自动配置,而是手动配置 Redis 向量存储。为此,你需要将 spring-ai-redis-store 添加到项目中:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-redis-store</artifactId>
</dependency>
或者在 Gradle 的 build.gradle 文件中添加:
dependencies {
implementation 'org.springframework.ai:spring-ai-redis-store'
}
创建一个 JedisPooled Bean:
@Bean
public JedisPooled jedisPooled() {
return new JedisPooled("<host>", 6379);
}
然后使用构建者模式(builder pattern)创建 RedisVectorStore Bean:
@Bean
public VectorStore vectorStore(JedisPooled jedisPooled, EmbeddingModel embeddingModel) {
return RedisVectorStore.builder(jedisPooled, embeddingModel)
.indexName("custom-index") // 可选,默认: "spring-ai-index"
.prefix("custom-prefix") // 可选,默认: "embedding:"
.metadataFields( // 可选,为过滤器定义元数据字段
MetadataField.tag("country"),
MetadataField.numeric("year"))
.initializeSchema(true) // 可选,默认: false
.batchingStrategy(new TokenCountBatchingStrategy()) // 可选,默认: TokenCountBatchingStrategy
.build();
}
// 这里可以使用任何 EmbeddingModel 实现
@Bean
public EmbeddingModel embeddingModel() {
return new OpenAiEmbeddingModel(new OpenAiApi(System.getenv("OPENAI_API_KEY")));
}
TAG、TEXT 或 NUMERIC)。上例中的 metadataFields 注册了可用于过滤的元数据字段:country类型为 TAGyear类型为 NUMERIC
访问原生客户端
Redis 向量存储实现通过 getNativeClient() 方法提供对底层原生 Redis 客户端(JedisPooled)的访问:
RedisVectorStore vectorStore = context.getBean(RedisVectorStore.class);
Optional<JedisPooled> nativeClient = vectorStore.getNativeClient();
if (nativeClient.isPresent()) {
JedisPooled jedis = nativeClient.get();
// 使用原生客户端执行 Redis 特定操作
}
原生客户端让你可以访问 VectorStore 接口未暴露的 Redis 特定功能和操作。