【SpringAIAlibaba新手村系列】(12)RAG 检索增强生成技术

简介: 本文深入探讨 RAG 技术在 AiOps 场景中的应用,以基于 ops.txt 构建运维知识库为例,讲解了如何通过将文本切分、向量化并存入向量数据库,实现 AI 故障查询。内容涵盖 EmbeddingModel、VectorStore 的基本概念,以及利用 Redis 的 SETNX 机制防止知识库重复导入的工程实践。核心在于让 AI 结合外部知识库,更准确地回答运维问题。

第十二章 RAG 检索增强生成技术

版本标注

  • Spring AI: 1.1.2
  • Spring AI Alibaba: 1.1.2.0

章节定位

  • 本章的 RetrievalAugmentationAdvisor + VectorStore 仍然是经典 RAG 入门方案。
  • 但 Spring AI Alibaba 1.1.2.x 官方代码已经进一步演进到 RAG Workflow 思路,典型流程是:Query -> Rewrite -> Retrieve -> Prepare -> Agent -> Response
  • 因此,本章建议理解为“基础版 RAG”;复杂业务更推荐升级为 Graph/Workflow 版本的 RAG。

s01 > s02 > s03 > s04 > s05 > s06 > s07 > s08 > s09 > s10 > s11 > [ s12 ] s13 > s14 > s15 > s16 > s17 > s18

"先查资料, 再作回答" -- RAG 的核心不是更会编, 而是更少胡说。


一、为什么需要 RAG?

1.1 AI 的知识局限

AI 大模型虽然很强,但它有以下局限:

  1. 知识有时效性:训练数据截止某个时间点,之后的事不知道
  2. 专业知识缺乏:某些垂直领域的知识可能不准确
  3. 企业内部信息:它不知道你公司的业务和数据

1.2 传统解决方式

微调(Fine-tuning):让 AI 重新训练

  • 缺点:成本高、需要大量数据、时间长
  • 适合:通用知识需要调整的场景

1.3 RAG 的诞生

RAG(Retrieval-Augmented Generation,检索增强生成) 的核心思想是:

"不改变 AI 的基础能力,而是在它回答问题时,先去知识库查找相关信息,然后把信息连同问题一起发给 AI"

传统方式:
用户 ──→ AI ──→ 直接回答(AI靠记忆)

RAG方式:
用户 ──→ 向量搜索 ──→ 知识库查找相关信息 ──→ 
      ──→ 把"问题+找到的信息"一起发给 AI ──→ AI结合信息回答

二、RAG 工作流程

2.0 工作流化的 RAG 思路

在很多入门教程里,我们通常把 RAG 理解成:

  1. 用户提问
  2. 向量检索
  3. 把检索结果塞进 Prompt
  4. 调用 LLM 回答

这条链路没有问题,但在 Spring AI Alibaba 1.1.2.x 的官方 workflow 示例中,RAG 已经进一步升级成更可控的多步骤流程:

Query -> Rewrite -> Retrieve -> Prepare -> Agent -> Response

各步骤的含义如下:

  • Rewrite:先让模型把原始问题改写成更适合检索的查询语句
  • Retrieve:基于改写后的查询做向量检索
  • Prepare:把命中的文档、用户问题、约束条件整理成更稳定的上下文
  • Agent:再交给 ReactAgent 或普通聊天模型生成最终答案

这种做法的好处是:

  1. 检索命中率通常更高
  2. Prompt 注入更清晰
  3. 更容易做调试、观测和节点拆分
  4. 后续更容易迁移到 Graph 和工作流编排

所以你可以把本章先学成“基础 RAG”,再进一步理解成可拆分、可编排的工作流化 RAG。

2.1 完整的 RAG 流程

