SpringAI框架中的RAG模塊詳解及應用示例
RAG(Retrieval-Augmented Generation)可以通過檢索知識庫,克服大模型訓練完成后參數凍結的局限性,攜帶知識讓大模型根據知識進行回答。SpringAI框架提供了模塊化的API來支持RAG,主要包括QuestionAnswerAdvisor
和RetrievalArgumentAdvisor
。
QuestionAnswerAdvisor
QuestionAnswerAdvisor
主要提供便捷簡單的RAG流功能,只需指定一些簡單的參數即可。例如,假設數據已加載到vectorStore
中,可以通過以下方法進行RAG知識庫檢索:
QuestionAnswerAdvisor questionAnswerAdvisor = QuestionAnswerAdvisor.builder(vectorStore).searchRequest(SearchRequest.builder().similarityThreshold(0.5) // 只返回相似度高于0.5的結果.topK(3) // 只返回前三個結果.filterExpression(newFilterExpressionBuilder().eq("a", "b").build()) // 只檢索 a==b 的文檔.build()).build();ChatClient chatClient = ChatClient.builder(openAiChatModel).defaultOptions(OpenAiChatOptions.builder().model("gpt-3.5-turbo").build()).build();ChatResponse response = chatClient.prompt().advisors(questionAnswerAdvisor).user(u -> u.text("你好")).call().chatResponse();
如果構造advisor時未指定過濾條件,構建請求時也能動態添加:
chatClient.prompt().user(u -> u.text("hello")).advisors(a -> a.param(QuestionAnswerAdvisor.FILTER_EXPRESSION, "a==b")).call().chatResponse();
這里的lambda表達式中的a
是一個AdvisorContext.Builder
實例,param()
用于向AdvisorContext
中添加參數,這些參數在advisor鏈中共享,advisor會自動調用相應方法完成知識庫檢索和拼接。
RetrievalArgumentAdvisor
RetrievalArgumentAdvisor
提供了更豐富的功能,允許程序員定義整個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();
高級RAG流程
檢索前預處理
- CompressionQueryTransformer:對用戶提問進行壓縮,適用于對話歷史較長且當前問題基于上下文的場景。示例:
Query query = Query.builder().text("And what is its second largest city?").history(newUserMessage("What is the capital of Denmark?"),newAssistantMessage("Copenhagen is the capital of Denmark.")).build();QueryTransformer transformer = CompressionQueryTransformer.builder().chatClientBuilder(chatClientBuilder).build();Query transformedQuery = transformer.transform(query);
也可由advisor自動完成:
CompressionQueryTransformer compressionQueryTransformer = CompressionQueryTransformer.builder().chatClientBuilder(ChatClient.builder(openAiChatModel)).build();RetrievalAugmentationAdvisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder().documentRetriever(VectorStoreDocumentRetriever.builder().build()).queryTransformers(compressionQueryTransformer).build();ChatClient.builder(openAiChatModel).build().prompt().user(u -> u.text("中國第二大的城市是哪里")).messages(newUserMessage("中國首都城市是哪里")).messages(newAssistantMessage("北京")).advisors(retrievalAugmentationAdvisor).call().chatResponse();
- RewriteQueryTransformer:使用大語言模型重寫用戶輸入,適合語義模糊或冗長的查詢。
QueryTransformer queryTransformer = RewriteQueryTransformer.builder().chatClientBuilder(chatClientBuilder).build();
- TranslationQueryTransformer:翻譯用戶查詢為目標語言(通常為嵌入模型支持的語言)。
QueryTransformer transformer = TranslationQueryTransformer.builder().chatClientBuilder(chatClientBuilder).targetLanguage("english").build();
- MultiQueryExpander:多查詢擴展器,將原始查詢擴展為多個不同形式的查詢以獲取更多相關結果。
MultiQueryExpander expander = MultiQueryExpander.builder().chatClientBuilder(chatClientBuilder).numberOfQueries(3) // 生成三個查詢.includeOriginal(false) // 不包含原始查詢.build();
檢索
負責從數據庫中檢索最相關文檔。
VectorStoreDocumentRetriever vectorStoreDocumentRetriever = VectorStoreDocumentRetriever.builder().vectorStore(vectorStore).topK(4) // 返回最相關的4個.filterExpression(newFilterExpressionBuilder().eq("a", "b").build()) // 過濾條件:a==b.similarityThreshold(0.4) // 只返回相關度大于0.4的文檔.build();List<Document> documents = vectorStoreDocumentRetriever.retrieve(newQuery("What is the main character of the story?"));
同樣可以交由advisor自動完成并最終展示結果。
檢索后處理
解決文檔內容過多導致的信息丟失、模型上下文長度限制、內容噪聲或重復問題。常見操作包括根據相關性重新排序文檔、刪除無關或重復文檔、壓縮文檔內容以減少干擾。
生成
根據用戶輸入和最終檢索到的文檔生成回答。
ContextualQueryAugmenter
將檢索到的相關內容拼接到用戶提問中,示例:
ContextualQueryAugmenter contextualQueryAugmenter = ContextualQueryAugmenter.builder().allowEmptyContext(false) // 是否允許檢索提供空內容.build();
- 當
.allowEmptyContext(false)
時,若無檢索內容,模型通常不會回答或回答不知道。 - 當
.allowEmptyContext(true)
時,即使檢索內容為空,也會嘗試回答。
ContextualQueryAugmenter
主要做以下工作:
- 檢查檢索結果是否為空
- 非空時,拼接檢索結果字符串并注入提示詞模板變量(如
{{retrievedDocs}}
) - 為空且
.allowEmptyContext(false)
時,設置空變量并指示模型“不要根據已有知識回答” - 為空且
.allowEmptyContext(true)
時,放行不插入上下文內容
以上即為SpringAI框架中RAG模塊的詳細介紹及使用示例,涵蓋從簡單到復雜的多種應用場景,幫助開發者靈活構建基于知識庫的問答系統。