首页  

Spring AI RAG Demo     所属分类 AI 浏览量 9
Spring AI RAG Demo



整体链路:
上传 PDF/TXT 文档 
文档分段 
向量化 
存入 Redis 向量库 
提问自动检索知识库 
LLM 回答

技术栈:
SpringBoot3.3 + SpringAI 2.0 + Ollama (Qwen) + RedisVectorStore + SpringDoc OpenAPI

一、整体依赖 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
        <relativePath/>
    </parent>
    <groupId>com.ai</groupId>
    <artifactId>spring-ai-rag-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringAI RAG Demo</name>

    <properties>
        <java.version>17</java.version>
        <spring.ai.version>2.0.0</spring.ai.version>
    </properties>

    <dependencies>
        <!-- SpringBoot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 文件上传 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring AI Ollama 对话+向量模型 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
            <version>${spring.ai.version}</version>
        </dependency>
        <!-- Redis 向量存储 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-redis-store-spring-boot-starter</artifactId>
            <version>${spring.ai.version}</version>
        </dependency>
        <!-- PDF文档解析 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-pdf-document-reader</artifactId>
            <version>${spring.ai.version}</version>
        </dependency>
        <!-- Markdown/TXT文档读取 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-markdown-document-reader</artifactId>
            <version>${spring.ai.version}</version>
        </dependency>
        <!-- Knife4j接口文档 -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
            <version>4.5.0</version>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


二、配置文件 application.yml


spring:
  application:
    name: spring-ai-rag
  # 文件上传限制
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB
  # Redis向量库配置
  data:
    redis:
      host: 127.0.0.1
      port: 6379
      password:
      database: 0
  ai:
    # Ollama 配置,提前执行 ollama pull qwen:7b
    ollama:
      base-url: http://127.0.0.1:11434
      chat:
        options:
          model: qwen:7b
          temperature: 0.3 # 低随机性,知识库问答更严谨
      embedding:
        options:
          model: qwen:7b
    # Redis向量库参数
    vectorstore:
      redis:
        index-name: rag_doc_index # 向量索引名称
        prefix: rag:doc: # Redis Key前缀
        initialize-schema: true # 自动创建向量索引
        dimensions: 3584 # qwen:7b向量维度,固定
        distance-type: COSINE # 余弦相似度

# 接口文档
knife4j:
  enable: true


三、启动类
package com.ai.rag;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RagApplication {
    public static void main(String[] args) {
        SpringApplication.run(RagApplication.class, args);
    }
}


四、RAG 核心配置类(构建 RAG 链路、检索增强 Advisor)
package com.ai.rag.config;

import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@RequiredArgsConstructor
public class RagConfig {

    private final VectorStore vectorStore;

    /**
     * 构建带RAG知识库增强的ChatClient
     * 1. SimpleLoggerAdvisor:打印请求/响应日志
     * 2. QuestionAnswerAdvisor:RAG核心,自动根据问题检索向量库,把文档塞进Prompt
     */
    @Bean
    public ChatClient ragChatClient(ChatClient.Builder builder) {
        // RAG系统提示词:严格基于知识库回答,无资料直接说不知道,禁止编造
        String ragSystemPrompt = """
                你是企业知识库问答助手,请严格根据上下文参考资料回答用户问题。
                1. 如果参考资料没有对应信息,直接回复「暂无相关知识库资料,无法解答该问题」,禁止编造内容;
                2. 回答条理清晰,重点加粗,精简话术;
                3. 不要输出无关内容,不要凭空拓展。
                """;

        return builder
                .defaultSystem(ragSystemPrompt)
                // 日志拦截器
                .defaultAdvisors(new SimpleLoggerAdvisor())
                // RAG检索增强拦截器
                .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))
                .build();
    }
}


五、文档上传 & 向量入库 Service


package com.ai.rag.service;

import lombok.RequiredArgsConstructor;
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentReader;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@Service
@RequiredArgsConstructor
public class DocumentVectorService {

