前言:在最近發布的 Spring AI 1.0.0.M6 版本中,其中一個重大變化是 Function Calling 被廢棄,被 Tool Calling 取代。Tool Calling工具調用(也稱為函數調用)是AI應用中的常見模式,允許模型通過一組API或工具進行交互,從而增強其能力
1、Tool Calling 工具調用 簡介
Spring AI 中的工具調用使 AI 模型能夠與外部工具和服務交互,從而增強其功能。Tool Calling 工具調用允許 AI 模型執行外部函數、訪問外部服務、執行復雜操作和與現有系統集成
主要使用的場景:
-
信息檢索(Information Retrieval)。
此類工具可用于從外部資源(如數據庫、Web服務、文件系統或者 WEB 搜索引擎)檢索信息。
目標:增強模型的知識,使其能夠回答其其它方式不能回答的問題。例如,工具用于檢索給定的位置天氣、檢索最新的新聞文章或者查詢數據庫。
-
采取行動(Taking Action)
此類工具可用于在軟件系統中的執行操作(如發送電子郵件、在數據庫中創建新記錄、提交表單或觸發工作流),自動執行原本需要人工干預或者顯式編程的任務。例如,與機器人交互生成待辦事項、自動填寫網頁表單、聊天機器人預訂機票、創建會議安排等。
注意: 通常我們認為工具調用是模型功能,但實際上由客戶端應用程序提供工具調用邏輯,模型只能請求工具調用并提供輸入參數,模型本身不執行工具調用。
2、為什么廢棄 Function Calling?
-
更好的改進和擴展 Spring AI 中工具調用功能。
-
新的 API 從 functions 改為 tools 術語,與行業術語保持一致性。
除以上兩點之外,在設計上也做了一定的優化,主要體現在;
-
新的 API 在工具的定義和實現之間提供了更好的分離
-
工具定義可以在不同的實現中重復使用
-
在使用上,簡化了構造器模式,更好的支持基于方法的工具,并改進了錯誤處理。
兩者在本質上概念上沒有區別,都是為增強大模型的能力,在底層的實現原理上也是一致的,只是對外提供的概念稍微變動一下。官方建議盡快將 Function Calling 相關使用的 API 遷移到 Tool Calling API。Function Calling API 在后續的版本中會被移除。基本上是將原API?中的Function 替換為 Tool,再者就是為了方便方法的使用做了一些優化。
3、Tool Calling 主要操作流程和源代碼
(1)主要操作流程
定義工具 :當需要向模型提供工具時,需在聊天請求中包含其定義。每個工具定義包含名稱、描述及輸入參數的模式(schema)。
模型發起調用 :當模型決定調用工具時,會返回包含工具名稱和符合預定義模式的輸入參數的響應。
應用執行工具 :應用程序負責根據工具名稱識別并執行對應工具,傳入提供的輸入參數。
處理結果 :工具調用的結果由應用程序處理。
返回結果至模型 :應用程序將工具調用結果返回給模型。
生成最終響應 :模型結合工具調用結果作為上下文生成最終響應
(2)源碼
?
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Tool {/*** 指定工具的名稱,如果不指定則默認使用方法名稱。* 注意:方法名稱的唯一性*/String name() default "";/*** 工具的描述,模型可以使用它來了解何時以及如何調用工具,如果不指定則使用方法名。* 強烈建議:詳細,清晰的描述工具的功能,這對于工具的使用至關重要,直接影響大模型的* 使用效果。*/String description() default "";/*** 指定工具執行的結果是直接返回,還是要發給大模型,默認發送給大模型*/boolean returnDirect() default false;/*** 指定工具執行結果轉換器。Spring AI 內置一個默認轉換為String,如果有特殊業務* 需求可自行實現。*/Class<? extends ToolCallResultConverter> resultConverter() default DefaultToolCallResultConverter.class;}?
4、Tool Calling 快速入門?
讓我們通過一個示例了解如何在Spring AI中使用工具調用。我們將實現兩個簡單工具:一個用于信息檢索,另一個用于執行操作。信息檢索工具用于獲取用戶時區的當前日期和時間,操作工具用于設置指定時間的鬧鐘。
(1)信息檢索
AI模型無法訪問實時信息。任何涉及當前日期、天氣預報等實時信息的問題,模型都無法直接回答。但我們可以提供能夠檢索此類信息的工具,并讓模型在需要實時數據時調用這些工具。
首先在DateTimeTools類中實現一個獲取用戶時區當前日期時間的工具。該工具不需要參數,通過Spring框架的LocaleContextHolder獲取用戶時區。工具方法使用@Tool注解,并添加詳細描述幫助模型理解調用時機。
package com.hs.demo.tool;import org.springframework.ai.tool.annotation.Tool;
import org.springframework.context.i18n.LocaleContextHolder;import java.time.LocalDateTime;public class DateTimeTools {@Tool(description = "獲取用戶時區的當前日期和時間")String getCurrentDateTime() {return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();}}
接下來將工具提供給模型,本例使用ChatClient與模型交互,通過tools()方法傳入DateTimeTools實例。當模型需要實時時間信息時,會自動請求調用該工具。ChatClient會執行工具調用并將結果返回給模型,模型結合結果生成最終響應。
輸出示例:
明天是2025-05-30。
如果直接提問但不提供工具,模型將返回:
我無法訪問實時信息,請提供當前日期以便計算明天的日期。
這證明模型在缺乏工具時無法自主獲取實時數據
?(2)? 執行操作
AI模型可以生成實現目標的計劃(如制定瑞士旅行計劃),但無法直接執行。此時需要工具來落實模型生成的計劃。
我們將定義第二個工具,用于在特定時間設置鬧鐘。在第一個工具的基礎上,先獲取當前時間,在當前時間的基礎上設置鬧鐘。在現有DateTimeTools類中新增設置鬧鐘的工具。該工具接收ISO-8601格式的時間參數,向控制臺輸出鬧鐘設置信息。同樣使用@Tool注解并添加詳細描述
class DateTimeTools {@Tool(description = "獲取用戶時區的當前日期和時間")String getCurrentDateTime() {return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();}@Tool(description = "為指定ISO-8601時間設置用戶鬧鐘")void setAlarm(String time) {LocalDateTime alarmTime = LocalDateTime.parse(time, DateTimeFormatter.ISO_DATE_TIME);System.out.println("鬧鐘已設置為 " + alarmTime);}
}
通過ChatClient同時提供兩個工具。當請求"10分鐘后設置鬧鐘"時,模型會先調用getCurrentDateTime獲取當前時間,計算目標時間后調用setAlarm工具。ChatClient自動處理工具調用請求并返回結果,模型最終生成響應
ChatModel chatModel = ...String response = ChatClient.create(chatModel).prompt("能設置10分鐘后的鬧鐘嗎?").tools(new DateTimeTools()).call().content();System.out.println(response);
應用日志將顯示正確設置的鬧鐘時間,驗證工具調用流程
參考鏈接:
Spring AI 框架在升級,Function Calling 廢棄,被 Tool Calling 取代
Spring AI之工具調用_springai-CSDN博客