RAG 项目随笔
ollama pull nomic-embed-text 基于 Ollama 部署 DeepSeek 大模型,提供 API 接口。 运用 Spring AI 框架承接接口实现 RAG 知识库能力。 这款 RAG 知识库支持文本解析,以及 Git 代码库的解析。
技术选型
JDK 17 ~ 21
Postgresql
SpringBoot 3.2.3
Spring AI 0.8.1 ~ 1.0.0
Redis
Docker
Ollama + DeepSeek
拉取 Ollama 模型使用 deepSeek-1.5b
拉取模型,推荐小一点,够做开发就可以
ollama pull deepseek-r1:1.5b
(可选)运行模型,运行后关闭,继续安装模型。 Ctrl/Command + D
ollama run deepseek-r1:1.5b
向量文本
ollama pull nomic-embed-text
curl http://127.0.0.1:11434/api/generate \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-r1:1.5b",
"prompt": "1+1",
"stream": false
}'
docker-compose
`
docker-comopse -f docker-compose-environment-aliyun.yml up -d
version: '3'
services:
对话模型
ollama pull deepseek-r1:1.5b
运行模型
ollama run deepseek-r1:1.5b
联网模型
ollama pull nomic-embed-text
ollama:
image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/ollama:0.5.10
container_name: ollama
restart: unless-stopped
ports:
- "11434:11434"
redis:
image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis:6.2
container_name: redis
restart: always
hostname: redis
privileged: true
ports:
- 16379:6379
volumes:
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: redis-server /usr/local/etc/redis/redis.conf
networks:
- my-network
healthcheck:
test: [ "CMD", "redis-cli", "ping" ]
interval: 10s
timeout: 5s
retries: 3
RedisAdmin https://github.com/joeferner/redis-commander
账密 admin/admin
redis-admin:
image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis-commander:0.8.0
container_name: redis-admin
hostname: redis-commander
restart: always
ports:
- 8081:8081
environment:
- REDIS_HOSTS=local:redis:6379
- HTTP_USER=admin
- HTTP_PASSWORD=admin
- LANG=C.UTF-8
- LANGUAGE=C.UTF-8
- LC_ALL=C.UTF-8
networks:
- my-network
depends_on:
redis:
condition: service_healthy
vector_db:
image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/pgvector:v0.5.0
container_name: vector_db
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=ai-rag-knowledge
- PGPASSWORD=postgres
volumes:
- ./pgvector/sql/init.sql:/docker-entrypoint-initdb.d/init.sql
logging:
options:
max-size: 10m
max-file: "3"
ports:
- '15432:5432'
healthcheck:
test: "pg_isready -U postgres -d ai-rag-knowledge"
interval: 2s
timeout: 20s
retries: 10
networks:
- my-network
networks:
my-network:
driver: bridge
`
对应 controller 接口
`
@RestController()
@CrossOrigin("*")
@RequestMapping("/api/v1/ollama/")
public class OllamaController implements IAiService {
@Resource
private OllamaChatClient chatClient;
/**
* http://localhost:8090/api/v1/ollama/generate?model=deepseek-r1:1.5b&message=1+1
*/
@RequestMapping(value = "generate", method = RequestMethod.GET)
@Override
public ChatResponse generate(@RequestParam String model, @RequestParam String message) {
return chatClient.call(new Prompt(message, OllamaOptions.create().withModel(model)));
}
/**
* http://localhost:8090/api/v1/ollama/generate_stream?model=deepseek-r1:1.5b&message=hi
*/
@RequestMapping(value = "generate_stream", method = RequestMethod.GET)
@Override
public Flux<ChatResponse> generateStream(@RequestParam String model, @RequestParam String message) {
return chatClient.stream(new Prompt(message, OllamaOptions.create().withModel(model)));
}
}
`
需要注意流式查询返回前端判断 STOP 结束符
SpringAI : 提供向量模型处理框架,支持文件的解析、拆分和向量化操作。
TikaDocumentReader : 用于解析上传的文件,支持多种文件格式(如 MD、TXT、SQL 等)。
TokenTextSplitter : 用于将解析后的文本内容拆分为更小的片段,便于后续处理和存储。
PostgreSQL 向量库 : 用于存储处理后的文本向量数据,支持高效的相似性搜索和检索。
TikaDocumentReader reader = new TikaDocumentReader(new PathResource(file));
List
List
documents.forEach(doc -> doc.getMetadata().put("knowledge", repoProjectName));
documentSplitterList.forEach(doc -> doc.getMetadata().put("knowledge", repoProjectName));
使用 JGit可以拉取
Git git = Git.cloneRepository()
.setURI(repoUrl)
.setDirectory(new File(localPath))
.setCredentialsProvider(new UsernamePasswordCredentialsProvider(userName, token))
.call();
上传文件解析
@RequestMapping(value = "file/upload", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
@Override
public Response<String> uploadFile(@RequestParam String ragTag, @RequestParam("file") List<MultipartFile> files) {
log.info("上传知识库开始 {}", ragTag);
for (MultipartFile file : files) {
TikaDocumentReader documentReader = new TikaDocumentReader(file.getResource());
List<Document> documents = documentReader.get();
List<Document> documentSplitterList = tokenTextSplitter.apply(documents);
documents.forEach(doc -> doc.getMetadata().put("knowledge", ragTag));
documentSplitterList.forEach(doc -> doc.getMetadata().put("knowledge", ragTag));
pgVectorStore.accept(documentSplitterList);
RList<String> elements = redissonClient.getList("ragTag");
if (!elements.contains(ragTag)) {
elements.add(ragTag);
}
}

浙公网安备 33010602011771号