你以为“把文档喂给模型”就叫 RAG?那它为啥还会一本正经地胡说八道?
🏆本文收录于《滚雪球学SpringBoot 3》:
https://blog.csdn.net/weixin_43970743/category_12795608.html,专门攻坚指数提升,本年度国内最系统+最专业+最详细(永久更新)。
本专栏致力打造最硬核 SpringBoot3 从零基础到进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中…欢迎大家订阅持续学习。 如果想快速定位学习,可以看这篇【SpringBoot3教程导航帖】https://blog.csdn.net/weixin_43970743/article/details/151115907,你想学习的都被收集在内,快速投入学习!!两不误。
若还想学习更多,可直接前往《滚雪球学SpringBoot(全版本合集)》:https://blog.csdn.net/weixin_43970743/category_11599389.html,涵盖SpringBoot所有版本教学文章。
演示环境说明:
- 开发工具:IDEA 2021.3
- JDK版本: JDK 17(推荐使用 JDK 17 或更高版本,因为 Spring Boot 3.x 系列要求 Java 17,Spring Boot 3.5.4 基于 Spring Framework 6.x 和 Jakarta EE 9,它们都要求至少 JDK 17。)
- Spring Boot版本:3.5.4(于25年7月24日发布)
- Maven版本:3.8.2 (或更高)
- Gradle:(如果使用 Gradle 构建工具的话):推荐使用 Gradle 7.5 或更高版本,确保与 JDK 17 兼容。
- 操作系统:Windows 11
1) RAG(Retrieval-Augmented Generation)核心原理解析
一句话讲透 RAG:先找“相关材料”,再让模型“基于材料回答”。
它解决的不是“模型会不会说”,而是“模型说的有没有根据”。
一个可落地的 RAG 流程通常长这样:
- Query 理解(可选):对用户问题做改写、扩展关键词
- 检索(Retrieval):把问题向量化(Embedding),去向量库做相似度搜索
- 构造上下文(Context Building):取 Top-K 文档片段 + 元数据(来源、时间、权限、标题)
- 生成(Generation):把“问题 + 检索结果片段”塞进 Prompt,让 LLM 输出
- 可追溯(Grounding):回答里带引用/出处(企业场景非常重要)
RAG 的“灵魂”其实就两句话:
- 材料找得准不准(检索质量)
- 模型是不是被迫“只依据材料说话”(提示词与约束)
2) Vector Database:Redis / Chroma / Pinecone 怎么选?
选向量库别一上来就“哪个最火用哪个”,先问自己两个问题:
数据在不在内网?吞吐和成本谁更敏感?(这句话很土,但很救命😅)
2.1 Redis Vector Store(偏“企业内网 + 低延迟 + 运维熟”)
Spring AI 的 RedisVectorStore 基于 Redis Stack(RedisJSON + RediSearch)来存储向量与元数据,并通过 RediSearch 做向量相似度检索。
适合:
- 你公司已经有 Redis/Redis Stack 运维体系
- 想把向量库当“基础设施”放内网
- 需要低延迟、可控性强
注意:
- 需要 Redis Stack 相关能力(RediSearch / RedisJSON)
2.2 Chroma(偏“本地/中小规模/研发快速验证”)
Spring AI 提供 Chroma Vector Store 的 Spring Boot 自动配置(starter 一把梭)。
Chroma 本身定位就是开源嵌入数据库:存向量、存元数据、支持过滤。
适合:
- PoC / 内部工具 / 小团队快速跑通
- 本地或单机部署优先
- 不想引入重型基础设施
2.3 Pinecone(偏“云托管/扩展性/省运维”)
Spring AI 也提供 Pinecone Vector Store 的集成与自动配置。
Pinecone 是云端向量数据库,省心但意味着数据出网(看合规要求)。
适合:
- 云优先、规模增长快、想少折腾运维
- 允许数据走云(或做脱敏/分级)
3) ETL Pipeline:用 Spring AI Reader 解析文档并 Embedding
企业知识库 RAG 的成败,80% 在 ETL。真的。
你检索不准,模型再聪明也只能“胡说得更像真的”。
Spring AI 官方把 ETL pipeline 明确拆成三段:
DocumentReader(读取文档,产出List<Document>)DocumentTransformer(转换/切分/清洗)DocumentWriter(写入存储,通常是 VectorStore)
3.1 一个“可跑”的最小 ETL:读取 → 切分 → 向量化写入
下面示例用“伪代码风格但贴近 Spring AI 真实组件命名”,你可以直接按你选的 VectorStore 替换依赖与配置。
pom.xml(示例:Chroma)
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-chroma</artifactId>
</dependency>
Spring AI 文档明确 Chroma 的 starter 依赖这样引入。
ETL 服务:
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.DocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public class KnowledgeIngestService {
private final VectorStore vectorStore;
public KnowledgeIngestService(VectorStore vectorStore) {
this.vectorStore = vectorStore;
}
public void ingest(DocumentReader reader, String sourceName) {
// 1) 读取文档 -> Document 列表(Spring AI ETL 概念):contentReference[oaicite:8]{index=8}
List<Document> docs = reader.get();
// 2) 切分:强烈建议切块(chunk),否则检索会很飘
var splitter = new TokenTextSplitter(); // 你可以配置 chunkSize/overlap
List<Document> chunks = splitter.apply(docs);
// 3) 写入向量库:VectorStore 会调用 EmbeddingModel 生成向量(配置在 Spring AI 里)
// 额外:补齐元数据,后续用于引用与权限过滤
chunks.forEach(d -> d.getMetadata().putAll(Map.of(
"source", sourceName
// 还可以加:docId、title、updatedAt、dept、aclLevel...
)));
vectorStore.add(chunks);
}
}
重点:ETL 三段式不是“学院派概念”,它就是为了让你能把“读取/切分/存储”拆开、可替换、可复用。
3.2 切分策略(chunking)别靠感觉:给你一个工程化标准
经验规则(不绝对,但好用):
- Chunk 太大:检索命中但上下文冗余,LLM 容易跑偏
- Chunk 太小:命中碎片化,信息不足,答非所问
- 一般从 300–800 tokens(或相近字符量)起步,配 10–20% overlap,再用离线评测调参
4) 实战:基于企业私有知识库的问答系统(Spring Boot 3)
这里给你一套“企业内网问答”的标准落地架构:
4.1 架构图(文字版)
- Ingestion 服务:文档源(Wiki/网盘/数据库/工单)→ Reader → Splitter → VectorStore
- Query 服务:用户问题 → Embedding → VectorStore similarity search → 拼 prompt → LLM 生成
- 治理组件:权限过滤、来源引用、日志与评测、缓存、失败降级
4.2 Query 侧代码:检索 + 组装上下文 + 生成回答(带引用)
假设你已经有 VectorStore,并且 EmbeddingModel / ChatModel 都在 Spring AI 里配好了。
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/rag")
public class RagQaController {
private final VectorStore vectorStore;
private final org.springframework.ai.chat.client.ChatClient chatClient;
public RagQaController(VectorStore vectorStore,
org.springframework.ai.chat.client.ChatClient chatClient) {
this.vectorStore = vectorStore;
this.chatClient = chatClient;
}
@GetMapping("/ask")
public RagAnswer ask(@RequestParam String q) {
// 1) 向量检索:topK + 可选过滤(部门/文档类型/权限级别等)
List<Document> hits = vectorStore.similaritySearch(
SearchRequest.query(q).withTopK(5)
// .withFilterExpression("aclLevel <= 2 AND dept == 'finance'")
);
// 2) 组装上下文:把命中文档拼成“证据区”
String evidence = hits.stream()
.map(d -> "SOURCE=" + d.getMetadata().getOrDefault("source", "unknown")
+ "\n" + d.getContent())
.collect(Collectors.joining("\n\n---\n\n"));
// 3) 生成:强约束模型“只基于证据回答”
String prompt = """
你是企业知识库助手。请严格只依据【证据】回答问题。
如果证据不足,请回答“根据现有资料无法确定”,并说明缺少哪些信息。
【问题】
%s
【证据】
%s
【输出要求】
1) 先给结论(1-3 句)
2) 再给依据(引用 SOURCE)
""".formatted(q, evidence);
String answer = chatClient.prompt(prompt).call().content();
// 4) 返回:把引用也带回去,便于前端展示“来源”
List<RagCitation> citations = hits.stream()
.map(d -> new RagCitation(
String.valueOf(d.getMetadata().getOrDefault("source", "unknown"))
))
.toList();
return new RagAnswer(answer, citations);
}
public record RagAnswer(String answer, List<RagCitation> citations) {}
public record RagCitation(String source) {}
}
这段实战代码里,真正决定“企业能不能用”的是两点:
- prompt 里强制“只依据证据”
- 返回里带 citations(让用户能点回原文)
4.3 企业场景必做的三件事(不做就等着挨骂😂)
-
权限过滤(ACL)
- 向量库里每个 chunk 都要带元数据:部门、密级、可见人群
- 检索时用 filter expression 限制(不同向量库能力不同)
-
可观测性(Observability)
- 记录:query、topK 命中、最终 prompt 长度、token 消耗、延迟
- 否则“为什么这次答错?”你只能靠猜
-
评测闭环(Evaluation)
- 建一个小的“问题集 + 标准答案/可接受答案”
- 每次改切分策略/模型/过滤规则都跑一遍离线评测
Redis / Chroma / Pinecone 的“落地选择建议”(一句话版)
- 内网合规 + 延迟敏感 + Redis 体系成熟:优先 RedisVectorStore(Redis Stack)
- 快速 PoC / 研发自测 / 小规模知识库:Chroma(starter 配置快)
- 云托管 + 规模增长 + 少运维:Pinecone(注意数据策略)
🧧福利赠与你🧧
无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。
最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。
同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G PDF编程电子书、简历模板、技术文章Markdown文档等海量资料。
ps:本文涉及所有源代码,均已上传至Gitee:
https://gitee.com/bugjun01/SpringBoot-demo开源,供同学们一对一参考 Gitee传送门https://gitee.com/bugjun01/SpringBoot-demo,同时,原创开源不易,欢迎给个star🌟,想体验下被🌟的感jio,非常感谢❗
🫵 Who am I?
我是 bug菌:
- 热活跃于 CSDN:
https://blog.csdn.net/weixin_43970743| 掘金:https://juejin.cn/user/695333581765240| InfoQ:https://www.infoq.cn/profile/4F581734D60B28/publish| 51CTO:https://blog.51cto.com/u_15700751| 华为云:https://bbs.huaweicloud.com/community/usersnew/id_1582617489455371| 阿里云:https://developer.aliyun.com/profile/uolxikq5k3gke| 腾讯云:https://cloud.tencent.com/developer/user/10216480/articles等技术社区; - CSDN 博客之星 Top30、华为云多年度十佳博主&卓越贡献奖、掘金多年度人气作者 Top40;
- 掘金、InfoQ、51CTO 等平台签约及优质作者;
- 全网粉丝累计 30w+。
更多高质量技术内容及成长资料,可查看这个合集入口 👉 点击查看:https://bbs.csdn.net/topics/612438251 👈️
硬核技术公众号 「猿圈奇妙屋」https://bbs.csdn.net/topics/612438251 期待你的加入,一起进阶、一起打怪升级。
- End -
- 点赞
- 收藏
- 关注作者
评论(0)