|
最新快照版本请使用Spring AI 1.1.0! |
检索增强生成
检索增强生成(RAG)是一种有助于克服大型语言模型局限性的技术 在长篇内容、事实准确性和语境意识方面有困难。
Spring AI 支持 RAG,提供模块化架构,允许你自己构建自定义 RAG 流程
或使用开箱即用的RAG流,使用顾问应用程序接口。
| 在概念部分了解更多关于检索增强生成的信息。 |
顾问
Spring AI 开箱即用支持 RAG 流程,使用顾问应用程序接口。
使用问答顾问或向量存储聊天记忆顾问,你需要添加Spring-AI-Advisors-Vector-store对项目的依赖性:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>
问答顾问
向量数据库存储的是AI模型未知的数据。当用户问题发送给AI模型时,问答顾问查询向量数据库中与用户问题相关的文档。
向量数据库的响应会附加到用户文本中,为AI模型生成响应提供上下文。
假设你已经把数据加载到一个VectorStore,你可以通过提供 的实例来执行检索增强生成(RAG)问答顾问前往聊天客户端.
ChatResponse response = ChatClient.builder(chatModel)
.build().prompt()
.advisors(new QuestionAnswerAdvisor(vectorStore))
.user(userText)
.call()
.chatResponse();
在这个例子中,问答顾问将对向量数据库中的所有文档进行相似性搜索。为了限制被搜索的文档类型,搜索请求需要一个类似 SQL 的过滤表达式,并且可以跨所有向量存储器.
该滤波表达式可在创建问答顾问因此,将始终适用于所有人聊天客户端也可以在运行时为每个请求提供。
以下是如何创建一个 的实例问答顾问其中阈值为0.8并归还顶部6结果。
var qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
.searchRequest(SearchRequest.builder().similarityThreshold(0.8d).topK(6).build())
.build();
动态滤波表达式
更新搜索请求运行时使用以下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参数允许你根据提供的表达式动态过滤搜索结果。
自定义模板
这问答顾问使用默认模板来补充检索到的文档。你可以通过提供自己的行为来定制这种行为提示模板对象通过.promptTemplate()建造者方法。
这提示模板此处提供的 可自定义顾问如何将检索到的上下文与用户查询合并。这与配置模板渲染器在聊天客户端本身(使用.templateRenderer()),这会影响顾问运行前初始用户/系统提示内容的渲染。有关客户端模板渲染的更多细节,请参见ChatClient提示模板。 |
习俗提示模板可以使用任何模板渲染器实现(默认情况下,它使用StPrompt模板基于StringTemplate引擎)。重要要求是模板必须包含以下两个占位符:
-
一个
查询占位符以接收用户提问。 -
一个
question_answer_context占位符以接收检索到的上下文。
PromptTemplate customPromptTemplate = PromptTemplate.builder()
.renderer(StTemplateRenderer.builder().startDelimiterToken('<').endDelimiterToken('>').build())
.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();
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();
这问答顾问.构建者.用户文本建议()方法被弃用,转而采用.promptTemplate()为了更灵活的定制。 |
检索增强顾问
Spring AI 包含一个 RAG 模块库,你可以用来构建自己的 RAG 流程。 这检索增强顾问是顾问为最常见的RAG流程提供开箱即用的实现,基于模块化架构。
使用检索增强顾问,你需要添加春艾拉格对项目的依赖性:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-rag</artifactId>
</dependency>
顺序RAG流
天真的RAG
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
.documentRetriever(VectorStoreDocumentRetriever.builder()
.similarityThreshold(0.50)
.vectorStore(vectorStore)
.build())
.build();
String answer = chatClient.prompt()
.advisors(retrievalAugmentationAdvisor)
.user(question)
.call()
.content();
默认情况下,检索增强顾问不允许检索的上下文为空。当发生这种情况时,它指示模型不要回答用户查询。你可以允许上下文为空,具体如下。
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接受滤网表达式根据元数据过滤搜索结果。你可以在实例化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();
你也可以使用文档后处理API用于在提交给模型前对检索到的文档进行后处理。例如,你可以利用这样的接口根据检索到的文档与查询的相关性对其进行重新排序,删除无关或冗余的文档,或压缩每份文档的内容以减少噪声和冗余。
模块
Spring AI 实现了受论文中模块化概念启发的模块化 RAG 架构:“模块化 RAG:将 RAG 系统转化为类乐高可重构框架”。
回收前
预检索模块负责处理用户查询,以实现最佳检索结果。
查询变换
一个用于转换输入查询以使其在检索任务中更有效的组件,解决挑战例如查询结构不佳、歧义词汇、复杂词汇或无支持语言。
当使用QueryTransformer建议配置ChatClient.Builder采用较低温度(例如0.0)以确保结果更确定性和准确,从而提升检索质量。大多数聊天模型的默认温度通常过高,无法实现最优查询转换,导致检索效果降低。 |
压缩查询变换器
一个压缩查询变换器使用大型语言模型将对话历史和后续查询压缩压缩成一个独立查询,捕捉对话的本质。
当对话历史较长且后续查询与对话上下文相关时,该变换器非常有用。与对话上下文相关。
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()方法可在构建器中提供。
RewriteQueryTransformer
一个RewriteQueryTransformer使用大型语言模型重写用户查询,以便在查询目标系统(如向量存储或网络搜索引擎)时提供更好的结果。
当用户查询冗长、含糊或包含无关信息时,该变换器非常有用这些信息可能影响搜索结果的质量。
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()方法可在构建器中提供。
TranslationQueryTransformer
一个TranslationQueryTransformer使用大型语言模型将查询翻译成支持的目标语言由用于生成文档嵌入的嵌入模型支持。如果查询已经在目标语言中,则返回时保持不变。如果查询语言未知,查询也返回时保持不变。
当嵌入模型训练特定语言和用户查询时,该变换器非常有用 是另一种语言。
Query query = new Query("Hvad er Danmarks hovedstad?");
QueryTransformer queryTransformer = TranslationQueryTransformer.builder()
.chatClientBuilder(chatClientBuilder)
.targetLanguage("english")
.build();
Query transformedQuery = queryTransformer.transform(query);
该组件所用的提示可以通过promptTemplate()方法可在构建器中提供。
查询扩展
一个组件,用于将输入查询扩展为查询列表,解决诸如查询形式不佳等挑战 通过提供替代的查询表述,或将复杂问题拆解为更简单的子查询。
多查询扩展器
一个多查询扩展器使用大型语言模型将查询扩展为多种语义多样化的变体
捕捉不同视角,有助于获取更多上下文信息并提高中奖概率
寻找相关结果。
MultiQueryExpander queryExpander = MultiQueryExpander.builder()
.chatClientBuilder(chatClientBuilder)
.numberOfQueries(3)
.build();
List<Query> queries = queryExpander.expand(new Query("How to run a Spring Boot app?"));
默认情况下,多查询扩展器将原始查询纳入扩展查询列表。你可以禁用这种行为
通过原文包括架构器中的方法。
MultiQueryExpander queryExpander = MultiQueryExpander.builder()
.chatClientBuilder(chatClientBuilder)
.includeOriginal(false)
.build();
该组件所用的提示可以通过promptTemplate()方法可在构建器中提供。
检索
检索模块负责查询数据系统(如向量存储)并检索最相关的文档。
文档检索
负责检索的组件文件从底层数据源,如搜索引擎、向量存储器,
数据库,或者知识图谱。
VectorStoreDocumentRetriever
一个VectorStoreDocumentRetriever从向量存储中检索与输入语义相似的文档
查询。它支持基于元数据、相似度阈值和 top k 结果进行过滤。
DocumentRetriever retriever = VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.similarityThreshold(0.73)
.topK(5)
.filterExpression(new FilterExpressionBuilder()
.eq("genre", "fairytale")
.build())
.build();
List<Document> documents = retriever.retrieve(new Query("What is the main character of the story?"));
滤波表达式可以是静态的,也可以是动态的。对于动态滤波表达式,你可以通过提供商.
DocumentRetriever retriever = VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.filterExpression(() -> new FilterExpressionBuilder()
.eq("tenant", TenantContextHolder.getTenantIdentifier())
.build())
.build();
List<Document> documents = retriever.retrieve(new Query("What are the KPIs for the next semester?"));
你也可以通过以下方式提供针对请求的过滤表达式查询API,使用FILTER_EXPRESSION参数。
如果同时提供了请求专用和检索器专用的过滤表达式,则请求专用过滤表达式优先。
Query query = Query.builder()
.text("Who is Anacletus?")
.context(Map.of(VectorStoreDocumentRetriever.FILTER_EXPRESSION, "location == 'Whispering Woods'"))
.build();
List<Document> retrievedDocuments = documentRetriever.retrieve(query);
文档连接
一个组件,用于将基于多次查询和多个数据源检索的文档组合成 一堆文件。作为连接过程的一部分,它还能处理重复文件和互惠 排名策略。
ConcatenationDocumentJoiner
一个ConcatenationDocumentJoiner结合基于多次查询和多个数据源检索的文档
通过将它们串联成一个单一的文档集合。如果出现重复文件,则保留第一次出现的记录。
每份文件的评分保持原样。
Map<Query, List<List<Document>>> documentsForQuery = ...
DocumentJoiner documentJoiner = new ConcatenationDocumentJoiner();
List<Document> documents = documentJoiner.join(documentsForQuery);
生成
生成模块负责根据用户查询和检索到的文档生成最终响应。
查询增强
一个用于补充输入查询的组件,用于提供大型语言模型 并附上回答用户问题所需的上下文。
ContextualQueryAugmenter
这ContextualQueryAugmenter通过提供文档内容的上下文数据补充用户查询。
QueryAugmenter queryAugmenter = ContextualQueryAugmenter.builder().build();
默认情况下,ContextualQueryAugmenter不允许检索的上下文为空。当那种情况发生时,
它指示模型不要回答用户的查询。
你可以启用允许空上下文允许模型即使检索到的上下文为空,也能生成响应。
QueryAugmenter queryAugmenter = ContextualQueryAugmenter.builder()
.allowEmptyContext(true)
.build();
该组件使用的提示可以通过promptTemplate()和emptyContextPromptTemplate()方法
在构建器中查看。