【Agent】Spring AI RAG 实战:本地向量库 + 云端知识库

目录

[一、场景:为什么需要 RAG](#一、场景:为什么需要 RAG)

[二、RAG 四步工作流](#二、RAG 四步工作流)

[三、本地版:ETL 链路代码](#三、本地版:ETL 链路代码)

[3.1 准备知识文档](#3.1 准备知识文档)

[3.2 文档加载器(Extract)](#3.2 文档加载器(Extract))

[3.3 向量库装配(Transform + Load + Query)](#3.3 向量库装配(Transform + Load + Query))

[3.4 第一次初始化 vs 后续加载(本篇重点)](#3.4 第一次初始化 vs 后续加载(本篇重点))

[3.5 检索增强接入(doChatWithRag)](#3.5 检索增强接入(doChatWithRag))

四、云端版:托管知识库接入

[4.1 云控制台准备](#4.1 云控制台准备)

[4.2 接入代码](#4.2 接入代码)

五、测试:检索命中日志怎么看

六、易错点速查表

七、面试怎么讲

八、下篇预告


摘要:模型答错业务政策 = 事故。用真实客服场景从 0 实现 RAG:文档加载 → 切分 → Embedding → 入库,再到检索增强问答,本地 SimpleVectorStore 与云端知识库两套方案对照,附"首次初始化 vs 后续加载"的启动机制拆解与检索日志排查技巧。 标签:Spring AI、RAG、向量数据库、知识库、大模型 分类:AI 应用开发 / Spring AI


一、场景:为什么需要 RAG

上篇文章给客服接上了记忆,它能记住对话。但业务问题照样答不了:

问题在哪:模型没有你公司的售后政策数据,只能靠"常识"编。这就是大模型的三大原罪:

|-------------|-----------------|
| 原罪 | 表现 |
| 不知道私有数据 | 你的公司政策它根本没学过 |
| 知识有截止时间 | 2024 年后改的政策它不知道 |
| 幻觉 | 不知道也硬答,还答得理直气壮 |

RAG(Retrieval-Augmented Generation,检索增强生成) 就是解法:模型回答前,先去知识库检索相关资料,把资料拼进提示词,再生成答案。相当于"开卷考试带资料"------不背进脑子,而是现查。


二、RAG 四步工作流

① 文档收集切割 :把售后政策、FAQ 等写成 Markdown/PDF,按语义切成小块(500~1000 字/块) ② 向量转换存储 :用 Embedding 模型把每块文本变成高维向量,连原文一起存进向量数据库 ③ 检索 :用户提问也转成向量,在库中算相似度,召回最相关的 topK 块 ④ 增强:把召回片段拼进 prompt:"参考以下资料回答...",模型只依据资料生成


三、本地版:ETL 链路代码

3.1 准备知识文档

我建了一个 document/ 目录放客服知识,纯 Markdown、标题清晰,方便切分后语义完整:

写作心法:一条政策写成一句完整的话(不依赖上下文代词),这样无论怎么切都不会"腰斩"关键信息。

3.2 文档加载器(Extract)

withAdditionalMetadata("filename", filename) 很关键------每个 chunk 都会带上"来自哪个文件"的元数据,后面过滤检索和排查问题都靠它。

3.3 向量库装配(Transform + Load + Query)

3.4 第一次初始化 vs 后续加载(本篇重点)

上面这段代码藏着 RAG 落地的一个关键机制------向量化是有"一次性成本"的,不该每次启动都付:

为什么要区分这两步?

|--------|---------------------------|----------------|
| 维度 | 首次初始化 | 后续加载 |
| 做了什么 | 读文档 + Embedding + 入库 + 落盘 | 从本地文件反序列化读回 |
| 耗时 | 30~40 秒(网络请求逐片向量化) | 2~5 秒(纯本地 IO) |
| API 调用 | 每个 chunk 一次 embedding(花钱) | 0 次 |
| 什么时候跑 | 知识库首次建好 / 文档更新后删缓存 | 每次应用启动 |

底层原理SimpleVectorStore 序列化时把向量也一起写进了 JSON (不只是文本)。所以 load() 时向量是现成的,根本不需要重新调 Embedding------向量库文件 vector-store.json 里存的就是"文本 + 高维向量 + 元数据"的完整数据。

日常使用的心智模型:。

3.5 检索增强接入(doChatWithRag)

改动就一处 :多挂一个 QuestionAnswerAdvisor,检索 + 拼 prompt + 基于资料回答全自动完成。

验证

------不再瞎编,答案有据可依了。


四、云端版:托管知识库接入

本地版有个痛点:SimpleVectorStore 存内存/本地文件 ,不适合多实例部署。生产上更省事的做法是用云厂商的托管知识库(阿里云百炼 / AWS Bedrock 等),文档上传由控制台管理,你只负责接 API。

4.1 云控制台准备

  1. 登录百炼控制台,创建知识库
  1. document/ 的文档上传到知识库(云端自动完成切分 + 向量化)
  1. 记下知识库名称(索引名,代码里要用,必须一字不差)

4.2 接入代码

然后 .advisors(cloudRagAdvisor) 挂上即可,调用方代码和本地版完全一样 ------QuestionAnswerAdvisor 屏蔽了底层差异,这是接口抽象的威力。

💡 本地 vs 云端在"初始化"上的差别 :本地版需要你自己管理"首次向量化 + 缓存复用";云端版把这个成本转移到了控制台------文档上传时云端就完成切分向量化,应用每次启动只是连接远程检索,天然没有"重复向量化"问题。


五、测试:检索命中日志怎么看

RAG 最怕"以为在检索,其实没命中"。建议在自定义 Advisor 里打日志看每次检索命中什么:

日志里该看到的样子

看到 filename 来源、命中条数、内容预览 → 检索链路就是通的。


六、易错点速查表

|-------------------------------|---------------------------------------------------|---------------------------------------------|
| 坑 | 原因 | 排查/修复 |
| 召回为 0 | 入库和检索用的 Embedding 模型不一致(两个不同的 embedding 向量空间) | 全程用同一个 EmbeddingModel Bean |
| 检索到但答案仍瞎编 | topK 太小没召回对 / system prompt 没约束"必须基于资料" | 调大 topK(5~10),prompt 写死"资料没有就说不知道" |
| 云端报 Index not found / 404 | 知识库名称与配置不一致 | 代码里的索引名 = 控制台知识库名,一字不差 |
| 改了文档但检索结果没变 | 缓存文件没删,走的是 load 分支 | 文档更新后删除 tmp/vector-store.json 重新初始化 |
| 重启后检索全空 | 本地 SimpleVectorStore 没落盘 | store.save(File) 落盘,启动时 load(File) |
| 切分后语义断裂 | chunk 太小或太大 | 5001000 字/块,保留 50200 字重叠 |
| 命中一堆无关片段 | 没做召回后的相关性过滤 | 设 similarityThreshold(如 0.6),低分块不进 prompt |

相关推荐
必须会一定会1 小时前
GPT-6 Astra 官方基准与 AI 编程能力:ARC-AGI-3、Terminal-Bench 4.0、长上下文评测
人工智能·gpt·agi
Java后端的Ai之路1 小时前
LangChain Deep Agents 从入门到企业实战
开发语言·人工智能·python·langchain·deepagents
ShallWeL1 小时前
RAG Embedding 模型替换与索引回归
人工智能·embedding·知识库·工作流·rag
小刘在重生~1 小时前
Java 集合|Collection、List、ArrayList、LinkedList、泛型、Collections 工具类
java·数据结构·list
爱吃火鸡面呀1 小时前
OpenCV 人脸检测与识别实战:从静态图像到视频流
人工智能·opencv·计算机视觉
北京晶数信息科技1 小时前
加油站成品油智慧监管云平台成品油流通数智化监管平台加油机数据采集设备交易即开票全链路技术实现方案:技术拆解、架构设计与落地实践
大数据·人工智能
知了一笑1 小时前
职场丨岗位减少,职责增加
大数据·人工智能·职场·产品·业务
懂压力传感器的涌客1 小时前
机器人触觉传感器方案中FSR如何选型与集成
人工智能·机器人·压力传感器·fsr·源头工厂·fsr压力传感器
超级架构师1 小时前
连接企业系统,不等于把接口直接交给 Agent:LIMENORA 的集成边界
网络·人工智能·架构·ai编程