上集回顾:老张给客服AI装上了"海马体",多轮对话终于连贯了。但新问题来了------用户问"你们ERP系统的功能有哪些?"AI傻眼了:"我不知道你们公司有什么系统..."
一、故事继续:知识鸿沟
周一早上,张姐又来了:
"老张,有个大客户在咨询咱们的ERP系统,AI怎么啥都不知道?客户都快跑了!"
老张一看后台:
用户:你们的ERP系统支持什么功能?
AI:抱歉,我不了解贵公司的产品...
老张的顿悟:"AI虽然会聊天、有记忆,但它从来没读过我们的文档!它不知道我们公司是做什么的!"
这就好比你有个聪明的秘书,但他从没看过公司的产品手册------你让他回答业务问题,他只能瞎猜。
二、技术引入:什么是RAG?
2.1 RAG是什么?
RAG = Retrieval-Augmented Generation(检索增强生成)
| 传统大模型 | RAG增强 |
|---|---|
| 只靠训练数据回答 | 先查资料,再生成答案 |
| 不知道公司内部信息 | 能基于公司文档回答 |
| 幻觉问题严重 | 有资料可查,有据可依 |
| 知识更新需重新训练 | 上传新文档即可 |
老张的类比:"RAG就像开卷考试------以前AI是闭卷,现在允许它翻书了!"
2.2 RAG的工作流程
用户提问
↓
① 检索:在知识库中找相关资料
↓
② 增强:把资料塞进Prompt
↓
③ 生成:AI基于资料生成答案
↓
返回答案(带来源引用)
三、第一步:文档解析
3.1 Spring AI的DocumentReader
Spring AI 通过 Apache Tika 提供了统一的多格式解析器 TikaDocumentReader,一份代码就能读 PDF / Word / TXT / Markdown / HTML:
java
// 一份代码通吃所有格式(PDF、Word、TXT、MD、HTML)
DocumentReader reader = new TikaDocumentReader(resource);
List<Document> documents = reader.read();
// 如果是纯 PDF,也可以用更细的 PagePdfDocumentReader / ParagraphPdfDocumentReader
// DocumentReader pdfReader = new PagePdfDocumentReader(resource);
⚠️ 代码验证说明 :早期版本有
PdfReader、WordDocumentReader等独立类,Spring AI 1.0 起统一收敛为TikaDocumentReader(按页/按段拆分可配ExtractedTextFormatter)。本教程统一用TikaDocumentReader,避免类名随版本变动。
3.2 实战:解析PDF
java
@Service
public class DocumentService {
public List<Document> parsePdf(String filePath) {
Resource resource = new FileSystemResource(filePath);
// 统一用 TikaDocumentReader 解析(PDF/Word/TXT 都支持)
DocumentReader reader = new TikaDocumentReader(resource);
// 解析并返回文档列表
return reader.read();
}
}
老张的发现:"原来Spring AI已经封装好了各种解析器,跟Spring Boot自动装配一样省心!"
四、第二步:文本分块
4.1 为什么要分块?
直接扔整个PDF给AI?不行!
| 问题 | 原因 |
|---|---|
| Token限制 | 大模型有输入长度上限 |
| 检索精度 | 整篇文档太粗,定位不准 |
| 语义完整 | 需要按段落/句子切分 |
4.2 TokenTextSplitter
java
// Spring AI 1.0:TokenTextSplitter 构造参数为
// (chunkSize, minChunkSizeChars, maxChunkSizeChars, overlap, maxNumChunks)
TextSplitter splitter = new TokenTextSplitter(
500, // 每个 chunk 最大 500 个 token
100, // 最小 chunk 字符数
800, // 最大 chunk 字符数
50, // 重叠 50 个 token(保持上下文连贯)
10000 // 最大 chunk 数量上限
);
// 分块
List<Document> chunks = splitter.apply(documents);
老张的比喻:"就像把一本书切成章节,每章几百字,方便查找和记忆。"
五、第三步:向量化
5.1 EmbeddingModel
把文字转成向量(数字列表),这样计算机才能"理解"语义:
java
@Service
public class EmbeddingService {
@Autowired
private EmbeddingModel embeddingModel;
public float[] embed(String text) {
// 调用智谱Embedding-2模型
EmbeddingResponse response = embeddingModel.call(text);
return response.getResults().get(0).getEmbedding();
}
}
输出示例:
原文:"退货政策是什么?"
向量:[0.023, -0.156, 0.789, ...](1536维)
5.2 语义相似度
"退货政策"的向量 ≈ "退款规定"的向量 → 相似度0.85
"订单查询"的向量 ≠ "退货政策"的向量 → 相似度0.32
老张的理解:"意思相近的文字,向量距离就近;意思无关的,距离就远。AI就是靠这个'理解'文字!"
六、第四步:存入向量库
6.1 主流向量库对比
| 向量库 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Redis | 快、简单 | 非专用 | 开发测试 |
| PgVector | PostgreSQL扩展 | 需PostgreSQL | 中小型项目 |
| Milvus | 性能好 | 部署复杂 | 大规模生产 |
| Chroma | 轻量本地 | 功能有限 | 个人项目 |
6.2 Redis向量库(推荐入门)
xml
<!-- 依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-redis</artifactId>
</dependency>
yaml
# 配置
spring:
ai:
vectorstore:
redis:
host: localhost
port: 6379
index-name: spring-ai-index
prefix: "spring-ai:"
6.3 存储文档
java
@Service
public class KnowledgeBaseService {
@Autowired
private VectorStore vectorStore;
@Autowired
private TextSplitter splitter;
@Autowired
private EmbeddingModel embeddingModel;
public void addDocument(Document doc) {
// 1. 分块
List<Document> chunks = splitter.apply(Collections.singletonList(doc));
// 2. 生成向量并存储
vectorStore.add(chunks);
}
}
七、第五步:检索增强生成
7.1 使用QuestionAnswerAdvisor
Spring AI内置了RAG助手,一行代码搞定:
java
@Service
public class RagChatService {
@Autowired
private ChatClient chatClient;
@Autowired
private VectorStore vectorStore;
public String chatWithRag(String question) {
return chatClient.prompt()
.user(question)
.advisors(new QuestionAnswerAdvisor(vectorStore)) // 添加RAG助手
.call()
.content();
}
}
老张的惊喜:"就一行?不需要手写检索逻辑?Spring AI太贴心了!"
7.2 完整流程演示
java
// 1. 上传文档到知识库
KnowledgeBaseService.addDocument(new Document(
"我们的ERP系统支持:采购管理、销售管理、库存管理、财务管理..."
));
// 2. 用户提问
String answer = ragChatService.chatWithRag("你们的ERP支持什么功能?");
// 3. AI回答(基于文档)
/*
根据我们的产品文档,我们的ERP系统主要支持以下功能:
1. 采购管理:供应商管理、采购订单、入库管理
2. 销售管理:客户管理、销售订单、出库管理
3. 库存管理:仓库管理、库存调拨、盘点管理
4. 财务管理:应收应付、成本核算、报表分析
*/
八、效果对比
| 场景 | 无RAG | 有RAG |
|---|---|---|
| 问公司产品 | 瞎编或说不知道 | 准确引用文档 |
| 问内部流程 | 通用回答 | 基于内部资料 |
| 知识更新 | 需重新训练 | 上传新文档 |
| 幻觉问题 | 严重 | 大幅降低 |
张姐的评价:"现在AI回答都有依据了,客户也放心了!"
九、下一集预告
RAG跑通了,但老张发现一个问题:检索质量不稳定。有时能召回正确答案,有时却找到了无关内容。
第5集《向量数据库是什么?AI的第二大脑》将深入讲解:Embedding原理、向量相似度计算、以及如何调优检索效果。
📦 完整代码
GitHub分支:chapter04-rag-intro
💬 互动环节
老兵问答:
你的项目中有需要接入AI知识库的场景吗?
A. 已有,正在做
B. 计划做,还没开始
C. 暂时没有
D. 其他(评论区聊聊)
下周三晚9点,我们继续!
作者:Java老兵搞AI | 关注我,看Java如何玩转AI