一、环境准备
Ollama
我这里用的 :ollama+ qwen 大家可以根据自己的环境自行更改
Windows版本
(qwen 模型):https://blog.csdn.net/YXWik/article/details/143871588
Linux版本
(deepseek模型 含安装脚本):https://blog.csdn.net/YXWik/article/details/149497501
Chroma 向量数据库
python版的RAG中装过chroma
:https://blog.csdn.net/YXWik/article/details/147392086
这里直接启动chroma
就行:
cmd
chroma run
默认是 8000 端口 以下命令更改端口启动
cpp
chroma run --host 0.0.0.0 --port 8000

二、java开发
POM文件
Ollama 依赖
cpp
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
Chroma 向量数据库依赖
cpp
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-chroma</artifactId>
</dependency>
Advisor API 依赖
cpp
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>
版本
cpp
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
整合
cpp
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.yxy</groupId>
<artifactId>spring-ai-vectorStore</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-ai-vectorStore</name>
<url>http://maven.apache.org</url>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-chroma</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-tika-document-reader</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>3.2.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
yaml配置文件
yml
spring:
application:
name: spring-ai-vectorStore
ai:
ollama:
base-url: http://localhost:11434
chat:
options:
model: qwen2.5-coder:7b
vectorstore:
chroma:
host: localhost
port: 8000
collection-name: TestCollection
tenant-name: default_tenant # Chroma 默认 tenant
database-name: default_database # Chroma 默认 database
initialize-schema: true # 自动创建 collection
使用向量库
引入向量库实体
cpp
@Autowired
private VectorStore vectorStore;
添加 QuestionAnswerAdvisor
实例以启用 RAG 功能
QuestionAnswerAdvisor
基于向量相似度的文档检索和答案生成
cpp
.advisors(new QuestionAnswerAdvisor(vectorStore))
向量库插入文本数据(追加版)
cpp
@GetMapping("/ai/vector/add")
public String addVector(@RequestParam(value = "text") String text) {
/**
* Document 文档类型
* text 文档内容
* metadata 元数据,用于增强检索能力,标注文档额外数据,例如来源,时间等
* Map.of("source", "manual") 标识这些文档的来源是手动添加的
*/
List<Document> documents = List.of(
new Document(text, Map.of("source", "manual")));
vectorStore.add(documents);
return "success";
}

测试写入

对话
cpp
@GetMapping("/ai/ollama")
public String ollama(@RequestParam(value = "msg") String msg) {
ChatClient chatClient = ChatClient.builder(ollamaChatModel)
.build();
String content = chatClient.prompt(msg).advisors(new QuestionAnswerAdvisor(vectorStore)).call().content();
System.out.println(content);
return content;
}

向量库插入文档数据(追加版)
测试.docx
java
YXWik是一个java开发者,喜欢探索AI。
技能有java,mysql
平时最喜欢的游戏是穿越火线

依赖
java
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-tika-document-reader</artifactId>
</dependency>

接口
java
@GetMapping("/ai/vector/addDocument")
public String addDocument() {
String path = "G:\\桌面\\测试.docx";
String label = "document";
// 读取文件
FileSystemResource resource = new FileSystemResource(path);
TikaDocumentReader tikaReader = new TikaDocumentReader(resource);
List<Document> docbatch = tikaReader.read();
// 文件发送给适量存储 将文档切分为512字符大小的块
docbatch = TokenTextSplitter.builder().withChunkSize(512).withMaxNumChunks(100).build().apply(docbatch);
System.out.println("添加的文档大小:" + docbatch.size());
// 最后为每块文档添加标签并存入向量数据库
docbatch.forEach(doc -> {
System.out.println("添加的文档内容:"+doc.getText());
doc.getMetadata().put("label",label);
vectorStore.add(List.of(doc));
});
return "success";
}


对话
我将文本内容进行了变更
重新将文件内容写入chroma

再次对话
虽然还是一个文件但是,内容是追加而不是替换的
要实现 "修改文件后重新上传会覆盖旧内容",需要手动添加 "删除旧数据 + 新增新数据" 的逻辑
向量库插入文档数据(替换版)
测试文件
接口
java
@GetMapping("/ai/vector/addDocumentOverRide")
public String addDocumentOverRide() {
String path = "G:\\桌面\\测试替换.docx";
String label = "document";
// 1. 生成该文件旧文档块的所有可能ID(格式:文件路径+序号)
List<String> oldDocumentIds = new ArrayList<>();
// 假设最大块数为100(与拆分时的maxNumChunks一致)
for (int i = 0; i < 100; i++) {
oldDocumentIds.add(path + "_" + i);
}
// 2. 批量删除该文件的旧文档块(按ID删除)
vectorStore.delete(oldDocumentIds); // 按ID列表删除
// 3. 读取新文件并拆分
FileSystemResource resource = new FileSystemResource(path);
TikaDocumentReader tikaReader = new TikaDocumentReader(resource);
List<Document> docbatch = tikaReader.read();
docbatch = TokenTextSplitter.builder()
.withChunkSize(512)
.withMaxNumChunks(100)
.build()
.apply(docbatch);
// 4. 为新文档块设置唯一ID(文件路径+块索引)
List<Document> newDocuments = new ArrayList<>();
for (int i = 0; i < docbatch.size(); i++) {
Document originalDoc = docbatch.get(i);
// 构建新文档,指定唯一ID
Document newDoc = new Document(
path + "_" + i, // 自定义ID:文件路径+块索引
originalDoc.getText(),
originalDoc.getMetadata()
);
newDoc.getMetadata().put("label", label);
newDoc.getMetadata().put("filePath", path);
newDocuments.add(newDoc);
}
// 5. 添加新文档
vectorStore.add(newDocuments);
return "success";
}
调用
对话