┌─────────────────────────────────────────────────────────────┐
│                    RAG 完整流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   阶段一:数据准备(离线)                                    │
│   ┌──────────┐    ┌──────────┐    ┌──────────┐             │
│   │ 文档集合 │───→│ 文本分块 │───→│ 向量化   │───→存入向量库│
│   └──────────┘    └──────────┘    └──────────┘             │
│                                                             │
│   阶段二:问答推理(在线)                                    │
│   ┌──────────┐    ┌──────────┐    ┌──────────┐             │
│   │ 用户问题 │───→│ 向量化   │───→│ 相似度搜索│───→获取相关 │
│   └──────────┘    └──────────┘    └──────────┘    文档      │
│                                            ↓                │
│   ┌──────────┐    ┌──────────┐    ┌──────────┐             │
│   │ 构建Prompt│←── │ 拼接上下文│←── │ 注入知识  │            │
│   └──────────┘    └──────────┘    └──────────┘             │
│                                            ↓                │
│                                   ┌──────────┐             │
│                                   │ 调用LLM │              │
│                                   └──────────┘             │
│                                            ↓                │
│                                   返回结合知识后的答案        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.2 本章场景:运维故障查询

这一章不是直接让大模型“凭空回答运维问题”,而是先给它准备一份本地知识资料,再通过 RAG 的方式让它去查资料后回答。

这份资料就放在项目的 resources 目录下,文件名通常叫:

ops.txt

你可以把它理解成一份简化版的“运维故障知识库”。里面会提前写好一些故障编码及对应说明,例如:

  • 故障编码:A0001
  • 故障编码:C2222
  • 对应解释:存储系统异常、网络不通、服务不可用等

也就是说,本章真正要做的事情不是“训练一个懂运维的大模型”,而是:

  1. 先把 ops.txt 里的故障资料读出来
  2. 将这些文本切分、向量化并存入向量数据库
  3. 用户提问时,先去向量库里检索最相关的故障说明
  4. 再把检索结果和用户问题一起交给大模型生成答案

这样一来,用户在调用接口时,不需要自己知道完整故障说明,只需要问类似:

  • A0001 是什么故障?
  • C2222 怎么处理?
  • 网络不通对应哪个故障编码?

系统就能先从 ops.txt 这份知识资料里找到相关内容,再让 AI 组织成更自然的回答。

所以这一章的场景,准确地说应该是:

基于 resources/ops.txt 构建一个小型运维知识库,然后通过 RAG 实现“查故障码、问故障原因、做运维问答”的效果。


三、项目代码详解

3.1 配置类

package com.atguigu.study.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SaaLLMConfig
{
   
    /**
     * 注册 Qwen 的 ChatClient
     */
    @Bean("qwenChatClient")
    public ChatClient qwenChatClient(@Qualifier("dashScopeChatModel") ChatModel chatModel)
    {
   
        return ChatClient.builder(chatModel).build();
    }

    /**
     * 注入已经自动配置好的 VectorStore
     */
    @Bean
    public RagService ragService(ChatClient qwenChatClient, VectorStore vectorStore)
    {
   
        return new RagService(qwenChatClient, vectorStore);
    }
}

上面这段代码想表达的重点不是“必须手写某一种向量库实现”,而是:

  1. EmbeddingModel 负责文本向量化
  2. VectorStore 负责向量检索
  3. ChatClient + Advisor 负责把检索结果注入到问答链路中

如果你选择 Redis、Milvus、PGVector 或其他实现,核心思路都一样。

3.2 RAG 控制器

package com.atguigu.study.controller;

import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.rag.advisor.RetrievalAugmentationAdvisor;
import org.springframework.ai.rag.retrieval.search.VectorStoreDocumentRetriever;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

/**
 * RAG 控制器
 * 展示如何使用检索增强生成来回答专业问题
 */
@RestController
public class RagController
{
   
    @Resource(name = "qwenChatClient")
    private ChatClient chatClient;

    // 注入已配置的向量数据库
    @Resource
    private VectorStore vectorStore;

