检索增强生成 (RAG)
检索增强生成 (RAG) 是一种有助于克服大型语言模型在长篇内容、事实准确性和上下文感知方面的局限性的技术。
Spring AI 通过提供模块化架构来支持 RAG,该架构允许您自己构建自定义 RAG 流或使用 API 使用开箱即用的 RAG 流Advisor。
顾问
Spring AI 使用 API 为常见的 RAG 流提供开箱即用的支持Advisor。
要使用QuestionAnswerAdvisor
或VectorStoreChatMemoryAdvisor
,您需要将spring-ai-advisors-vector-store
依赖项添加到您的项目中:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>
问答顾问
向量数据库存储的是 AI 模型无法感知的数据。当用户问题发送给 AI 模型时,它QuestionAnswerAdvisor会查询向量数据库,查找与用户问题相关的文档。
来自向量数据库的响应被附加到用户文本中,为 AI 模型生成响应提供上下文。
假设您已经将数据加载到 中,则可以通过向VectorStore提供一个实例来执行检索增强生成 (RAG) 。QuestionAnswerAdvisorChatClient
ChatResponse response = ChatClient.builder(chatModel)
.build().prompt()
.advisors(new QuestionAnswerAdvisor(vectorStore))
.user(userText)
.call()
.chatResponse();
在此示例中,QuestionAnswerAdvisor 将对 Vector 数据库中的所有文档执行相似性搜索。为了限制搜索的文档类型,SearchRequest 采用了一个可移植的 SQL 类过滤表达式 VectorStores。
此过滤表达式可以在创建时进行配置QuestionAnswerAdvisor,因此将始终适用于所有ChatClient请求,也可以在运行时为每个请求提供。
以下是 QuestionAnswerAdvisor 如何创建阈值实例0.8并返回最佳6结果。
var qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
.searchRequest(SearchRequest.builder().similarityThreshold(0.8d).topK(6).build())
.build();
动态过滤表达式
SearchRequest 使用顾问上下文参数在运行时更新过滤表达式 FILTER_EXPRESSION:
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(QuestionAnswerAdvisor.builder(vectorStore)
.searchRequest(SearchRequest.builder().build())
.build())
.build();
// Update filter expression at runtime
String content = this.chatClient.prompt()
.user("Please answer my question XYZ")
.advisors(a -> a.param(QuestionAnswerAdvisor.FILTER_EXPRESSION, "type == 'Spring'"))
.call()
.content();
该FILTER_EXPRESSION
参数允许您根据提供的表达式动态过滤搜索结果。
自定义模板
使用 QuestionAnswerAdvisor 默认模板,通过检索到的文档来扩充用户问题。您可以PromptTemplate通过 builder 方法提供自己的对象来自定义此行为.promptTemplate()。
此处提供PromptTemplate的 自定义了顾问程序如何将检索到的上下文与用户查询合并。这与TemplateRenderer在ChatClient本身上配置 (使用)不同,后者会影响顾问程序运行前.templateRenderer()初始用户/系统提示内容的渲染。有关客户端级模板渲染的更多详细信息, 请参阅ChatClient 提示模板。
自定义PromptTemplate可以使用任何TemplateRenderer实现(默认情况下,它使用StPromptTemplate基于StringTemplate引擎的实现)。重要的要求是模板必须包含以下两个占位符:
query用于接收用户问题的占位符。
用于接收检索到的上下文的占位符question_answer_context。
PromptTemplate customPromptTemplate = PromptTemplate.builder()
.renderer(StTemplateRenderer.builder().startDelimiterToken(‘<’).endDelimiterToken(‘>’).build())
.template(“””
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();
String question = "Where does the adventure of Anacletus and Birba take place?";
QuestionAnswerAdvisor qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
.promptTemplate(customPromptTemplate)
.build();
String response = ChatClient.builder(chatModel).build()
.prompt(question)
.advisors(qaAdvisor)
.call()
.content();
该QuestionAnswerAdvisor.Builder.userTextAdvise()方法已被弃用,取而代之的是使用.promptTemplate()更灵活的定制方法。
检索增强顾问
Spring AI 包含一个RAG 模块库,您可以使用它来构建自己的 RAG 流。它RetrievalAugmentationAdvisor基于Advisor模块化架构,为最常见的 RAG 流提供开箱即用的实现。
要使用RetrievalAugmentationAdvisor,您需要将spring-ai-rag依赖项添加到您的项目中:
String answer = chatClient.prompt()
.advisors(retrievalAugmentationAdvisor)
.user(question)
.call()
.content();
默认情况下,RetrievalAugmentationAdvisor不允许检索到的上下文为空。如果出现这种情况,它会指示模型不回答用户查询。您可以按如下方式允许空上下文。
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
.documentRetriever(VectorStoreDocumentRetriever.builder()
.similarityThreshold(0.50)
.vectorStore(vectorStore)
.build())
.queryAugmenter(ContextualQueryAugmenter.builder()
.allowEmptyContext(true)
.build())
.build();
String answer = chatClient.prompt()
.advisors(retrievalAugmentationAdvisor)
.user(question)
.call()
.content();
接受VectorStoreDocumentRetriever一个FilterExpression基于元数据过滤搜索结果的参数。您可以在实例化时VectorStoreDocumentRetriever或在每次请求运行时使用FILTER_EXPRESSION顾问上下文参数提供一个参数。
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
.documentRetriever(VectorStoreDocumentRetriever.builder()
.similarityThreshold(0.50)
.vectorStore(vectorStore)
.build())
.build();
String answer = chatClient.prompt()
.advisors(retrievalAugmentationAdvisor)
.advisors(a -> a.param(VectorStoreDocumentRetriever.FILTER_EXPRESSION, “type == ‘Spring’”))
.user(question)
.call()
.content();
有关更多信息,请参阅VectorStoreDocumentRetriever 。
高级 RAG
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
.queryTransformers(RewriteQueryTransformer.builder()
.chatClientBuilder(chatClientBuilder.build().mutate())
.build())
.documentRetriever(VectorStoreDocumentRetriever.builder()
.similarityThreshold(0.50)
.vectorStore(vectorStore)
.build())
.build();
String answer = chatClient.prompt()
.advisors(retrievalAugmentationAdvisor)
.user(question)
.call()
.content();
您还可以使用该DocumentPostProcessorAPI 对检索到的文档进行后处理,然后再将其传递给模型。例如,您可以使用此类接口根据检索到的文档与查询的相关性对其进行重新排序,移除不相关或冗余的文档,或者压缩每个文档的内容以减少噪音和冗余。
模块
Spring AI 实现了一种模块化 RAG 架构,其灵感来自于论文“模块化 RAG:将 RAG 系统转变为类似乐高的可重构框架”中详述的模块化概念。
预检索
预检索模块负责处理用户查询以获得最佳的检索结果。
查询转换
用于转换输入查询以使其更有效地执行检索任务的组件,解决诸如格式不正确的查询、歧义的术语、复杂的词汇或不受支持的语言等挑战。
使用 时QueryTransformer,建议将 设置ChatClient.Builder为较低的温度(例如 0.0),以确保结果更确定、更准确,从而提高检索质量。大多数聊天模型的默认温度通常过高,无法实现最佳查询转换,从而导致检索效率降低。
压缩查询转换器
ACompressionQueryTransformer使用大型语言模型将对话历史和后续查询压缩为独立查询,以捕捉对话的本质。
当对话历史很长并且后续查询与对话上下文相关时,此转换器很有用。
Query query = Query.builder()
.text(“And what is its second largest city?”)
.history(new UserMessage(“What is the capital of Denmark?”),
new AssistantMessage(“Copenhagen is the capital of Denmark.”))
.build();
QueryTransformer queryTransformer = CompressionQueryTransformer.builder()
.chatClientBuilder(chatClientBuilder)
.build();
Query transformedQuery = queryTransformer.transform(query);
promptTemplate()可以通过构建器中可用的方法自定义此组件使用的提示。
重写查询转换器
ARewriteQueryTransformer使用大型语言模型重写用户查询,以便在查询目标系统(例如向量存储或网络搜索引擎)时提供更好的结果。
当用户查询冗长、模糊或包含可能影响搜索结果质量的不相关信息时,此转换器很有用。
Query query = new Query(“I’m studying machine learning. What is an LLM?”);
QueryTransformer queryTransformer = RewriteQueryTransformer.builder()
.chatClientBuilder(chatClientBuilder)
.build();
Query transformedQuery = queryTransformer.transform(query);
promptTemplate()可以通过构建器中可用的方法自定义此组件使用的提示。
翻译查询转换器
ATranslationQueryTransformer使用大型语言模型将查询翻译成用于生成文档嵌入的嵌入模型所支持的目标语言。如果查询已经是目标语言,则返回原样结果。如果查询的语言未知,则也返回原样结果。
当嵌入模型在特定语言上进行训练并且用户查询使用不同的语言时,此转换器很有用。
Query query = new Query(“Hvad er Danmarks hovedstad?”);
QueryTransformer queryTransformer = TranslationQueryTransformer.builder()
.chatClientBuilder(chatClientBuilder)
.targetLanguage(“english”)
.build();
Query transformedQuery = queryTransformer.transform(query);
promptTemplate()可以通过构建器中可用的方法自定义此组件使用的提示。
查询扩展
用于将输入查询扩展为查询列表的组件,通过提供替代查询公式或将复杂问题分解为更简单的子查询来解决诸如格式不良的查询等挑战。
多查询扩展器
AMultiQueryExpander使用大型语言模型将查询扩展为多个语义不同的变体以捕捉不同的视角,有助于检索额外的上下文信息并增加找到相关结果的机会。
MultiQueryExpander queryExpander = MultiQueryExpander.builder()
.chatClientBuilder(chatClientBuilder)
.numberOfQueries(3)
.build();
List
默认情况下,MultiQueryExpander扩展查询列表中会包含原始查询。您可以通过includeOriginal构建器中的方法禁用此行为。
MultiQueryExpander queryExpander = MultiQueryExpander.builder()
.chatClientBuilder(chatClientBuilder)
.includeOriginal(false)
.build();
promptTemplate()可以通过构建器中可用的方法自定义此组件使用的提示。
检索
检索模块负责查询向量存储等数据系统并检索最相关的文档。
文档搜索
负责Documents从底层数据源(例如搜索引擎、向量存储、数据库或知识图)检索的组件。
VectorStoreDocumentRetriever
AVectorStoreDocumentRetriever从向量存储中检索与输入查询语义相似的文档。它支持基于元数据、相似度阈值和 Top-k 结果的过滤。
DocumentRetriever retriever = VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.similarityThreshold(0.73)
.topK(5)
.filterExpression(new FilterExpressionBuilder()
.eq(“genre”, “fairytale”)
.build())
.build();
List
过滤表达式可以是静态的,也可以是动态的。对于动态过滤表达式,您可以传递Supplier。
DocumentRetriever retriever = VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.filterExpression(() -> new FilterExpressionBuilder()
.eq(“tenant”, TenantContextHolder.getTenantIdentifier())
.build())
.build();
List
Query您还可以通过API 使用参数提供特定于请求的过滤表达式FILTER_EXPRESSION。如果同时提供了特定于请求和特定于检索器的过滤表达式,则特定于请求的过滤表达式优先。
Query query = Query.builder()
.text(“Who is Anacletus?”)
.context(Map.of(VectorStoreDocumentRetriever.FILTER_EXPRESSION, “location == ‘Whispering Woods’”))
.build();
List
文档连接
该组件用于将基于多个查询从多个数据源检索到的文档合并为一个文档集合。作为合并过程的一部分,它还可以处理重复文档和互惠排名策略。
ConcatenationDocumentJoiner
将基于多个查询从多个数据源检索到的文档ConcatenationDocumentJoiner连接起来,形成一个文档集合。如果出现重复文档,则保留第一个出现的文档。每个文档的得分保持不变。
Map<Query, List<List
DocumentJoiner documentJoiner = new ConcatenationDocumentJoiner();
List
检索后
后检索模块负责处理检索到的文档以获得最佳的生成结果。
文档后期处理
用于根据查询对检索到的文档进行后处理的组件,解决了诸如中间丢失、模型的上下文长度限制等挑战,以及需要减少检索到的信息中的噪音和冗余。
例如,它可以根据文档与查询的相关性对文档进行排名,删除不相关或冗余的文档,或者压缩每个文档的内容以减少噪音和冗余。
一代
生成模块负责根据用户查询和检索到的文档生成最终响应。
查询增强
用于使用附加数据扩充输入查询的组件,有助于为大型语言模型提供回答用户查询所需的必要上下文。
上下文查询增强器
ContextualQueryAugmenter使用所提供文档内容中的上下文数据来增强用户查询。
QueryAugmenter queryAugmenter = ContextualQueryAugmenter.builder().build();
默认情况下,ContextualQueryAugmenter不允许检索到的上下文为空。当这种情况发生时,它会指示模型不回答用户查询。
您可以启用该allowEmptyContext选项,以允许模型即使在检索到的上下文为空时也能生成响应。
QueryAugmenter queryAugmenter = ContextualQueryAugmenter.builder()
.allowEmptyContext(true)
.build();
可以通过构建器中提供的promptTemplate()和方法自定义此组件使用的提示。emptyContextPromptTemplate()
最后编辑:Jeebiz 更新时间:2025-08-08 00:47