💡 核心结论:一句话先记住 如果说大模型是一个"脑容量有限且不上网"的万事通(知识停留在被训练好的那一年,而且记不住海量企业文件),那么 RAG(检索增强生成) 就是给它配了一个"实时联网的企业私有资料库"。每次回答问题前,先去资料库里查一查,带着资料再开口,从此告别胡说八道!
🛑 一、 为什么需要 RAG?(大模型的两个致命伤)
- 有限的上下文(脑容量小): 它们无法一次性摄取整个语料库,你不可能把全公司的文档一次性塞进它的聊天框。
- 静态知识(知识被冻结): 它们的训练数据在某个时间点就被冻结了,不知道最新的业务动态和私有数据。
大白话解药: 检索(Retrieval)通过在查询时获取相关的外部知识来解决这些问题。RAG 的基础就是:使用特定上下文的信息来增强 LLM 的回答,产生基于事实的答案。
📁 二、 怎么搭一个 RAG?(两大核心步骤)
- 构建知识库 (Knowledge Base)
大白话: 也就是存放你用来检索的文档或结构化数据的存储库。
- 从零建库: 你可以使用 Spring AI Alibaba 提供的"文档加载器"和"向量存储"从你自己的数据(如 PDF、Word)从头构建。
- 用现成的库: 如果你已经有一个知识库(例如现有的 SQL 数据库、CRM 或内部文档系统),千万别重建它! 你可以直接:
- 将其连接为 Agent 的工具,用于 Agentic RAG。
- 直接查询它,并将检索到的内容作为上下文提供给 LLM,用于 两步 RAG。
- Spring AI Alibaba RAG 组件与构建模块
框架为你提供了一整套数据流水线上的"零件"(模块化 RAG 架构):
- 文档加载器和解析器: 从外部源(文件、数据库、云存储等)摄取数据,返回标准化的文档对象。
- 文本分割器: 把大型长文档切碎成更小的块,方便单独检索,也能塞进模型的上下文窗口。
- 嵌入模型 (Embedding Model): 把文字变成机器能理解的数字向量。
- 向量存储 (Vector Store): 专门用于存储和搜索嵌入的数据库。
- 检索器 (Retriever): 负责在用户提问时,找出最相关的文档块。
🏛️ 三、 RAG 的三大架构流派(核心玩法)
- 两步 RAG (Two-step RAG) ------ 规矩老实人
大白话: 检索步骤总是在生成步骤之前执行。每次用户提问,系统先默默去查库,查到了资料,再把资料和问题一起交给大模型。
- 优点: 架构简单、可预测。因为 LLM 调用的最大次数是已知且有上限的(就1次),延迟相对好控制(主要受网络和数据库查询速度影响)。
- 适用场景: 明确需要查资料才能回答的业务场景。
💻 两步 RAG 代码展示(使用 Hook 拦截塞入资料): 在 Spring AI Alibaba 中,官方推荐使用 MessagesModelHook 或 ModelInterceptor 在模型调用前"偷塞"资料。
Java
// 使用 MessagesModelHook 实现两步 RAG
import com.alibaba.cloud.ai.graph.agent.hook.ModelHook;
ModelHook ragHook = new MessagesModelHook() {
@Override
public CompletableFuture<Map<String, Object>> beforeModel(OverAllState state, RunnableConfig config) {
// 1. 拿到用户提问
String userQuery = (String) state.get("input");
// 2. 从检索器中找出相关文档块
List<Document> docs = retriever.retrieve(userQuery);
String context = docs.stream().map(Document::getContent).collect(Collectors.joining("\n"));
// 3. 把知识拼接到消息列表里喂给大模型
List<Message> messages = (List<Message>) state.value("messages").orElse(new ArrayList<>());
messages.add(new SystemMessage("请严格根据以下参考资料回答问题:\n" + context));
return CompletableFuture.completedFuture(Map.of("messages", messages));
}
};
// 挂载到 Agent 身上
ReactAgent agent = ReactAgent.builder()
.name("two_step_rag_agent")
.model(chatModel)
.hooks(ragHook) // 拦截发功
.build();
- Agentic RAG ------ 聪明智能体
大白话: 把你的系统(SQL 库、内部 Wiki)封装成工具 (Tool) 给 Agent。大模型拿到问题后,自己评估"这题我会不会?要不要用工具查?查几次?"。
- 优点: 极其灵活,能处理复杂的复合问题。
- 缺点: 延迟不可控,它可能来回调用好几次工具才给你最终答案。
💻 Agentic RAG 代码展示(把数据库变成工具):
Java
// 封装查询现有系统的工具
ToolCallback dbSearchTool = FunctionToolCallback.builder("search_internal_db", (query) -> {
return myDatabaseService.queryData(query);
}).description("当需要查询内部业务数据时,务必调用此工具").build();
// Agent 直接拿工具干活
ReactAgent agenticRagAgent = ReactAgent.builder()
.name("agentic_rag_agent")
.model(chatModel)
.tools(dbSearchTool) // ⭐ 丢给它工具,让它自己判断何时调用
.build();
- 混合 RAG (Hybrid RAG) ------ 究极缝合怪
大白话: 小孩子才做选择,大人全都要。在实际应用中,通常会将上述策略结合起来,或者在检索底层同时使用"关键词检索"+"向量检索"来保证极高的召回率和准确率。
🏆 四、 最佳实践总结
不要将 RAG 仅仅停留在"检索出一段文字"上。大多数实际应用需要更进一步:将检索与生成深度集成,产生基于事实的、上下文感知的答案。 采用模块化 RAG 架构(将加载、切分、检索解耦),可以让你在未来轻松替换组件(比如升级更强的向量数据库或嵌入模型)。
🎯 终极秒记口诀 模型脑子不够用,旧库僵化不顶用; RAG 把外脑来接通,找准资料再播送; 加载切分向量化,模块组件立大功; 两步 RAG Hook 塞,Agentic 工具向前冲!