    /**
     * RAG 问答接口
     * 
     * 接口:http://localhost:8012/rag4aiops?msg=00000
     * 接口:http://localhost:8012/rag4aiops?msg=C2222
     * 
     * 测试步骤:
     * 1. 先调用 add 接口(如果没有历史数据)
     * 2. 再调用 rag4aiops 接口询问故障码
     * 
     * @param msg 用户的故障编码查询
     * @return AI 结合知识库返回的答案
     */
    @GetMapping("/rag4aiops")
    public Flux<String> rag(String msg)
    {
   
        // 1. 定义系统提示词
        //    告诉 AI 它的角色是"运维工程师",按照知识库中的编码给出解释
        String systemInfo = """
                你是一个运维工程师,按照给出的编码给出对应故障解释,否则回复找不到信息。
                """;

        // 2. 创建检索增强Advisor
        //    这是 RAG 的核心组件!
        //    - VectorStoreDocumentRetriever 负责从向量数据库中检索相关内容
        //    - RetrievalAugmentationAdvisor 负责把检索结果注入到Prompt中
        RetrievalAugmentationAdvisor advisor = RetrievalAugmentationAdvisor.builder()
                // 指定使用向量数据库进行检索
                .documentRetriever(
                    VectorStoreDocumentRetriever.builder()
                        .vectorStore(vectorStore)
                        .build()
                )
                .build();

        // 3. 构建并发送请求
        //    在 .advisors() 中添加 RAG Advisor
        //    它会自动执行:检索 → 注入 → 调用AI → 返回结果
        return chatClient
                .prompt()
                .system(systemInfo)
                .user(msg)
                .advisors(advisor)     // 关键:添加RAG增强
                .stream()
                .content();
    }
}

四、RAG 的核心组件

4.1 RetrievalAugmentationAdvisor

这是 Spring AI 提供的 RAG 增强组件,它的作用:

  1. 拦截用户请求
  2. 从向量数据库检索相关信息
  3. 将检索结果注入到 Prompt 中
  4. 调用 AI,让它基于检索结果回答
  5. 返回最终答案

4.2 DocumentRetriever

文档检索器,负责:

  • 将用户问题转为向量
  • 在向量数据库中执行相似度搜索
  • 返回匹配度最高的文档

五、本章小结

5.1 核心概念

概念 说明
RAG 检索增强生成,让AI结合知识库回答问题
VectorStore 向量数据库,存储文档的向量
RetrievalAugmentationAdvisor RAG核心组件,自动检索+注入
DocumentRetriever 从向量数据库检索文档的组件

5.2 RAG 工作流程

提问 → 向量化 → 相似度搜索 → 提取相关文档 → 注入Prompt → 调用AI → 返回答案

5.3 应用场景

  • 企业内部知识问答
  • 产品手册查询
  • 客服问答系统
  • 专业领域知识库

本章重点

  1. 理解 RAG 的核心原理
  2. 掌握 RetrievalAugmentationAdvisor 的使用
  3. 理解 RAG 在实际场景中的应用

下章剧透(s13):

学会了 RAG 技术后,下一章我们将学习 Tool Calling(工具调用)——让 AI 能够"调用外部函数"来完成真实任务!


📝 编辑者:Flittly
📅 更新时间:2026年4月
🔗 相关资源Spring AI RAG 官方文档

