使用 Spring AI 遞迴顧問建立自我改進的 AI 代理

工程 | Christian Tzolov | 2025 年 11 月 4 日 | ...

Spring AI ChatClient 提供了一個流暢的 API,用於與 AI 模型進行通訊。流暢的 API 提供了構建提示的組成部分的方法,這些組成部分作為輸入傳遞給 AI 模型。

顧問是流暢 API 的關鍵組成部分,它們攔截、修改和增強 AI 驅動的互動。其主要優點包括封裝常見的生成式 AI 模式、轉換髮送到和來自大型語言模型 (LLM) 的資料,以及為各種模型和用例提供可移植性。

顧問會處理 ChatClientRequestChatClientResponse 物件。框架會根據顧問的 getOrder() 值(值越低越先執行)將顧問串聯起來,最後一個顧問會呼叫 LLM。

Spring AI 提供內建顧問,用於對話記憶檢索增強生成 (RAG)、日誌記錄和護欄。開發人員還可以建立自定義顧問。

典型顧問結構

public class MyAdvisor implements CallAdvisor {
    
    // 1. Sets the advisor orders
    public int getOrder() { return MY_ADVISOR_ORDER; } 

    // 2. Sets the advisor name
    public String getName() { return MY_ADVISOR_NAME; } 

    public ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {
        // 3. Pre-process the request (modify, validate, log, etc.)
        request = preProcess(request);
        // 4. Call the next advisor in the chain
        ChatClientResponse response = chain.nextCall(request);
        // 5. Post-process the response (modify, validate, log, etc.)
        return postProcess(response);
    }
}

遞迴顧問

從版本 1.1.0-M4 開始,Spring AI 引入了遞迴顧問,支援多次迴圈執行顧問鏈,以支援迭代工作流

  • 工具呼叫迴圈:按順序執行多個工具,每個工具的輸出都會為下一個決策提供資訊
  • 輸出驗證:驗證結構化響應,並在驗證失敗時透過反饋重試
  • 重試邏輯:根據響應質量或外部標準最佳化請求
  • 評估流程:在交付前評估和修改響應
  • 智慧體迴圈:構建自主智慧體,透過分析結果並確定下一步行動來規劃、執行和迭代任務,直到目標實現

傳統的單次執行顧問模式無法充分處理這些場景。

遞迴顧問會多次迴圈執行下游顧問鏈,重複呼叫 LLM,直到滿足某個條件。

CallAdvisorChain.copy(CallAdvisor after) 方法會建立一個只包含下游顧問的子鏈,從而在保持適當的順序和可觀測性的同時實現受控迭代,並防止上游顧問重複執行。

該圖說明了遞迴顧問如何透過允許流程多次迴圈返回顧問鏈來啟用迭代處理。與傳統的單次執行不同,遞迴顧問可以根據響應條件重新訪問先前的顧問,從而在客戶端、顧問和 LLM 之間建立複雜的迭代工作流。

以下是實現遞迴顧問的基本模式

public class MyRecursiveAdvisor implements CallAdvisor {
    
    @Override
    public ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {
        
        // Call the chain initially
        ChatClientResponse response = chain.nextCall(request);
        
        // Check if we need to retry
        while (!isConditionMet(response)) {
            // Modify the request based on the response
            ChatClientRequest modifiedRequest = modifyRequest(request, response);
            
            // Create a sub-chain and recurse
            response = chain.copy(this).nextCall(modifiedRequest);
        }
        
        return response;
    }
}

與非遞迴顧問的關鍵區別在於使用 chain.copy(this).nextCall(...) 而不是 chain.nextCall(...) 來迭代內部鏈的副本。這確保了每次迭代都透過完整的下游鏈,允許其他顧問觀察和攔截,同時保持適當的可觀測性。

⚠️ 重要提示

遞迴顧問是 Spring AI 1.1.0-M4 中一個新的實驗性功能。它們僅支援非流式傳輸,需要仔細的顧問排序,並且由於多次 LLM 呼叫而可能增加成本。

對於維護外部狀態的內部顧問要特別小心——它們可能需要額外關注以在迭代過程中保持正確性。

始終設定終止條件和重試限制,以防止無限迴圈。

考慮您的用例是更受益於遞迴顧問,還是更受益於在您的應用程式程式碼中圍繞 ChatClient 呼叫實現顯式 while 迴圈。

內建遞迴顧問

Spring AI 1.1.0-M4 提供兩個遞迴顧問

ToolCallAdvisor

預設的工具呼叫支援