更改文件
调用
对话
查询向量库所有内容
cpp
@GetMapping("/ai/vector/list")
public List<String> listAllDocs() {
List<Document> allDocs = vectorStore.similaritySearch(""); // 用空文本查所有文档
System.out.println("所有文档数量:" + allDocs.size());
System.out.println("所有文档内容:");
allDocs.forEach(System.out::println);
return allDocs.stream().map(Document::getText).collect(Collectors.toList());
}
踩坑记录
如果项目启动报错如下:
cpp
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-09-04T13:49:08.939+08:00 ERROR 30180 --- [spring-ai-vectorStore] [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ollamaController': Unsatisfied dependency expressed through field 'vectorStore': Error creating bean with name 'vectorStore' defined in class path resource [org/springframework/ai/vectorstore/chroma/autoconfigure/ChromaVectorStoreAutoConfiguration.class]: I/O error on GET request for "http://localhost:8000/api/v2/tenants/SpringAiTenant/databases/SpringAiDatabase/collections/TestCollection": Connection refused: connect
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:787) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:767) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:508) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1419) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) ~[spring-context-6.1.6.jar:6.1.6]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.6.jar:6.1.6]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.5.jar:3.2.5]
at org.yxy.OllamaApplication.main(OllamaApplication.java:14) ~[classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'vectorStore' defined in class path resource [org/springframework/ai/vectorstore/chroma/autoconfigure/ChromaVectorStoreAutoConfiguration.class]: I/O error on GET request for "http://localhost:8000/api/v2/tenants/SpringAiTenant/databases/SpringAiDatabase/collections/TestCollection": Connection refused: connect
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:784) ~[spring-beans-6.1.6.jar:6.1.6]
... 20 common frames omitted
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:8000/api/v2/tenants/SpringAiTenant/databases/SpringAiDatabase/collections/TestCollection": Connection refused: connect
at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.createResourceAccessException(DefaultRestClient.java:557) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:482) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.retrieve(DefaultRestClient.java:444) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.ai.chroma.vectorstore.ChromaApi.getCollection(ChromaApi.java:226) ~[spring-ai-chroma-store-1.0.0.jar:1.0.0]
at org.springframework.ai.chroma.vectorstore.ChromaVectorStore.afterPropertiesSet(ChromaVectorStore.java:121) ~[spring-ai-chroma-store-1.0.0.jar:1.0.0]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1833) ~[spring-beans-6.1.6.jar:6.1.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-6.1.6.jar:6.1.6]
... 30 common frames omitted
Caused by: java.net.ConnectException: Connection refused: connect
at java.base/sun.nio.ch.Net.connect0(Native Method) ~[na:na]
at java.base/sun.nio.ch.Net.connect(Net.java:579) ~[na:na]
at java.base/sun.nio.ch.Net.connect(Net.java:568) ~[na:na]
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:588) ~[na:na]
at java.base/java.net.Socket.connect(Socket.java:633) ~[na:na]
at java.base/java.net.Socket.connect(Socket.java:583) ~[na:na]
at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:183) ~[na:na]
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:498) ~[na:na]
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:603) ~[na:na]
at java.base/sun.net.www.http.HttpClient.<init>(HttpClient.java:246) ~[na:na]
at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:351) ~[na:na]
at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:373) ~[na:na]
at java.base/sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1309) ~[na:na]
at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1242) ~[na:na]
at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1128) ~[na:na]
at java.base/sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:1057) ~[na:na]
at org.springframework.http.client.SimpleClientHttpRequest.executeInternal(SimpleClientHttpRequest.java:79) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.http.client.AbstractStreamingClientHttpRequest.executeInternal(AbstractStreamingClientHttpRequest.java:70) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:476) ~[spring-web-6.1.6.jar:6.1.6]
... 35 common frames omitted

说明chroma
是 通过 chroma run
启动的 停止后采用chroma run --host 0.0.0.0 --port 8000
启动即可解决
