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 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 documents = reader.get();
List documentSplitterList = tokenTextSplitter.apply(documents);

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);
            }
        }
posted @ 2025-12-03 01:02  8023渡劫  阅读(31)  评论(0)    收藏  举报