預設情況下,Spring AI 工具執行在每個 ChatModel 實現內部使用 ToolCallingManager 實現。這意味著工具呼叫請求和響應流程對於 ChatClient 顧問是不透明的,因為它發生在顧問執行鏈之外。

ToolCallAdvisor

ToolCallAdvisor 利用使用者控制的工具執行,在顧問鏈中實現工具呼叫迴圈,提供對工具執行的顯式控制,而不是委託給模型的內部工具執行。

  • 迴圈直到不再有工具呼叫為止
  • 使其他顧問(例如 Advisor ABC)能夠攔截和更改每個工具呼叫請求和響應
  • 支援“直接返回”功能
  • 停用聊天模型的內部工具執行

示例用法

var toolCallAdvisor = ToolCallAdvisor.builder()
    .toolCallingManager(toolCallingManager)
    .advisorOrder(BaseAdvisor.HIGHEST_PRECEDENCE + 300)
    .build();
        
public record Request(String location) {}

var weatherTool = FunctionToolCallback.builder("getWeather", (Request request) -> "15.0°C")
        .description("Gets the weather for a location")
        .inputType(Request.class)
        .build();

var chatClient = ChatClient.builder(chatModel)
    .defaultToolCallbacks(weatherTool) // Tools registration
    .defaultAdvisors(toolCallAdvisor) // Tool Call Execution as Advisor
    .build();

String response = chatClient.prompt()
    .user("What's the weather in Paris and Amsterdam and convert the temperature to Fahrenheit?")
    .call()
    .content();

注意:預設情況下,ToolCallAdvisor 的順序設定為接近 Ordered.HIGHEST_PRECEDENCE,以確保顧問在鏈中首先執行(請求處理時首先執行,響應處理時最後執行),從而允許內部顧問攔截和處理工具請求和響應訊息。

當工具執行具有 returnDirect=true 時,顧問會執行該工具,檢測到該標誌,中斷迴圈,並直接將輸出返回給客戶端,而無需將其傳送給 LLM。當工具的輸出是最終答案時,這可以減少延遲。

💡 演示專案:請參閱 遞迴顧問演示專案中的 ToolCallAdvisor 的完整工作示例。

StructuredOutputValidationAdvisor

StructuredOutputValidationAdvisor 會根據生成的模式驗證結構化 JSON 輸出,並在驗證失敗時重試

  • 從預期的輸出型別自動生成 JSON 模式
  • 根據模式驗證 LLM 響應,並在出現驗證錯誤訊息時重試
  • 可配置的最大重試次數
  • 支援用於 JSON 處理的自定義 ObjectMapper

示例用法

public record ActorFilms(String actor, List<String> movies) {}

var validationAdvisor = StructuredOutputValidationAdvisor.builder()
    .outputType(ActorFilms.class)
    .maxRepeatAttempts(3)
    .build();

var chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(validationAdvisor)
    .build();

ActorFilms actorFilms = chatClient.prompt()
    .user("Generate the filmography for Tom Hanks")
    .call()
    .entity(ActorFilms.class);

當驗證失敗時,顧問會使用錯誤詳細資訊增強提示,並重試,直到達到配置的最大嘗試次數。

注意:預設情況下,StructuredOutputValidationAdvisor 的順序設定為接近 Ordered.LOWEST_PRECEDENCE,以確保顧問在鏈的末尾執行(但在模型呼叫之前),這意味著它在請求處理時最後執行,在響應處理時首先執行。

最佳實踐

  • 設定明確的終止條件:確保迴圈具有明確的退出條件,以防止無限迴圈。
  • 使用適當的順序:將遞迴顧問放置在鏈的早期,以允許其他顧問觀察迭代;或放置在後期,以防止觀察。
  • 提供反饋:在重試請求中新增有關重試原因的資訊,以幫助 LLM 改進。
  • 限制迭代次數:設定最大嘗試次數限制,以防止失控執行。
  • 監控執行:使用 Spring AI 的可觀測性功能來跟蹤迭代次數和效能。
  • 選擇正確的方法:評估遞迴顧問或圍繞 ChatClient 呼叫顯式 while 迴圈是否更適合您的特定用例和架構。

效能考量

遞迴顧問會增加 LLM 呼叫的次數,從而影響:

  • 成本:更多的 API 呼叫會增加成本
  • 延遲:多次迭代會增加處理時間
  • 令牌使用量:每次迭代都會消耗額外的令牌

為了最佳化,請設定合理的重試限制並監控迭代次數。儘可能快取中間結果。

資源

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

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

瞭解更多

獲得支援

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

瞭解更多

即將舉行的活動

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

檢視所有