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 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渡劫  阅读(6)  评论(0)    收藏  举报