Spring AI 学习指南(十一)RAG私有知识库实战
一、前言:为什么 RAG 是企业AI落地的刚需?
前面我们完成了基础对话、多轮记忆、MCP工具调用、Agent智能体,让AI具备了聊天、思考、做事的能力。
但所有通用大模型,都存在三个无法规避的硬伤:
-
知识静态滞后:训练数据固定,无法学习企业最新制度、业务文档、产品手册
-
无私有业务认知:完全不懂公司内部业务规则、专属流程、私有资料
-
严重幻觉问题:面对未知业务问题,会凭空编造答案,绝对无法上线生产
想要让AI 适配企业业务、基于内部文档精准答疑、杜绝幻觉,唯一低成本、高效率、可迭代的落地方案就是 RAG(检索增强生成)。
本篇采用 Spring AI 原生高阶写法:使用 QuestionAnswerAdvisor 自动实现检索增强,告别手动拼接上下文,架构更标准、代码更简洁、完全贴合生产规范。
二、RAG核心原理(极简通俗版)
2.1 核心思想:先检索,后生成
传统大模型问答:用户提问 → 模型凭历史训练数据回答 → 易滞后、易幻觉。
RAG 增强问答:用户提问 → 向量库语义检索私有文档 → 模型仅基于检索到的真实资料生成答案 → 数据真实、无幻觉、可随时更新知识库。
2.2 标准RAG两大阶段
阶段一:知识库离线构建(初始化执行一次)
文档加载 → 文本切片 → 向量化 → 存入向量库
阶段二:在线智能问答(用户每次提问)
问题向量化 → 语义相似度检索 → 自动拼接上下文Prompt → 模型精准生成答案
2.3 RAG vs 模型微调(企业选型结论)
-
微调:改模型权重、成本极高、训练周期长、文档更新需要重新训练、容易灾难性遗忘
-
RAG:不改模型、只改数据、零训练成本、支持动态增量更新、随时更新业务文档
企业业务文档频繁变更,RAG 是绝对最优解。
三、项目核心依赖
本篇所需完整依赖,适配文档解析、向量存储、AI问答全套能力,完整的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 http://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.5.14</version>
<relativePath/>
</parent>
<groupId>demo.ai</groupId>
<artifactId>spring-ai-demo</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.ai.version>1.1.6</spring.ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring.ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-client-chat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pdf-document-reader</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>
</dependencies>
</project>
四、企业级RAG核心配置类
4.1 统一向量库+切片+记忆全局配置
package demo.ai.conf;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.document.DocumentTransformer;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@RequiredArgsConstructor
public class VectorStoreConfig {
/**
* 初始化向量库
* SimpleVectorStore:内存向量库,开箱即用,适合开发、测试、小型项目
* 生产建议替换:Milvus / PgVector / RedisVector
*/
@Bean
public VectorStore vectorStore(EmbeddingModel embeddingModel) {
return SimpleVectorStore.builder(embeddingModel).build();
}
/**
* 全局文本切片器
* 单片段800字符,兼顾语义完整性与检索精度
*/
@Bean
public DocumentTransformer textSplitter() {
return TokenTextSplitter.builder().withChunkSize(800).build();
}
/**
* 窗口式会话记忆
* 保留最近10条对话,防止上下文溢出,支撑多轮RAG追问
*/
@Bean
public MessageWindowChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.maxMessages(10)
.build();
}
/**
* 构建带记忆的ChatClient
* 为RAG多轮问答、上下文联动提供基础能力
*/
@Bean
public ChatClient chatClient(ChatClient.Builder builder, MessageWindowChatMemory chatMemory) {
return builder
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.build();
}
}
4.2 核心配置说明
-
VectorStore:依托框架自动注入的EmbeddingModel实现文本向量化,统一向量入口
-
TokenTextSplitter:全局统一切片规则800字符,相比默认配置,检索精度更高、语义更完整
-
MessageWindowChatMemory:限制最大对话数,解决多轮RAG上下文过长、Token溢出问题
-
ChatClient:全局注入记忆顾问,天然支持RAG多轮关联追问
五、知识库加载工具类(PDF文档解析入库)
新版知识库加载工具类做了全面升级,摒弃了简陋的异常捕获,采用标准ETL流水线设计,新增日志可视化、文本增量入库能力、自定义文档路径配置。同时拆分PDF加载、纯文本加载双方法,既支持静态PDF知识库初始化,也支持动态文本实时入库,适配更多业务场景,结构更贴合生产级ETL规范。
package demo.ai.rag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentReader;
import org.springframework.ai.document.DocumentTransformer;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
@RequiredArgsConstructor
@Slf4j
public class KnowledgeBaseLoader {
private final VectorStore vectorStore;
private final DocumentTransformer textSplitter;
@Value("classpath:doc/公司考勤制度.pdf")
private org.springframework.core.io.Resource pdfResource;
/**
* 加载 PDF 文档到向量数据库
* 标准ETL流水线:抽取(Extract) - 转换(Transform) - 加载(Load)
*/
public void loadPdfToVectorStore() {
// 1. 抽取(Extract):使用 PdfDocumentReader 读取 PDF
DocumentReader pdfReader = new PagePdfDocumentReader(pdfResource);
List<Document> documents = pdfReader.get();
log.info("抽取完成,共 {} 个页面", documents.size());
// 2. 转换(Transform):对文档进行文本分割,生成便于检索的知识碎片
List<Document> chunks = textSplitter.apply(documents);
log.info("切分完成,共 {} 个知识片段", chunks.size());
// 3. 加载(Load):将向量存储到 VectorStore
// ETL 流水线链式调用风格
vectorStore.write(chunks);
log.info("向量存储完成");
}
/**
* 加载纯文本内容到向量数据库
* 支持动态传入文本与元数据,适配实时增量入库场景
*/
public void loadTextToVectorStore(String textContent, Map<String, Object> metadata) {
Document doc = new Document(textContent, metadata);
List<Document> chunks = textSplitter.apply(List.of(doc));
vectorStore.write(chunks);
log.info("文本内容已加载,共 {} 个知识片段", chunks.size());
}
}
六、RAG核心控制器
package demo.ai.controller;
import demo.ai.rag.KnowledgeBaseLoader;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/rag")
public class RagController {
@Resource
private ChatClient chatClient;
@Resource
private KnowledgeBaseLoader knowledgeBaseLoader;
@Resource
private VectorStore vectorStore;
/**
* 手动加载/刷新知识库
* 适合文档更新后手动刷新,无需重启项目
* 访问:http://localhost:8080/rag/load
*/
@GetMapping("/load")
public String loadKnowledgeBase() {
knowledgeBaseLoader.loadPdfToVectorStore();
return "✅ 知识库加载成功";
}
/**
* 标准RAG智能问答接口
* 自动语义检索 + 多轮上下文记忆 + 私有文档答疑
* 访问:http://localhost:8080/rag/ask?msg=你的问题
*/
@GetMapping("/ask")
public String ask(@RequestParam String msg) {
return chatClient.prompt()
.user("简单介绍下" + msg)
// 核心:开启官方RAG检索增强顾问
.advisors(QuestionAnswerAdvisor.builder(vectorStore).build())
// 绑定固定会话ID,实现多轮追问上下文关联
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, "default-001"))
.call()
.content();
}
}
七、完整测试流程(可直接复现)
7.1 准备私有知识库文档
下载文章顶部的公司考勤制度.pdf(也可以ai生成一个pdf),存放到项目 resources/doc/公司考勤制度.pdf,放入企业考勤、薪酬、加班补偿等私有业务制度内容,适配本次RAG问答测试场景。
7.2 初始化加载知识库
访问接口:http://localhost:8080/rag/load
控制台打印切片数量,代表向量化入库成功。
7.3 单轮RAG精准问答
示例提问:加班怎么补偿的?
RAG执行逻辑:
-
自动将问题向量化
-
在向量库中语义匹配相关文档片段
-
自动拼接参考文档进Prompt
-
模型仅基于私有文档作答,杜绝幻觉
7.4 强关联多轮追问(核心能力)
依托全局会话记忆,天然支持上下文关联追问:
第一轮:加班怎么补偿的?
第二轮(无任何参数):那工作日和周末补偿有什么区别?
AI自动读取上一轮对话上下文 + 知识库数据,精准迭代回答。
八、生产环境选型 & 最佳实践
✅ 最佳实践
-
开发测试:使用 SimpleVectorStore 内存向量库,零配置、快速开发
-
生产环境:替换为 Milvus、PgVector、RedisVector 持久化向量库
-
切片规范:通用业务文档采用800字符分块,保证语义完整
-
知识库动态更新:提供接口手动刷新,适配业务文档迭代
-
固定会话ID:业务问答统一会话标识,保证多轮连贯
❌ 高频踩坑点
-
文档路径错误导致加载失败,必须统一放在 resources/doc 下
-
切片过大导致语义混杂、过小导致上下文断裂
-
生产使用内存向量库,重启项目知识库丢失
-
未开启会话记忆,多轮追问无法关联上下文
九、本篇学习总结
本篇基于企业级标准源码,从零落地 Spring AI 高阶RAG知识库能力,核心收获:
-
掌握分层RAG架构:向量库、切片器、会话记忆、ChatClient解耦配置
-
熟练使用 QuestionAnswerAdvisor 官方自动化RAG方案,告别手写冗余代码
-
实现PDF私有文档解析、向量化、入库、智能问答全流程
-
掌握可动态刷新的知识库加载方案,适配业务迭代
-
实现RAG+多轮记忆联动,完成强关联上下文智能答疑
-
分清开发/生产向量库选型方案,具备项目上线能力
至此,我们已经集齐 Spring AI 基础对话、多轮记忆、MCP工具调用、Agent智能体、企业级RAG知识库 全套核心能力。
更多推荐



所有评论(0)