為您的 AI 應用程式提供動力:Spring AI Advisors

工程 | Christian Tzolov | 2024 年 10 月 2 日 | ...

在快速發展的人工智慧世界中,開發人員不斷尋求增強其 AI 應用程式的方法。Spring AI,一個用於構建 AI 驅動型應用程式的 Java 框架,引入了一項強大的功能:Spring AI Advisors

Advisors 可以為您的 AI 應用程式提供強大的支援,使其更具模組化、可移植性,並且更易於維護。

如果閱讀文章不方便,您可以收聽這個**實驗性**播客,它**由 AI 生成**,內容來自部落格文章。

什麼是 Spring AI Advisors?

Spring AI Advisor 的核心是元件,它們會攔截並可能修改 AI 應用程式中聊天補全請求和響應的流程。系統中的關鍵參與者是 AroundAdvisor,它允許開發人員動態地轉換或利用這些互動中的資訊。

使用 Advisor 的主要好處包括:

  1. 封裝重複性任務:將常見的 GenAI 模式打包成可重用單元。
  2. 轉換:增強傳送到語言模型 (LLM) 的資料,並格式化傳送回客戶端的響應。
  3. 可移植性:建立可重用的轉換元件,這些元件可以跨各種模型和用例工作。

Advisor 如何工作

Advisor 系統作為一個鏈式結構執行,序列中的每個 Advisor 都有機會處理傳入的請求和傳出的響應。下面是簡化的流程:

spring-ai-advisors-flow

  1. 從使用者的提示建立一個 AdvisedRequest,以及一個空的 advisor-context
  2. 鏈中的每個 Advisor 都會處理請求,可能會修改它,然後將執行轉發給鏈中的下一個 Advisor。或者,它也可以選擇透過不呼叫下一個實體來阻止請求。
  3. 最後一個 Advisor 將請求傳送到 Chat Model。
  4. Chat Model 的響應被作為 AdvisedResponse 傳遞迴 Advisor 鏈,它結合了原始的 ChatResponse 和鏈的輸入路徑中的 advise context。
  5. 每個 Advisor 都可以處理或修改響應。
  6. 從最終的 AdvisedResponse 中增強的 ChatResponse 被返回給客戶端。

使用 Advisor

Spring AI 提供了幾個預構建的 Advisor 來處理常見場景和 Gen AI 模式。

使用 ChatClient API,您可以在管道中註冊所需的 Advisor。

var chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(
        new MessageChatMemoryAdvisor(chatMemory), // chat-memory advisor
        new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()) // RAG advisor
    )
    .build();

String response = chatClient.prompt()
    // Set chat memory parameters at runtime
    .advisors(advisor -> advisor.param("chat_memory_conversation_id", "678")
            .param("chat_memory_response_size", 100))
    .user(userText)
    .call()
	.content();

實現您自己的 Advisor

Advisor API 包含用於非流式處理的 CallAroundAdvisorCallAroundAdvisorChain,以及用於流式處理場景的 StreamAroundAdvisorStreamAroundAdvisorChain。它還包括 AdvisedRequest 來表示未封鎖的 Prompt 請求資料,以及 AdvisedResponse 來表示聊天補全資料。AdvisedRequestAdvisedResponse 都有一個 advise-context 欄位,用於在 Advisor 鏈中共享狀態。

簡單日誌 Advisor

建立自定義 Advisor 非常簡單。讓我們實現一個簡單的日誌 Advisor 來演示這個過程。

public class SimpleLoggerAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {
    private static final Logger logger = LoggerFactory.getLogger(SimpleLoggerAdvisor.class);

    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {
        logger.debug("BEFORE: {}", advisedRequest);
        AdvisedResponse advisedResponse = chain.nextAroundCall(advisedRequest);
        logger.debug("AFTER: {}", advisedResponse);
        return advisedResponse;
    }

    @Override
    public Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {
        logger.debug("BEFORE: {}", advisedRequest);
        Flux<AdvisedResponse> advisedResponses = chain.nextAroundStream(advisedRequest);
        return new MessageAggregator().aggregateAdvisedResponse(advisedResponses,
                advisedResponse -> logger.debug("AFTER: {}", advisedResponse));
    }
}

此 Advisor 會在請求被處理之前記錄請求,並在收到響應之後記錄響應,從而為 AI 互動過程提供有價值的見解。