    private final VectorStore vectorStore;
    // 文本分片器:按token切割长文档,适配模型上下文窗口
    private final TokenTextSplitter textSplitter = new TokenTextSplitter(800, 150, 5, 10000);

    /**
     * 上传文档写入向量库
     */
    public void uploadAndVector(MultipartFile file) throws Exception {
        DocumentReader reader;
        String fileName = file.getOriginalFilename();
        if (fileName.endsWith(".pdf")) {
            // PDF解析
            reader = new PagePdfDocumentReader(file.getResource());
        } else {
            // TXT/MD/Word通用解析
            reader = new TikaDocumentReader(file.getResource());
        }
        // 读取原始文档
        List<Document> originDocs = reader.get();
        // 文档分段
        List<Document> splitDocs = textSplitter.apply(originDocs);
        // 批量写入向量库(自动向量化)
        vectorStore.add(splitDocs);
    }

    /**
     * 清空向量知识库
     */
    public void clearVectorStore() {
        vectorStore.deleteAll();
    }
}


六、接口 Controller(文件上传、问答、流式问答)


package com.ai.rag.controller;

import com.ai.rag.service.DocumentVectorService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/ai/rag")
@RequiredArgsConstructor
public class RagController {

    private final ChatClient ragChatClient;
    private final DocumentVectorService documentVectorService;

    @PostMapping("/upload")
    @Operation(summary = "上传知识库文档(PDF/TXT/MD/Word)")
    public String uploadDoc(@RequestParam("file") MultipartFile file) throws Exception {
        documentVectorService.uploadAndVector(file);
        return "文档上传并向量化入库成功:" + file.getOriginalFilename();
    }

    @DeleteMapping("/clear")
    @Operation(summary = "清空全部知识库向量数据")
    public String clearDoc() {
        documentVectorService.clearVectorStore();
        return "知识库已清空";
    }

    @GetMapping("/chat")
    @Operation(summary = "RAG知识库同步问答")
    public String chat(
            @Parameter(description = "提问内容") @RequestParam String question
    ) {
        return ragChatClient.prompt()
                .user(question)
                .call()
                .content();
    }

    @GetMapping(value = "/stream/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @Operation(summary = "RAG流式问答(SSE打字机)")
    public Flux<String> streamChat(@RequestParam String question) {
        return ragChatClient.prompt()
                .user(question)
                .stream()
                .content();
    }
}


七、前置环境准备
启动 Redis:本地 Redis 6.0+,无密码直接启动
启动 Ollama

# 拉取通义千问7b模型
ollama pull qwen:7b
# 启动Ollama(默认11434端口)
ollama serve
准备测试文档:新建知识库.txt写入测试文本,例如:


Spring AI是Spring官方推出的Java大模型应用开发框架,支持RAG知识库、FunctionCall工具调用、多模型适配。
RAG全称检索增强生成,用来解决大模型幻觉、私有数据问答问题。



八、测试步骤
启动 SpringBoot 项目,访问接口文档:http://127.0.0.1:8080/doc.html
调用/ai/rag/upload上传知识库.txt
调用问答接口提问:Spring AI是什么,模型会读取文档回答
提问无关内容(例如:今天天气),模型返回:暂无相关知识库资料,无法解答该问题


九、扩展优化点
元数据过滤:上传文档时绑定业务分类,检索时按分类过滤向量;
对话记忆:添加MessageChatMemoryAdvisor实现多轮对话;
文档去重:新增 MD5 文档指纹,避免重复入库;
向量库切换:替换为 Milvus/PGVector 适配生产环境;
文档异步向量化:MQ 异步处理大文件分片入库,防止接口超时;
重排序 Rerank:增加 Rerank 模型对召回文档二次排序,提升问答精度。




上一篇    
BeanUtils.copyProperties 使用说明

道德经与易经

Spring AI 应用框架