Spring AI集成Chroma VectorStore技术详解与最佳实践
本文将系统讲解如何在Spring AI项目中集成Chroma向量数据库,实现文档嵌入存储与相似性检索。内容涵盖名词解释、技术背景、发展历史、权威资料引用,并通过多种Mermaid图表优化结构说明,帮助开发者知其然,更知其所以然。
一、概述
随着AI大模型、知识检索、RAG(Retrieval Augmented Generation)等技术的兴起,向量数据库成为存储与检索嵌入向量的核心组件。Chroma作为开源向量数据库,结合Spring AI生态,可轻松实现文档、内容、元数据的嵌入存储与高效检索。
二、名词解释
| 向量数据库 | 存储高维向量并支持向量相似性检索的数据库。代表产品有Chroma、Milvus等。 |
| Chroma | 一款开源嵌入式向量数据库,支持文档、向量与元数据存储与检索。 |
| EmbeddingModel | 嵌入模型,将文本/图片等数据转化为向量。常见如OpenAI Embedding API。 |
| VectorStore | 向量存储接口,Spring AI对向量数据库的抽象封装。 |
| SimilaritySearch | 基于向量的相似性检索,返回与查询向量最接近的内容。 |
| Metadata Filter | 通过元数据筛选检索结果的机制。 |
三、技术背景与发展历史
1. 项目背景
- AI应用场景:RAG、语义搜索、智能问答、知识库。
- 技术痛点:传统数据库无法高效进行语义相似性检索,而向量数据库为此而生。
- Spring AI发展:Spring AI自2023年起快速迭代,集成多种Embedding模型与向量数据库。
2. Chroma发展历程
- 2023年:Chroma项目开源,定位为易用、高性能的嵌入数据库。
- 2023年底:Chroma Cloud上线,支持云端多租户、数据库、集合管理。
- 2024年:Spring AI原生支持Chroma,简化Spring Boot下的集成流程。
参考资料
- Chroma 官方文档
- Spring AI 官方文档
- 向量数据库发展综述
四、系统性认知速记口
五、Spring AI集成Chroma实战详解
1. 环境准备
-
本地Chroma部署:
docker run -it –rm –name chroma -p 8000:8000 ghcr.io/chroma-core/chroma:1.0.0
启动后服务地址为 http://localhost:8000/api/v1
-
Maven依赖:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-chroma</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
2. 配置文件示例
# Chroma连接配置
spring.ai.vectorstore.chroma.client.host=http://localhost
spring.ai.vectorstore.chroma.client.port=8000
spring.ai.vectorstore.chroma.collection-name=TestCollection
spring.ai.vectorstore.chroma.initialize-schema=true
# OpenAI嵌入API Key
spring.ai.openai.api.key=你的OpenAI API Key
3. 代码集成示例
嵌入模型Bean
@Bean
public EmbeddingModel embeddingModel() {
return new OpenAiEmbeddingModel(OpenAiApi.builder().apiKey(System.getenv("OPENAI_API_KEY")).build());
}
手动创建Chroma VectorStore Bean
@Bean
public VectorStore chromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi) {
return ChromaVectorStore.builder(chromaApi, embeddingModel)
.tenantName("SpringAiTenant")
.databaseName("SpringAiDatabase")
.collectionName("TestCollection")
.initializeSchema(true)
.build();
}
文档添加与检索
@Autowired
VectorStore vectorStore;
List<Document> documents = List.of(
new Document("Spring AI rocks!!", Map.of("author", "john")),
new Document("The World is Big and Salvation Lurks Around the Corner", Map.of("author", "jill")),
new Document("You walk forward facing the past.", Map.of("author", "john"))
);
// 添加文档
vectorStore.add(documents);
// 相似性检索
List<Document> results = vectorStore.similaritySearch(
SearchRequest.builder().query("Spring").topK(5).build()
);
元数据过滤检索
List<Document> filteredResults = vectorStore.similaritySearch(
SearchRequest.builder()
.query("World")
.topK(5)
.filterExpression("author in ['john', 'jill'] && article_type == 'blog'")
.build()
);
六、Mermaid结构图解
1. Flowchart:整体流程梳理
#mermaid-svg-jkGIDErpKC0ab9rS {font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-jkGIDErpKC0ab9rS .error-icon{fill:#552222;}#mermaid-svg-jkGIDErpKC0ab9rS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jkGIDErpKC0ab9rS .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-jkGIDErpKC0ab9rS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jkGIDErpKC0ab9rS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jkGIDErpKC0ab9rS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jkGIDErpKC0ab9rS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jkGIDErpKC0ab9rS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jkGIDErpKC0ab9rS .marker.cross{stroke:#333333;}#mermaid-svg-jkGIDErpKC0ab9rS svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jkGIDErpKC0ab9rS .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-jkGIDErpKC0ab9rS .cluster-label text{fill:#333;}#mermaid-svg-jkGIDErpKC0ab9rS .cluster-label span{color:#333;}#mermaid-svg-jkGIDErpKC0ab9rS .label text,#mermaid-svg-jkGIDErpKC0ab9rS span{fill:#333;color:#333;}#mermaid-svg-jkGIDErpKC0ab9rS .node rect,#mermaid-svg-jkGIDErpKC0ab9rS .node circle,#mermaid-svg-jkGIDErpKC0ab9rS .node ellipse,#mermaid-svg-jkGIDErpKC0ab9rS .node polygon,#mermaid-svg-jkGIDErpKC0ab9rS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jkGIDErpKC0ab9rS .node .label{text-align:center;}#mermaid-svg-jkGIDErpKC0ab9rS .node.clickable{cursor:pointer;}#mermaid-svg-jkGIDErpKC0ab9rS .arrowheadPath{fill:#333333;}#mermaid-svg-jkGIDErpKC0ab9rS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jkGIDErpKC0ab9rS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jkGIDErpKC0ab9rS .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-jkGIDErpKC0ab9rS .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-jkGIDErpKC0ab9rS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jkGIDErpKC0ab9rS .cluster text{fill:#333;}#mermaid-svg-jkGIDErpKC0ab9rS .cluster span{color:#333;}#mermaid-svg-jkGIDErpKC0ab9rS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jkGIDErpKC0ab9rS :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Chroma
向量存储
相似性检索
用户请求
文本转嵌入
结果返回
说明:用户输入文本,经嵌入模型转为向量,存储于Chroma中,之后可进行相似性检索。
2. StateDiagram-v2:Chroma向量库状态转变
#mermaid-svg-2ziHa1fgVSUgmPLp {font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-2ziHa1fgVSUgmPLp .error-icon{fill:#552222;}#mermaid-svg-2ziHa1fgVSUgmPLp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2ziHa1fgVSUgmPLp .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-2ziHa1fgVSUgmPLp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2ziHa1fgVSUgmPLp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2ziHa1fgVSUgmPLp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2ziHa1fgVSUgmPLp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2ziHa1fgVSUgmPLp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2ziHa1fgVSUgmPLp .marker.cross{stroke:#333333;}#mermaid-svg-2ziHa1fgVSUgmPLp svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2ziHa1fgVSUgmPLp defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-2ziHa1fgVSUgmPLp g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-2ziHa1fgVSUgmPLp g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-2ziHa1fgVSUgmPLp g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-2ziHa1fgVSUgmPLp g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-2ziHa1fgVSUgmPLp g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-2ziHa1fgVSUgmPLp .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-2ziHa1fgVSUgmPLp .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-2ziHa1fgVSUgmPLp .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-2ziHa1fgVSUgmPLp .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-2ziHa1fgVSUgmPLp .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-2ziHa1fgVSUgmPLp .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-2ziHa1fgVSUgmPLp .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-2ziHa1fgVSUgmPLp .edgeLabel .label text{fill:#333;}#mermaid-svg-2ziHa1fgVSUgmPLp .label div .edgeLabel{color:#333;}#mermaid-svg-2ziHa1fgVSUgmPLp .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-2ziHa1fgVSUgmPLp .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-2ziHa1fgVSUgmPLp .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-2ziHa1fgVSUgmPLp .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-2ziHa1fgVSUgmPLp .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-2ziHa1fgVSUgmPLp .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2ziHa1fgVSUgmPLp .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2ziHa1fgVSUgmPLp #statediagram-barbEnd{fill:#333333;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2ziHa1fgVSUgmPLp .cluster-label,#mermaid-svg-2ziHa1fgVSUgmPLp .nodeLabel{color:#131300;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-2ziHa1fgVSUgmPLp .note-edge{stroke-dasharray:5;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-note text{fill:black;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram-note .nodeLabel{color:black;}#mermaid-svg-2ziHa1fgVSUgmPLp .statediagram .edgeLabel{color:red;}#mermaid-svg-2ziHa1fgVSUgmPLp #dependencyStart,#mermaid-svg-2ziHa1fgVSUgmPLp #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-2ziHa1fgVSUgmPLp :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
初始化
已连接
已创建集合
已添加文档
检索中
返回结果
说明:系统从初始化到连接、集合创建、文档添加、检索、返回结果的状态流转。
3. SequenceDiagram:Spring AI与Chroma交互时序
#mermaid-svg-y3vGeBvI8EgSiiH5 {font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-y3vGeBvI8EgSiiH5 .error-icon{fill:#552222;}#mermaid-svg-y3vGeBvI8EgSiiH5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-y3vGeBvI8EgSiiH5 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-y3vGeBvI8EgSiiH5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-y3vGeBvI8EgSiiH5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-y3vGeBvI8EgSiiH5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-y3vGeBvI8EgSiiH5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-y3vGeBvI8EgSiiH5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-y3vGeBvI8EgSiiH5 .marker.cross{stroke:#333333;}#mermaid-svg-y3vGeBvI8EgSiiH5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-y3vGeBvI8EgSiiH5 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-y3vGeBvI8EgSiiH5 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-y3vGeBvI8EgSiiH5 .actor-line{stroke:grey;}#mermaid-svg-y3vGeBvI8EgSiiH5 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-y3vGeBvI8EgSiiH5 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-y3vGeBvI8EgSiiH5 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-y3vGeBvI8EgSiiH5 .sequenceNumber{fill:white;}#mermaid-svg-y3vGeBvI8EgSiiH5 #sequencenumber{fill:#333;}#mermaid-svg-y3vGeBvI8EgSiiH5 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-y3vGeBvI8EgSiiH5 .messageText{fill:#333;stroke:#333;}#mermaid-svg-y3vGeBvI8EgSiiH5 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-y3vGeBvI8EgSiiH5 .labelText,#mermaid-svg-y3vGeBvI8EgSiiH5 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-y3vGeBvI8EgSiiH5 .loopText,#mermaid-svg-y3vGeBvI8EgSiiH5 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-y3vGeBvI8EgSiiH5 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-y3vGeBvI8EgSiiH5 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-y3vGeBvI8EgSiiH5 .noteText,#mermaid-svg-y3vGeBvI8EgSiiH5 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-y3vGeBvI8EgSiiH5 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-y3vGeBvI8EgSiiH5 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-y3vGeBvI8EgSiiH5 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-y3vGeBvI8EgSiiH5 .actorPopupMenu{position:absolute;}#mermaid-svg-y3vGeBvI8EgSiiH5 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-y3vGeBvI8EgSiiH5 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-y3vGeBvI8EgSiiH5 .actor-man circle,#mermaid-svg-y3vGeBvI8EgSiiH5 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-y3vGeBvI8EgSiiH5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
User
SpringAI
EmbeddingModel
ChromaDB
提交检索请求
文本转向量
返回向量
相似性检索(含元数据过滤)
检索结果
返回文档列表
User
SpringAI
EmbeddingModel
ChromaDB
说明:用户请求经Spring AI处理,嵌入模型转向量后,Spring AI调用Chroma进行检索并返回结果。
七、参考与权威资料
- Chroma 官方文档
- Spring AI 官方文档
- 向量数据库发展综述
- Spring AI GitHub
- Chroma GitHub
八、总结与认知速记
- 向量数据库是AI语义检索的关键基础设施。
- Chroma开源、易用,支持本地与云端部署。
- Spring AI自动化集成,极大提高开发效率。
- 元数据过滤让检索结果更可控、更精准。
- 初始化Schema需显式配置,兼容不同环境。
- Mermaid三种图表分别适合流程、状态、时序结构说明。
建议开发者结合实际业务场景,灵活选型嵌入模型与向量数据库,善用Spring AI生态,快速构建智能检索与问答系统。
如需完整代码示例或深入定制方案,欢迎留言交流!




