当前位置: 首页 > news >正文

Spring AI RAG 检索增强生成:概念、实战与完整代码

场景

Spring AI ChatMemory 对话记忆配置JDBC方式到Mysql数据库实战示例与原理讲解:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/161040572

基于上述基础,学习RAG的使用。

大语言模型(LLM)存在知识滞后、易产生幻觉、领域知识不足等局限性。

检索增强生成(Retrieval Augmented Generation,RAG)技术通过“外部知识检索 + LLM生成”的模式,

在回答问题前先从外部知识源中查找相关信息,再结合自身能力组织语言输出,有效弥补了这些缺陷。

本文将基于之前的 Spring AI 1.1.2 + Ollama 技术栈,系统性地介绍 RAG 的核心概念、Spring AI 中的实现方式,

并提供可直接运行的完整实例代码。

一、RAG 核心概念与工作流程

1.1 什么是 RAG?

RAG 技术的核心在于将检索与生成相结合。传统的生成模型依赖训练数据来生成回答,

当面对新问题或新兴领域知识时,可能产生不准确或不合逻辑的回答。

RAG 引入检索机制,在接收到用户问题后,首先从外部知识库中检索相关信息,

然后将其与原始问题一同输入给生成模型,从而产生更准确、上下文相关的答案。

1.2 RAG 四步流程

步骤说明关键技术
① 文档加载与分块(Ingestion)将原始文档(PDF、TXT 等)加载进来,切割成适合嵌入的小片段(chunks)DocumentReader、TokenTextSplitter
② 向量化与存储(Embedding & Store)用 Embedding 模型将文本片段转换为高维向量,存入向量数据库EmbeddingModel、VectorStore
③ 语义检索(Retrieval)用户提问时,将问题同样向量化,在数据库中执行相似度搜索,检索最相关片段SearchRequest、相似度计算
④ 增强生成(Generation)将检索到的相关文档片段作为上下文,与用户问题一起提交给 LLM,生成精准回答ChatClient + PromptTemplate

1.3 向量数据库

向量数据库专门用于存储、管理和高效检索高维向量数据。

其核心优势是支持语义级搜索——例如“苹果手机”和“iPhone”虽关键词不同,但语义相近,其向量距离很小,可被精准匹配到。

Spring AI 通过 VectorStore 接口抽象了向量数据库的访问,支持多种实现:

SimpleVectorStore(内存向量库,适合原型开发)

Elasticsearch

PgVector

Milvus / Weaviate / Chroma 等

1.4 关键组件依赖关系

组件角色Spring AI 接口
Document表示原始文档及其元数据org.springframework.ai.document.Document
DocumentReader从文件系统加载文档JsonReaderTextReaderPagePdfDocumentReader
TextSplitter将长文本切割成小块TokenTextSplitter
EmbeddingModel将文本转换为向量EmbeddingModel(Ollama 提供)
VectorStore存储和检索向量SimpleVectorStoreElasticsearchVectorStore
QuestionAnswerAdvisor拦截用户请求,自动检索并注入上下文QuestionAnswerAdvisor.builder(vectorStore)

二、Spring AI RAG 实现方式

Spring AI 通过 Advisor API 为 RAG 提供了开箱即用的支持,核心组件是 QuestionAnswerAdvisor。

使用时需要添加 spring-ai-advisors-vector-store 依赖

2.1 QuestionAnswerAdvisor 工作原理

当用户问题发送到 AI 模型时,QuestionAnswerAdvisor 会查询向量数据库以获取与用户问题相关的文档,

将这些文档附加到用户文本中作为上下文,然后再提交给 AI 模型生成回答。其可配置项为:

配置项说明示例
similarityThreshold相似度阈值,低于此值的文档将被过滤0.8
topK返回最相关的前 K 个文档6
FILTER_EXPRESSION动态过滤表达式(类似 SQL WHERE)"type == 'Spring'"
promptTemplate自定义提示词模板,控制上下文与用户问题的拼接方式包含{query}{question_answer_context}占位符

2.2 检索与生成分离的 ETL 模型

Spring AI RAG 遵循 ETL(Extract-Transform-Load)模型:

Extract(提取):从知识库中读取文档。

Transform(转换):将文档分割为小块,并通过 Embedding 模型转换为向量。

Load(加载):将向量数据写入向量数据库。

这三个步骤通常在应用启动时完成。

运行时,基于 ETL 模型实现真正的 RAG——用户的查询被嵌入,向量数据库被查询,检索到的文档被注入到 LLM 的提示词中。

2.3 RAG Advisor 与其他 Advisor 的组合

RAG 的 QuestionAnswerAdvisor 可以与之前介绍的 Advisor 自由组合:

组合方式效果
QuestionAnswerAdvisor+MessageChatMemoryAdvisor带记忆的 RAG 问答
QuestionAnswerAdvisor+SensitiveWordGuardAdvisor安全过滤 + RAG
QuestionAnswerAdvisor+SimpleLoggerAdvisor调试日志
全部组合安全过滤 → 日志记录 → 对话记忆 → 文档检索 → LLM 生成

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

实现

以下示例基于 Spring AI 1.1.2 + Ollama + SimpleVectorStore,演示如何从零构建一个本地 RAG 知识库问答系统。

pom.xml

<properties> <java.version>17</java.version> <spring-ai.version>1.1.2</spring-ai.version> </properties> <!-- 新增:使用 Spring AI BOM 统一管理所有模块版本 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>${spring-ai.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring AI Ollama 核心 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-ollama</artifactId> </dependency> <!-- RAG Advisor(核心:提供 QuestionAnswerAdvisor) --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-advisors-vector-store</artifactId> </dependency> <!-- Tika 文档读取器(支持 PDF、Word、TXT 等多种格式) --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-tika-document-reader</artifactId> </dependency> </dependencies>

示例知识库文件

在src/main/resources/knowledge-base/badao-internal.txt 中创建:

Badao科技内部知识库 ## 公司政策 - 员工年假:入职满1年享受10天带薪年假,满3年增加到15天。 - 远程办公:每周三、周五为固定远程办公日。 - 报销流程:所有报销需在“易报销”系统提交,金额超过500元需部门经理审批。 ## 内部项目 - 项目代号“天枢”:基于Spring AI与Ollama构建的企业智能助手,负责人为张三。 - 项目代号“瑶光”:下一代实时数据湖方案,采用Apache Iceberg + Flink,负责人为李四。 - 内部编码规范:所有Java项目必须使用Lombok,禁止使用var关键字,SQL必须使用参数化查询。 ## 技术选型 - 消息中间件:统一使用RocketMQ,禁止引入RabbitMQ。 - 向量数据库:生产环境采用PgVector,开发环境可使用SimpleVectorStore。 - 前端框架:统一使用React 18 + Ant Design 5.x。 ## 团队联系人 - 基础架构组:赵六(zhaoliu@badao.com) - AI组:王五(wangwu@badao.com) - 数据组:钱七(qianqi@badao.com)

application.yml

​ server: port: 886 spring: # 替换为实际密码 ai: ollama: base-url: http://localhost:11434 chat: model: qwen2.5:7b-instruct options: temperature: 0.3 # RAG 场景建议使用较低温度,减少幻觉 embedding: model: nomic-embed-text # Embedding 模型(用于文档向量化) options: num-batch: 4 # 一次处理的文本数量 logging: level: org.springframework.ai.rag: DEBUG org.springframework.ai.vectorstore: DEBUG ​

Embedding 模型下载(项目启动前执行)

ollama pull nomic-embed-text

模型选型说明:

Chat 模型:

qwen2.5:7b-instruct 支持工具调用且中文能力强,适合生成自然语言回答。也可选择 deepseek-r1:8b、llama3.1:8b 等。

Embedding 模型:

nomic-embed-text 生成 768 维向量,免费且质量好。也可选择 bge-m3(1024 维)、mxbai-embed-large(1024 维)等,

但需修改配置文件中 dimensions 参数。

核心要求:

Chat 模型和 Embedding 模型都必须是 Ollama 本地已下载的模型,

且 Embedding 模型的向量维度必须与向量数据库的 dimensions 配置一致。

VectorStoreConfig — 文档加载与向量存储初始化

Spring AI 在 RAG 流程中默认不负责文档分词,文档的加载与分词需要开发者显式调用 DocumentReader 和 TextSplitter 来完成。

package com.badao.ai.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.document.Document; import org.springframework.ai.document.DocumentReader; import org.springframework.ai.reader.tika.TikaDocumentReader; import org.springframework.ai.transformer.splitter.TokenTextSplitter; import org.springframework.ai.vectorstore.SimpleVectorStore; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; import java.util.List; @Configuration public class VectorStoreConfig { private static final Logger logger = LoggerFactory.getLogger(VectorStoreConfig.class); @Value("classpath:knowledge-base/badao-internal.txt") private Resource knowledgeResource; @Bean public VectorStore vectorStore(EmbeddingModel embeddingModel) { // 创建内存向量库(开发演示用) return SimpleVectorStore.builder(embeddingModel).build(); } @Bean public CommandLineRunner loadDocuments(VectorStore vectorStore) { return args -> { // 1. 使用 Tika 读取文档(自动检测文件类型) DocumentReader reader = new TikaDocumentReader(knowledgeResource); List<Document> documents = reader.get(); logger.info("共读取到 {} 个文档", documents.size()); // 2. 文本分块(TokenTextSplitter 按语义切分,更适合中文) TokenTextSplitter splitter = TokenTextSplitter.builder() .withChunkSize(300) // 每个块最多 300 token .withMinChunkSizeChars(50) // 最小块字符数,避免出现极短碎片(替代原来 minChunkSize 的功能) .withMinChunkLengthToEmbed(5) // 保留默认,过滤极短内容 .withKeepSeparator(true) // 保留原文换行等分隔符 .build(); List<Document> chunks = splitter.apply(documents); logger.info("文本切分为 {} 个片段", chunks.size()); // 3. 写入向量数据库(自动调用 EmbeddingModel 向量化) vectorStore.add(chunks); logger.info("向量化完成,向量库初始化成功!"); }; } }

要点说明:

SimpleVectorStore 是 Spring AI 内置的内存向量库实现,适合原型开发和小规模知识库(文档量不超过几千条)。

数据存在内存中,服务重启后需要重新加载,生产环境请替换为 PgVectorStore、ElasticsearchVectorStore 等持久化方案。

TokenTextSplitter 按 Token 数量切分文本,避免切断句子。chunkOverlap 设置重叠区域,保证语义连贯性,防止关键信息被切断。

TikaDocumentReader 基于 Apache Tika,可自动识别 PDF、Word、TXT、HTML 等多种文档格式,无需手动判断文件类型。

RagConfig — 注册 RAG Advisor

package com.badao.ai.config; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RagConfig { @Bean public ChatClient chatClient(ChatModel chatModel, VectorStore vectorStore) { return ChatClient.builder(chatModel) .defaultAdvisors( QuestionAnswerAdvisor.builder(vectorStore) .searchRequest(SearchRequest.builder() .similarityThreshold(0.7) // 相似度阈值 .topK(3) // 返回前 3 个最相关文档 .build()) .build() ) .build(); } }

RagService

package com.badao.ai.service; import org.springframework.ai.chat.client.ChatClient; import org.springframework.stereotype.Service; @Service public class RagService { private final ChatClient chatClient; public RagService(ChatClient chatClient) { this.chatClient = chatClient; } /** * 基于知识库的 RAG 问答 */ public String ask(String question) { return chatClient.prompt() .user(question) .call() .content(); } }

控制器

package com.badao.ai.controller; import com.badao.ai.service.RagService; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api") public class RagController { private final RagService ragService; public RagController(RagService ragService) { this.ragService = ragService; } @PostMapping("/rag") public ChatResponse rag(@RequestBody ChatRequest request) { String result = ragService.ask(request.message()); return new ChatResponse(200, "success", result); } public record ChatRequest(String message) {} public record ChatResponse(int code, String msg, String data) {} }

测试验证

常用优化策略

策略说明配置示例
提高相似度阈值相同topK下减少候选文档量,剔除不相关文档similarityThreshold(0.8)
降低相似度阈值相同topK下增加候选文档量,适合文档量大的场景similarityThreshold(0.5)
控制返回数量topK不宜过大,否则会超出模型上下文窗口topK(3)
文档分块优化调整chunkSizechunkOverlap平衡精度和召回率chunkSize(300),chunkOverlap(50)
动态过滤按文档类型、日期等元数据过滤.param(QuestionAnswerAdvisor.FILTER_EXPRESSION, "type == 'manual'")
自定义提示词模板控制上下文与用户问题的拼接格式,提升回答质量见 上文

总结

环节核心组件关键操作
文档加载TikaDocumentReader自动识别多种文档格式
文本分块TokenTextSplitterchunkSize(300),chunkOverlap(30)
向量化EmbeddingModelOllama 提供nomic-embed-text模型
向量存储VectorStore开发用SimpleVectorStore,生产用 PgVector / Elasticsearch
检索 + 生成QuestionAnswerAdvisorsimilarityThreshold+topK控制检索质量
增强生成ChatClient检索结果自动注入上下文

RAG 技术让通用大模型能够“读懂”你的私有文档,在面对特定领域问题时给出精准答案。

结合 Spring AI 的模块化设计和 Ollama 的本地模型能力,Java 开发者可以轻松构建安全、高效、低成本的本地知识库问答系统。

本文系统地介绍了 Spring AI RAG 的核心概念与完整实现方式。关键要点回顾:

http://www.jsqmd.com/news/815790/

相关文章:

  • IT求职简历投递格式:PDF vs Word,哪个更稳妥?
  • 无锡封窗厂家实力排行 基于品质服务维度实测 - 奔跑123
  • 数字电路状态机设计:从原理到Verilog三段式实现
  • 吹塑制品生产企业选吹塑机厂家的2026选购参考 - 速递信息
  • 上海APP开发口碑实力排行:2024年硬核优选名单与技术路径深度测评
  • HCIA-Datacom 备考攻略:VRP 通用路由平台原理与配置实战详解
  • 书匠策AI:2025年毕业论文还在“裸奔“?这个AI工具让你少熬10个夜
  • 构建标准化Docker镜像:打造高效一致的CI/CD与开发环境
  • GIS数据导出Excel的65535魔咒:除了ArcGIS,还有哪些工具能一键搞定xlsx?
  • 别再硬编码了!用QML动态加载子窗口的3种实战方法(附Python后端代码)
  • 别只看报价:吹塑机厂家真正该比的核心要素 - 速递信息
  • Spring AI基础
  • 日语大语言模型选型指南:从开源生态到商业部署实践
  • 快速分子对接终极指南:使用QVina 2和QVina-W加速药物发现
  • GPU显存健康终极指南:使用memtest_vulkan检测显卡硬件问题
  • 配置管理最佳实践:环境变量、多环境配置与安全加固
  • C#进阶语法**总结
  • 告别网盘限速!LinkSwift浏览器插件一键解锁8大平台全速下载体验
  • AutoDL租服务器训练yolo8x模型
  • 2026年分销商城系统开发平台推荐!深扒技术能力 - FaiscoJeff
  • 打工人怎么领外卖优惠券省钱?2026年这5个认知盲区正在悄悄吃掉你每月327元
  • 别再死记公式了!用NumPy手撸一遍Group Convolution和Depthwise Convolution,彻底搞懂计算量差异
  • Vim/Neovim集成AI编程助手Neural:安装配置与实战指南
  • PocketClaw:iOS原生客户端连接自托管OpenClaw AI助手
  • 小爱音箱智能升级完整指南:5步打造专属AI语音助手
  • 3个核心功能深度解析:如何用rpatool成为Ren‘Py游戏资源管理专家
  • 2026兰州摩托车驾校测评推荐|5家正规机构横向对比,新手拿证不踩坑 - 深度智识库
  • linux系统安装分区教程
  • UniApp打包iOS避坑指南:那些让你抓狂的兼容性问题与解决方案
  • 2026年多层板厂家怎么选?西林木业ENF级板材筑牢健康防线 - 速递信息