目录
相关文章
|
15天前
|
NoSQL Java 数据库
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
本文围绕 Embedding 与向量数据库展开,讲解了文本向量化、相似度检索和 VectorStore 的基本用法,并结合 SimpleVectorStore 示例说明了 Spring 中自动装配与手动注册 Bean 的区别,为后续学习 RAG 打下基础。
239 4
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
|
11天前
|
人工智能 Java API
【SpringAIAlibaba新手村系列】(13)Tool Calling 函数工具调用技术
本文详细解析 Spring AI 的 Tool Calling 技术,阐明其如何弥补大模型“会说不会做”的局限。通过 @Tool 注解,开发者可轻松将 Java 方法暴露为 AI 工具。文中深入讲解了 ToolCallbacks.from() 注册工具的原理,以及工具方法在当前 Spring Boot 进程内通过反射动态执行的底层逻辑,强调了模型决策与框架执行的协同过程,为理解 AI 赋能实际操作奠定基础。
348 0
|
人工智能 JavaScript Java
【SpringAIAlibaba新手村系列】(1)初识 Spring AI Alibaba 框架
本文介绍了SpringAIAlibaba框架的基本概念和使用方法。作为Spring官方AI框架的阿里云实现版本,它简化了Java开发者调用AI模型的过程。文章详细讲解了核心概念如ChatModel、ChatClient,以及阿里云百炼平台的功能。通过HelloWorld项目示例,展示了如何配置APIKey、编写控制层代码,实现普通调用和流式输出两种AI交互方式。重点阐述了SpringAI与SpringAIAlibaba的关系,以及自动配置机制的工作原理,帮助开发者快速上手这一框架。
1452 4
|
19天前
|
人工智能 前端开发 Java
【SpringAIAlibaba新手村系列】(4)流式输出与响应式编程
本文围绕 Spring AI 中的流式输出与响应式编程展开,重点解释了传统一次性响应与流式返回的差异,以及 Flux 在异步数据流中的核心作用。文章结合 ChatModel.stream() 与 ChatClient 的多种代码示例,说明如何实现 AI 内容的边生成边返回,并帮助读者理解流式调用在用户体验、性能和长文本场景中的实际价值。
405 4
【SpringAIAlibaba新手村系列】(4)流式输出与响应式编程
|
5天前
|
人工智能 Java API
【SpringAIAlibaba新手村系列】(17)百炼 RAG 知识库应用
本章基于 Spring AI Alibaba 落地百炼 RAG,完成 DashScopeApi、ChatModel、ChatClient 配置,并通过检索器与 DocumentRetrievalAdvisor 组装检索增强问答链路,实现可运行的知识库问答接口。
127 1
|
18天前
|
人工智能 Java API
【SpringAIAlibaba新手村系列】(5)Prompt 提示词基础与多种消息类型
本章详解Spring AI 1.1.2中Prompt核心机制:以System/User/Assistant/Tool四类消息构建结构化提示,强调“角色决定语义”;涵盖多模型配置、链式API与底层Message组装两种实践方式,并给出系统消息设计最佳实践。
289 7
|
10天前
|
人工智能 Java 定位技术
【SpringAIAlibaba新手村系列】(14)MCP 本地服务与工具集成
本章从 MCP Server 视角出发,说明如何将本地天气查询能力整理并暴露为标准化工具服务。内容涵盖 @Tool、ToolCallbackProvider、MethodToolCallbackProvider 的作用,以及 Streamable-HTTP 协议下服务端的能力注册与对外提供逻辑。
179 13
|
存储 人工智能 Java
【SpringAIAlibaba新手村系列】(3)ChatModel 与 ChatClient 的深度对比
本章深度解析 Spring AI 中 `ChatModel`(底层接口)与 `ChatClient`(高级封装)的本质区别:前者如“手动挡”,精准控制但需写大量样板代码;后者似“智能点餐机”,链式调用、支持系统提示、模板、工具调用等,开发高效。初学者推荐优先使用 `ChatClient`。
294 0
【SpringAIAlibaba新手村系列】(3)ChatModel 与 ChatClient 的深度对比
|
17天前
|
人工智能 JSON Java
【SpringAIAlibaba新手村系列】(7)结构化输出与对象映射
本文详解 Spring AI 结构化输出功能,通过 Java Record 与 .entity() 方法,实现 AI 的 JSON 响应自动映射为 Java 对象,解决纯文本难以集成的问题。文中还对比了 Lambda 写法并提供 Prompt 设计最佳实践。
159 3
|
16天前
|
人工智能 JavaScript Java
【SpringAIAlibaba新手村系列】(10)Text to Voice 文本转语音技术
本文围绕 Spring AI Alibaba 1.1.2.2 的文本转语音实现展开,记录了基于 DashScopeAudioSpeechModel 与 stream() 的可运行方案。文章重点说明了模型、音色、输出格式与流式拼接音频文件的关键细节。
183 6

热门文章

最新文章

下一篇
开通oss服务