aggregateAdvisedResponse(...) 工具將 AdviseResponse 塊聚合為單個 AdvisedResponse,返回原始流並接受一個 Consumer 回撥以獲取完成的結果。它保留了原始內容和上下文。

重讀 (Re2) Advisor

讓我們基於 Re-Reading (Re2) 技術實現一個更高階的 Advisor,該技術受此 論文 啟發,可以提高大型語言模型的推理能力。

public class ReReadingAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {
    private static final String DEFAULT_USER_TEXT_ADVISE = """
        {re2_input_query}
        Read the question again: {re2_input_query}
        """;

    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }

    @Override
    public int getOrder() {
        return 0;
    }

    private AdvisedRequest before(AdvisedRequest advisedRequest) {

        String inputQuery = advisedRequest.userText(); //original user query

        Map<String, Object> params = new HashMap<>(advisedRequest.userParams());        
        params.put("re2_input_query", inputQuery);

        return AdvisedRequest.from(advisedRequest)
                .withUserText(DEFAULT_USER_TEXT_ADVISE)
                .withUserParams(params)
                .build();
    }

    @Override
    public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {
        return chain.nextAroundCall(before(advisedRequest));
    }

    @Override
    public Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {
        return chain.nextAroundStream(before(advisedRequest));
    }
}

此 Advisor 修改輸入查詢,以包含一個“重讀”步驟,可能可以提高 AI 模型對問題的理解和推理能力。

高階主題

Spring AI 的高階主題涵蓋了 Advisor 管理的重要方面,包括*順序控制*、*狀態共享*和*流式處理能力*。Advisor 的執行順序由 getOrder() 方法決定。Advisor 之間的狀態共享透過共享的 advise-context 物件實現,從而支援複雜的多個 Advisor 場景。該系統同時支援流式處理和非流式處理 Advisor,允許處理完整的請求和響應,或使用響應式程式設計概念處理連續的資料流。

控制 Advisor 順序

Advisor 在鏈中的順序至關重要,它由 getOrder() 方法決定。具有較低順序值的 Advisor 會先執行。由於 Advisor 鏈是一個棧,鏈中的第一個 Advisor 最後處理請求,最先處理響應。如果您想確保某個 Advisor 最後執行,請將其順序設定為接近 Ordered.LOWEST_PRECEDENCE 的值;反之,要先執行,請將其順序設定為接近 Ordered.HIGHEST_PRECEDENCE 的值。如果您有多個具有相同順序值的 Advisor,則執行順序不確定。

使用 AdvisorContext 進行狀態共享

AdvisedRequestAdvisedResponse 都共享一個 advise-context 物件。您可以使用 advise-context 在鏈中的 Advisor 之間共享狀態,並構建涉及多個 Advisor 的更復雜的處理場景。

流式處理與非流式處理

Spring AI 支援流式處理和非流式處理 Advisor。非流式處理 Advisor 處理完整的請求和響應,而流式處理 Advisor 則使用響應式程式設計概念(例如,Flux 用於響應)來處理連續的流。

對於流式處理 Advisor,需要注意的是,單個 AdvisedResponse 例項僅代表整個 Flux<AdvisedResponse> 響應的一部分。相比之下,對於非流式處理 Advisor,AdvisedResponse 包含了完整的響應。

最佳實踐

  1. 保持 Advisor 專注於特定任務,以提高模組化程度。
  2. 在必要時,使用 advise-context 在 Advisor 之間共享狀態。
  3. 實現 Advisor 的流式處理和非流式處理版本,以獲得最大的靈活性。
  4. 仔細考慮 Advisor 在鏈中的順序,以確保正確的資料流。

結論

Spring AI Advisor 提供了一種強大而靈活的方式來增強您的 AI 應用程式。透過利用此 API,您可以建立更復雜、可重用且易於維護的 AI 元件。無論您是實現自定義邏輯、管理對話歷史還是改進模型推理,Advisor 都提供了清晰有效的解決方案。

我們鼓勵您在專案中嘗試使用 Spring AI Advisor,並與社群分享您的自定義實現。可能性是無限的,您的創新可能有助於塑造 AI 應用程式開發的未來!

祝您編碼愉快,願您的 AI 應用程式越來越智慧、響應迅速!

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有