版本声明:本文基于 Spring AI 1.0.0 版本编写。由于 Spring AI 目前仍处于活跃开发阶段,API 和组件可能在后续版本中发生变化,请注意及时关注官方文档更新以保持兼容性。
大纲
- 前言
- 什么是 Retrieval Augmented Generation(RAG)?
- Spring AI 对 RAG 的支持概述
- 先决条件与环境准备
- 项目依赖配置
- 核心组件详解
- 6.1
VectorStore
:向量数据库 - 6.2
QuestionAnswerAdvisor
:基础问答型 RAG - 6.3
RetrievalAugmentationAdvisor
:模块化 RAG 流程
- 6.1
- 高级功能
- 7.1 自定义 Prompt 模板
- 7.2 动态过滤搜索结果
- 7.3 查询转换(Query Transformation)
- 7.4 文档后处理(Document Post-Processing)
- 示例代码整合
- 结语
前言
随着大语言模型(LLM)应用日益普及,如何结合私有知识库来增强模型的回答能力,成为了构建智能应用的关键。Retrieval Augmented Generation(RAG) 是一种非常有效的解决方案。
Spring AI 提供了对 RAG 的强大支持,通过模块化设计和开箱即用的组件,开发者可以快速构建出高效的 RAG 应用。本文将带你从零开始,深入理解并实践 Spring AI 中的 RAG 技术。
什么是 Retrieval Augmented Generation(RAG)?
RAG 是一种结合信息检索(Retrieval)和生成式模型(Generation)的技术。其基本流程如下:
- 用户输入问题;
- 系统从外部知识库中检索最相关的文档;
- 将这些文档作为上下文附加到用户问题中;
- 将组合后的上下文发送给语言模型进行回答。
这种技术能有效解决以下问题:
- LLM 缺乏最新或特定领域的知识;
- 回答缺乏事实依据;
- 上下文感知能力弱。
Spring AI 对 RAG 的支持概述
Spring AI 提供了两种主要方式实现 RAG:
组件 | 说明 |
---|---|
QuestionAnswerAdvisor |
适用于简单问答场景的开箱即用组件 |
RetrievalAugmentationAdvisor |
支持模块化架构,构建复杂可扩展的 RAG 流程 |
此外,Spring AI 还提供了统一的 VectorStore
接口,支持多种向量数据库(如 FAISS、Pinecone、Weaviate、InMemoryVectorStore 等),便于灵活切换底层存储引擎。
先决条件与环境准备
在开始之前,请确保你具备以下条件:
- Java 17 或以上版本
- Maven 或 Gradle 构建工具
- Spring Boot 3.x
- 已安装的向量数据库或使用内存版
InMemoryVectorStore
- OpenAI API Key(或其他 LLM 提供商密钥)
- 基础的 Spring Boot 开发经验
项目依赖配置(Maven 示例)
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI 核心依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<!-- RAG 模块支持 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>
</dependencies>
核心组件详解
6.1 VectorStore:向量数据库
VectorStore
是 Spring AI 提供的接口,用于存储和检索嵌入向量数据。常见实现包括:
InMemoryVectorStore
(开发测试用)PineconeVectorStore
WeaviateVectorStore
FaissVectorStore
示例:初始化 InMemoryVectorStore
@Bean
public VectorStore vectorStore(EmbeddingClient embeddingClient) {
return new InMemoryVectorStore(embeddingClient);
}
示例:加载数据到 VectorStore
@Bean
public CommandLineRunner loadData(VectorStore vectorStore) {
return args -> {
List<Document> documents = List.of(
new Document("Copenhagen is the capital of Denmark.", Map.of("type", "fact")),
new Document("The second largest city in Denmark is Aarhus.", Map.of("type", "fact"))
);
vectorStore.add(documents);
};
}
6.2 QuestionAnswerAdvisor:基础问答型 RAG
这是最简单的 RAG 实现方式,适合用于问答类任务。
示例代码:
var qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
.searchRequest(SearchRequest.builder().similarityThreshold(0.7).topK(3).build())
.build();
String answer = ChatClient.builder(chatModel)
.build()
.prompt()
.advisors(qaAdvisor)
.user("What is the second largest city in Denmark?")
.call()
.content();
6.3 RetrievalAugmentationAdvisor:模块化 RAG 流程
该组件允许你构建模块化的 RAG 流程,支持查询转换、文档检索、后处理等步骤。
Naive RAG 示例:
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
.documentRetriever(VectorStoreDocumentRetriever.builder()
.similarityThreshold(0.50)
.vectorStore(vectorStore)
.build())
.build();
String answer = chatClient.prompt()
.advisors(retrievalAugmentationAdvisor)
.user("What is the second largest city in Denmark?")
.call()
.content();
高级 RAG 示例(带查询转换):
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
.queryTransformers(RewriteQueryTransformer.builder()
.chatClientBuilder(ChatClient.builder(chatModel))
.build())
.documentRetriever(VectorStoreDocumentRetriever.builder()
.similarityThreshold(0.50)
.vectorStore(vectorStore)
.build())
.build();
高级功能详解
7.1 自定义 Prompt 模板
你可以自定义模板控制模型如何使用检索到的内容。
PromptTemplate customPromptTemplate = PromptTemplate.builder()
.template("""
<query>
Context information is below.
---------------------
<question_answer_context>
---------------------
Given the context information and no prior knowledge, answer the query.
Follow these rules:
1. If the answer is not in the context, just say that you don't know.
2. Avoid statements like 'Based on the context...' or 'The provided information...'.
""")
.build();
var qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
.promptTemplate(customPromptTemplate)
.build();
7.2 动态过滤搜索结果
你可以在运行时动态指定过滤表达式。
String answer = chatClient.prompt()
.user("Where does the adventure of Anacletus and Birba take place?")
.advisors(a -> a.param(QuestionAnswerAdvisor.FILTER_EXPRESSION, "type == 'fiction'"))
.advisors(qaAdvisor)
.call()
.content();
7.3 查询转换(Query Transformation)
用于优化原始查询以提升检索效果。
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
.queryTransformers(RewriteQueryTransformer.builder()
.chatClientBuilder(ChatClient.builder(chatModel))
.build())
.documentRetriever(...)
.build();
7.4 文档后处理(Document Post Processing)
你可以实现 DocumentPostProcessor
接口来压缩或排序文档:
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
.documentRetriever(...)
.documentPostProcessors(new ReRankingPostProcessor()) // 自定义类
.build();
示例代码整合(完整服务类)
@Service
public class RagService {
private final ChatModel chatModel;
private final VectorStore vectorStore;
public RagService(ChatModel chatModel, VectorStore vectorStore) {
this.chatModel = chatModel;
this.vectorStore = vectorStore;
}
public String answerQuestion(String userText) {
var promptTemplate = PromptTemplate.builder()
.template("""
<query>
Context information is below.
---------------------
<question_answer_context>
---------------------
Given the context information and no prior knowledge, answer the query.
Follow these rules:
1. If the answer is not in the context, just say that you don't know.
2. Avoid statements like 'Based on the context...' or 'The provided information...'.
""")
.build();
var advisor = QuestionAnswerAdvisor.builder(vectorStore)
.promptTemplate(promptTemplate)
.searchRequest(SearchRequest.builder().similarityThreshold(0.7).topK(3).build())
.build();
return ChatClient.builder(chatModel)
.build()
.prompt()
.advisors(advisor)
.user(userText)
.call()
.content();
}
}
结语
通过本文的详细介绍与代码演示,相信你已经掌握了如何在 Spring Boot 中使用 Spring AI 实现 Retrieval Augmented Generation(RAG)。
Spring AI 的 RAG 支持不仅简化了开发流程,还提供了强大的灵活性和可扩展性,非常适合用于:
- 企业级知识问答系统
- 智能客服
- 内容辅助生成
- 私有领域知识增强型 LLM 应用
随着 Spring AI 社区的发展,未来还将提供更多模块化组件和优化策略,帮助开发者更高效地构建 AI 应用。
提示:如果你使用的是 OpenAI,记得设置合适的温度值(如 0.0)以保证查询转换和检索的稳定性。