iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0
生成式 AI

使用 Spring AI 打造企業 RAG 知識庫系列 第 19

Day19 - Spring AI的鏈式增強器

  • 分享至 

  • xImage
  •  

AOP無所不在

https://ithelp.ithome.com.tw/upload/images/20240819/20161290PpCeC08JCZ.jpg
Spring 框架有兩個很重要的觀念,一個是 IoC,另一個則是 AOP,只是 AOP 大多整合進應用中,開發人員直接撰寫 AOP 的機會越來越少,很多開發人員甚至都忘了還有這種功能
AOP 的基本概念就是可以攔截指定的方法並且增強方法的功能,且無需修改到主要的業務代碼,使業務與非業務處理邏輯分離
例如 @Transactional 標註,只要元件的方法上增加 @Transactional 標註,Spring 會自動在方法中進行 Open、Commit,並且在業務處理失敗時,執行 Rollback。
另一個常見的應用是 log,使用 AOP 可以在不更動原程式的情況下在執行前後加上 log 紀錄

Spring AI提供的Advisor(增強器)

在 Spring AOP 中 Advisor(增強器) 的作用就是找到切入點對應的方法,並在定義的時機執行 Advice(增強方法),還記得 Day15 最後提到的 .advisors() 嗎?這正是要放入 Advisor 的地方,Spring AI 提供了 RequestResponseAdvisor 介面,只要實作就能在 ChatModel 執行 call() 或是 stream() 的前後調用 Advisor,目前 Spring AI 提供的實作類別有以下四個
https://ithelp.ithome.com.tw/upload/images/20240819/201612900g7q0iHGAj.png

  • MessageChatMemoryAdvisor: 將訊息送出前加入 ChatMemory,之後將所有 ChatMemory 資料以 List 方式送給 AI 處理
  • PromptChatMemoryAdvisor: 將訊息送出前加入 ChatMemory,之後將所有 ChatMemory 訊息加入 SystemMassage,最後將 UserMessage 與 SystemMessage 一同送給 AI 處理
  • VectorStoreChatMemoryAdvisor: 前面兩個都是處理短期聊天資訊,一旦系統關閉就會失去所有聊天內容,而此類別則可在訊息送出前加入向量資料庫,並從向量資料庫中取出相似聊天內容送給 AI 處理,讓聊天訊息可以長久保存
  • QuestionAnswerAdvisor: 此類別即是 RAG 的調用實作,凱文大叔會在後面章節詳細說明

程式碼實作

今天先來實作短期記憶,凱文大叔將昨天的 Service 進行改寫,原本手動加入 InMemoryChatMemory 以及取得歷史訊息的部分不用自己動手了

@RequiredArgsConstructor
@Service
public class ChatService {
	private final ChatClient chatClient;
	private final ChatMemory chatMemory = new InMemoryChatMemory();
	
	public String chat(String chatId, String userMessage) {	   
		return this.chatClient.prompt()
		.advisors(new MessageChatMemoryAdvisor(chatMemory, chatId, 30))
		.user(userMessage)
        .call().content()
	}
}

MessageChatMemoryAdvisorPromptChatMemoryAdvisor 兩者效果基本差不多,大家可以自行測試結果是否有差異,放入的參數分別如下
chatMemory:用來存對話訊息的 ChatMemory
chatId:區分對話的代號
30:送給 AI 的最近歷史聊天數量

為了驗證結果,特別加入log,分別在發送訊息前以及收到訊息後印出

@RequiredArgsConstructor
@Service
@Slf4j
public class ChatService {
	private final ChatClient chatClient;
	private final ChatMemory chatMemory = new InMemoryChatMemory();
	
	public String chat(String chatId, String userMessage) {	   
		log.info("Chat ID:{} User Message:{}",chatId,userMessage); //Request Message
		String assistantMessage = this.chatClient.prompt()
		.advisors(new MessageChatMemoryAdvisor(chatMemory, chatId, 30))
		.user(userMessage)
        .call().content();
		log.info("Chat ID:{} Assistant Message:{}",chatId,assistantMessage); //Response Message
		return assistantMessage;
	}
}

驗收成果

https://ithelp.ithome.com.tw/upload/images/20240819/20161290WBgQmjFsi1.png

可以看出效果跟昨天一樣,MessageChatMemoryAdvisor 與 PromptChatMemoryAdvisor 只差在歷史訊息送出的方式,大家可以挑一種喜歡的來使用即可

回顧

今天學到了甚麼?

  • AOP 基本概念
  • Spring AI 提供的 Advisor 程式
  • 如何在 ChatClient 設定 Advisor 程式,完成短期記憶

程式看起來與昨天差別不大,不過 .advisors() 是可放入多個 Advisor 程式的,除了 Spring AI 提供的以外,開發人員也可以自行實作 RequestResponseAdvisor,明天我們就將 log 改寫成 Advisor 讓大家熟悉Advisor 鏈的寫法

Source Code:

程式碼下載: https://github.com/kevintsai1202/SpringBoot-AI-Day19.git


認識凱文大叔

凱文大叔使用 Java 開發程式超過 20 年,對於 Java 生態非常熟悉,曾使用反射機制開發 ETL 框架,對 Spring 背後的原理非常清楚,目前以 Spring Boot 作為後端開發框架,前端使用 React 搭配 Ant Design
下班之餘在 Amazing Talker 擔任程式語言講師,並獲得學員的一致好評

最近剛成立一個粉絲專頁-凱文大叔教你寫程式 歡迎大家多追蹤,我會不定期分享實用的知識以及程式開發技巧

想討論 Spring 的 Java 開發人員可以加入 FB 討論區 Spring Boot Developer Taiwan

我是凱文大叔,歡迎一起加入學習程式的行列


上一篇
Day18 - Spring AI 官方記憶
下一篇
Day20 - 自行開發Spring AI插件
系列文
使用 Spring AI 打造企業 RAG 知識庫21
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言