说明:文中所有类名 / 方法名均在本地
spring-ai 1.1.3的 jar 中核对过。中文文档(1.0 时代示例)里几处旧 API,统一整理在最后的「踩坑清单」。
1. 它是什么
-
传统关系库:精确匹配 (
where id = ?)。 -
向量库:相似性搜索 ------ 给一个查询向量,返回"相似"的向量(KNN)。
-
向量库本身不生成向量 ,只负责存储 + 检索。向量由
EmbeddingModel生成(float[])。 -
在 RAG 里的位置:
灌库:文档 → 切分 → EmbeddingModel 向量化 → VectorStore 存储
提问:问题 → 向量化 → 相似度检索 topK → 检索结果作为上下文拼进提示词 → 大模型回答
2. 核心 API(1.1.3 实测签名)
java
// 只读检索(函数式接口,最小权限原则)
@FunctionalInterface
public interface VectorStoreRetriever {
List<Document> similaritySearch(SearchRequest request);
default List<Document> similaritySearch(String query) { ... }
}
// 读写
public interface VectorStore extends DocumentWriter, VectorStoreRetriever {
void add(List<Document> documents);
void delete(List<String> idList);
void delete(Filter.Expression filterExpression);
default void delete(String filterExpression) { ... } // 字符串 DSL
default <T> Optional<T> getNativeClient() { ... } // 拿底层原生客户端
}
Document 常用方法(注意是 getText()):
java
doc.getId();
doc.getText();
doc.getMetadata();
doc.getScore();
SearchRequest 默认值:topK = 4、similarityThreshold = 0.0(即 SIMILARITY_THRESHOLD_ACCEPT_ALL,不过滤)。
3. 支持的 19 种实现
Azure / Cassandra / Chroma / Elasticsearch / GemFire / MariaDB / Milvus / MongoDB Atlas / Neo4j / OpenSearch / Oracle / PgVector / Pinecone / Qdrant / Redis / SAP Hana / Typesense / Weaviate,外加 SimpleVectorStore(内存实现,教学用)。
4. 三种接入方式
A. Starter 自动配置(推荐)
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-milvus</artifactId>
</dependency>
yaml
spring:
ai:
vectorstore:
milvus:
client: { host: localhost, port: 19530 }
initialize-schema: true # ⚠ 1.1 起默认 false,需要显式打开
embedding-dimension: 1536 # 必须和 embedding 模型维度一致
这样才会有 VectorStore bean 可以 @Autowired。
B. 手动配置(不用自动配置)
依赖换成非 starter 的 spring-ai-milvus-store,然后:
java
@Bean
public VectorStore vectorStore(MilvusServiceClient client, EmbeddingModel embeddingModel) {
return MilvusVectorStore.builder(client, embeddingModel)
.collectionName("test_vector_store")
.indexType(IndexType.IVF_FLAT)
.metricType(MetricType.COSINE)
.batchingStrategy(new TokenCountBatchingStrategy())
.initializeSchema(true)
.build();
}
C. SimpleVectorStore(本模块在用)
不会被自动配置,必须自己声明:
java
@Bean
public SimpleVectorStore vectorStore(EmbeddingModel embeddingModel) {
return SimpleVectorStore.builder(embeddingModel).build();
}
内存存储,重启即丢,只适合演示 / 教学。
5. 读写删最小示例
java
// 写
vectorStore.add(List.of(new Document("Spring AI rocks", Map.of("country", "BG"))));
// 读(两种方式等价)
List<Document> docs = retriever.similaritySearch("Spring");
List<Document> docs2 = retriever.similaritySearch(SearchRequest.builder()
.query("Spring").topK(5).similarityThreshold(0.7).build());
// 删:按 ID / 按过滤表达式 / 按字符串表达式
vectorStore.delete(List.of(doc.getId()));
vectorStore.delete(b.eq("country", "BG").build());
vectorStore.delete("country == 'BG'");
性能:按 ID 删最快;按过滤器删可能扫索引;大批量删除要分批做。
6. 元数据过滤(只作用于 metadata,类似 SQL where)
字符串 DSL:
"country == 'BG'"
"genre in ['comedy','drama'] && year >= 2020"
编程式:
java
FilterExpressionBuilder b = new FilterExpressionBuilder();
Filter.Expression exp = b.and(b.in("genre", "drama", "documentary"),
b.not(b.lt("year", 2020))).build();
运算符:
- 比较:
==!=>>=<<= - 组合:
AND/&&、OR/|| - 其它:
IN、NIN、NOT、IS NULL/IS NOT NULL(并非所有向量库都实现了 NULL 判断)
本项目提醒:
KnowledgeBase的元数据是source/category,笔记示例里的type == 'Spring'、genre == 'fairytale'命中不了,要么改语料,要么改过滤表达式。
7. 批处理策略(大批量灌库必看)
- 接口:
org.springframework.ai.embedding.BatchingStrategy#batch(List<Document>)。 - 默认实现
TokenCountBatchingStrategy:上限 8191 token、预留 10%,即实际8191 * 0.9;单文档超限直接抛异常。 - 覆盖默认:注册一个自己的 bean 即可(自动配置会被替换)。
java
@Bean
public BatchingStrategy customBatchingStrategy() {
return new TokenCountBatchingStrategy(EncodingType.CL100K_BASE, 8000, 0.1);
}
- 若 embedding 模型支持
autoTruncate(如 Vertex AI),要把批处理上限设成模型实际限制的 5~10 倍,否则批策略先抛异常、模型根本没机会截断。 - 但静默截断会丢掉长文档尾部信息 → 更推荐灌库前先切分。
8. 读写分离写法(推荐)
灌库服务依赖 VectorStore,检索服务只依赖 VectorStoreRetriever:
java
@Service
class DocumentRetriever {
private final VectorStoreRetriever retriever;
DocumentRetriever(VectorStoreRetriever retriever) { this.retriever = retriever; }
List<Document> findSimilar(String query) { return retriever.similaritySearch(query); }
}
好处:最小权限、依赖更少、函数式接口可用 lambda / 方法引用造测试替身。
9. ⚠ 1.1.3 踩坑清单(文档 vs 实际)
| 文档 / 教程写法 | 1.1.3 实际 |
|---|---|
Document::getContent |
Document::getText(另有 getFormattedContent()) |
chatModel.generate(prompt) |
chatModel.call(String) |
| schema 自动初始化 | initialize-schema 默认 false,需显式打开 |
直接 @Autowired VectorStore |
必须有具体 starter 或自己声明 bean;SimpleVectorStore 不自动配置 |
Document.getScore() 一定有值 |
存在该 API,但不匹配时为 null,用前先判空 |
本项目专属坑:DeepSeek 没有 embedding 接口 ,spring.ai.openai.embedding.* 必须另配服务(SiliconFlow / 通义兼容模式 / Ollama),否则 add() 直接 404;且入库与检索必须用同一个 embedding 模型,否则维度不匹配。
java
List<Document> docs = new JsonReader(new FileSystemResource(file), "name", "description").get();
vectorStore.add(docs);