序
本文主要研究一下Spring AI的RedisVectorStore
示例
pom.xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-redis</artifactId>
</dependency>
配置
spring:
ai:
vectorstore:
type: redis
redis:
initialize-schema: true
indexName: default-idx
prefix: "default:"
代码
@Test
public void testAddAndSearch() {
List<Document> documents = List.of(
new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("meta1", "meta1")),
new Document("The World is Big and Salvation Lurks Around the Corner"),
new Document("You walk forward facing the past and you turn back toward the future.", Map.of("meta2", "meta2")));
// Add the documents to Milvus Vector Store
redisVectorStore.add(documents);
// Retrieve documents similar to a query
List<Document> results = this.redisVectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build());
log.info("results:{}", JSON.toJSONString(results));
}
输出如下:
results:[{"contentFormatter":{"excludedEmbedMetadataKeys":[],"excludedInferenceMetadataKeys":[],"metadataSeparator":"\n","metadataTemplate":"{key}: {value}","textTemplate":"{metadata_string}\n\n{content}"},"formattedContent":"distance: 0.21754569\nvector_score: 0.21754569\n\nSpring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!","id":"8edf4d98-6730-4b19-8681-67bbd7aa002d","metadata":{"distance":0.21754569,"vector_score":0.21754569},"score":0.7824543118476868,"text":"Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!"},{"contentFormatter":{"$ref":"$[0].contentFormatter"},"formattedContent":"distance: 0.21754569\nvector_score: 0.21754569\n\nSpring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!","id":"dbdcc61f-7f7c-4c61-9491-aaf3ddb15ae9","metadata":{"distance":0.21754569,"vector_score":0.21754569},"score":0.7824543118476868,"text":"Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!"},{"contentFormatter":{"$ref":"$[0].contentFormatter"},"formattedContent":"distance: 0.2854656\nvector_score: 0.2854656\n\nThe World is Big and Salvation Lurks Around the Corner","id":"a28f2344-3389-427a-9a3d-69e3a1000a05","metadata":{"distance":0.2854656,"vector_score":0.2854656},"score":0.7145344018936157,"text":"The World is Big and Salvation Lurks Around the Corner"},{"contentFormatter":{"$ref":"$[0].contentFormatter"},"formattedContent":"distance: 0.2854656\nvector_score: 0.2854656\n\nThe World is Big and Salvation Lurks Around the Corner","id":"874aff9b-cd3d-41d9-9114-47157f3e4ccc","metadata":{"distance":0.2854656,"vector_score":0.2854656},"score":0.7145344018936157,"text":"The World is Big and Salvation Lurks Around the Corner"},{"contentFormatter":{"$ref":"$[0].contentFormatter"},"formattedContent":"distance: 0.2968012\nvector_score: 0.2968012\n\nYou walk forward facing the past and you turn back toward the future.","id":"c90a7824-dcdb-4855-ab07-0ac3629fba83","metadata":{"distance":0.2968012,"vector_score":0.2968012},"score":0.7031987905502319,"text":"You walk forward facing the past and you turn back toward the future."}]
源码
RedisVectorStoreAutoConfiguration
org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreAutoConfiguration.java
@AutoConfiguration(after = RedisAutoConfiguration.class)
@ConditionalOnClass({ JedisPooled.class, JedisConnectionFactory.class, RedisVectorStore.class, EmbeddingModel.class })
@ConditionalOnBean(JedisConnectionFactory.class)
@EnableConfigurationProperties(RedisVectorStoreProperties.class)
@ConditionalOnProperty(name = SpringAIVectorStoreTypes.TYPE, havingValue = SpringAIVectorStoreTypes.REDIS,
matchIfMissing = true)
public class RedisVectorStoreAutoConfiguration {
@Bean
@ConditionalOnMissingBean(BatchingStrategy.class)
BatchingStrategy batchingStrategy() {
return new TokenCountBatchingStrategy();
}
@Bean
@ConditionalOnMissingBean
public RedisVectorStore vectorStore(EmbeddingModel embeddingModel, RedisVectorStoreProperties properties,
JedisConnectionFactory jedisConnectionFactory, ObjectProvider<ObservationRegistry> observationRegistry,
ObjectProvider<VectorStoreObservationConvention> customObservationConvention,
BatchingStrategy batchingStrategy) {
JedisPooled jedisPooled = this.jedisPooled(jedisConnectionFactory);
return RedisVectorStore.builder(jedisPooled, embeddingModel)
.initializeSchema(properties.isInitializeSchema())
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
.customObservationConvention(customObservationConvention.getIfAvailable(() -> null))
.batchingStrategy(batchingStrategy)
.indexName(properties.getIndexName())
.prefix(properties.getPrefix())
.build();
}
private JedisPooled jedisPooled(JedisConnectionFactory jedisConnectionFactory) {
String host = jedisConnectionFactory.getHostName();
int port = jedisConnectionFactory.getPort();
JedisClientConfig clientConfig = DefaultJedisClientConfig.builder()
.ssl(jedisConnectionFactory.isUseSsl())
.clientName(jedisConnectionFactory.getClientName())
.timeoutMillis(jedisConnectionFactory.getTimeout())
.password(jedisConnectionFactory.getPassword())
.build();
return new JedisPooled(new HostAndPort(host, port), clientConfig);
}
}
RedisVectorStoreAutoConfiguration在spring.ai.vectorstore.type
为redis
时启用,它在RedisAutoConfiguration之后自动配置,它依赖EmbeddingModel及RedisVectorStoreProperties来创建RedisVectorStore
RedisVectorStoreProperties
org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreProperties.java
@ConfigurationProperties(RedisVectorStoreProperties.CONFIG_PREFIX)
public class RedisVectorStoreProperties extends CommonVectorStoreProperties {
public static final String CONFIG_PREFIX = "spring.ai.vectorstore.redis";
private String indexName = "default-index";
private String prefix = "default:";
public String getIndexName() {
return this.indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public String getPrefix() {
return this.prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
}
RedisVectorStoreProperties主要是配置spring.ai.vectorstore.redis
配置,它从CommonVectorStoreProperties继承了initializeSchema属性,自己提供了indexName、prefix属性
RedisAutoConfiguration
org/springframework/boot/autoconfigure/data/redis/RedisAutoConfiguration.java
@AutoConfiguration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(RedisConnectionDetails.class)
PropertiesRedisConnectionDetails redisConnectionDetails(RedisProperties properties) {
return new PropertiesRedisConnectionDetails(properties);
}
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
}
RedisAutoConfiguration依赖RedisProperties以及LettuceConnectionConfiguration或者JedisConnectionConfiguration
RedisProperties
org/springframework/boot/autoconfigure/data/redis/RedisProperties.java
@ConfigurationProperties(prefix = "spring.data.redis")
public class RedisProperties {
/**
* Database index used by the connection factory.
*/
private int database = 0;
/**
* Connection URL. Overrides host, port, username, and password. Example:
* redis://user:password@example.com:6379
*/
private String url;
/**
* Redis server host.
*/
private String host = "localhost";
/**
* Login username of the redis server.
*/
private String username;
/**
* Login password of the redis server.
*/
private String password;
/**
* Redis server port.
*/
private int port = 6379;
/**
* Read timeout.
*/
private Duration timeout;
/**
* Connection timeout.
*/
private Duration connectTimeout;
/**
* Client name to be set on connections with CLIENT SETNAME.
*/
private String clientName;
/**
* Type of client to use. By default, auto-detected according to the classpath.
*/
private ClientType clientType;
private Sentinel sentinel;
private Cluster cluster;
private final Ssl ssl = new Ssl();
private final Jedis jedis = new Jedis();
private final Lettuce lettuce = new Lettuce();
//......
}
RedisProperties主要是配置spring.data.redis
,它提供了database、url、host、username、password、port、timeout、connectTimeout、clientName、clientType、sentinel、cluster、ssl、jedis、lettuce属性
小结
Spring AI提供了spring-ai-starter-vector-store-redis用于自动装配RedisVectorStore。可以使用redis/redis-stack:latest
这个docker镜像来验证。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。