Azure OpenAI Function Calling (已棄用)
函式呼叫 (Function calling) 允許開發者在其程式碼中建立函式描述,然後將該描述作為請求的一部分傳遞給語言模型。模型響應包含與描述匹配的函式名稱及其呼叫時所需的引數。
您可以向 AzureOpenAiChatModel
註冊自定義 Java 函式,模型將智慧地選擇輸出一個包含呼叫一個或多個已註冊函式所需引數的 JSON 物件。這允許您將 LLM 的能力與外部工具和 API 連線起來。Azure 模型經過訓練,能夠檢測何時應該呼叫函式並響應符合函式簽名的 JSON。
Azure OpenAI API 不會直接呼叫函式;相反,模型會生成 JSON,您可以在程式碼中使用該 JSON 呼叫函式,並將結果返回給模型以完成對話。
Spring AI 提供了靈活且使用者友好的方式來註冊和呼叫自定義函式。通常,自定義函式需要提供函式 name
、description
和函式呼叫 signature
(以 JSON Schema 形式),以告知模型函式期望哪些引數。description
有助於模型理解何時呼叫該函式。
作為開發者,您需要實現一個函式來接收 AI 模型傳送的函式呼叫引數,並將結果返回給模型。您的函式可以進一步呼叫其他第三方服務來提供結果。
Spring AI 使這一切變得非常簡單,只需定義一個返回 java.util.Function
的 @Bean
定義,並在呼叫 ChatModel
時將 bean 名稱作為選項提供即可。
在底層,Spring 使用適當的介面卡程式碼包裝您的 POJO(即函式),使其能夠與 AI 模型進行互動,從而節省您編寫繁瑣的樣板程式碼。底層基礎設施的基礎是 ToolCallback.java
介面以及配套的 Builder 工具類,用於簡化 Java 回撥函式的實現和註冊。
工作原理
假設我們希望 AI 模型能夠回應它本身不具備的資訊,例如給定位置的當前溫度。
我們可以向 AI 模型提供有關我們自定義函式的元資料,模型在處理您的 prompt 時可以使用這些元資料來檢索資訊。
例如,如果在處理 prompt 的過程中,AI 模型確定需要有關給定位置溫度的附加資訊,它將發起一個由伺服器端生成的請求/響應互動。AI 模型會呼叫客戶端函式。AI 模型以 JSON 格式提供方法呼叫詳細資訊,客戶端負責執行該函式並返回響應。
Spring AI 大大簡化了支援函式呼叫所需的程式碼編寫工作。它為您代理函式呼叫互動過程。您只需將函式定義提供為 @Bean
,然後在 prompt 選項中提供該函式的 bean 名稱即可。您還可以在 prompt 中引用多個函式 bean 名稱。
快速入門
讓我們建立一個透過呼叫我們自己的函式來回答問題的聊天機器人。為了支援聊天機器人的響應,我們將註冊一個自定義函式,該函式接收一個位置並返回該位置的當前天氣。
當模型響應 prompt 需要回答諸如“波士頓天氣如何?”這樣的問題時,AI 模型將呼叫客戶端,並提供位置值作為引數傳遞給函式。這種類似 RPC 的資料以 JSON 格式傳遞。
我們的函式可以呼叫基於 SaaS 的天氣服務 API,並將天氣響應返回給模型以完成對話。在本例中,我們將使用一個名為 MockWeatherService
的簡單實現,它對不同位置的溫度進行硬編碼。
以下 MockWeatherService.java
表示天氣服務 API
public class MockWeatherService implements Function<Request, Response> {
public enum Unit { C, F }
public record Request(String location, Unit unit) {}
public record Response(double temp, Unit unit) {}
public Response apply(Request request) {
return new Response(30.0, Unit.C);
}
}
將函式註冊為 Bean
使用 AzureOpenAiChatModelAuto-Configuration
,您可以透過多種方式將自定義函式註冊為 Spring 上下文中的 bean。
我們從描述最 POJO 友好的選項開始。
普通 Java 函式
在這種方法中,您像定義其他任何 Spring 管理的物件一樣,在應用程式上下文中定義 @Beans
。
在內部,Spring AI ChatModel
將建立一個 ToolCallback
例項,該例項添加了透過 AI 模型呼叫其邏輯。@Bean
的名稱作為 ChatOption
傳遞。
@Configuration
static class Config {
@Bean
@Description("Get the weather in location") // function description
public Function<MockWeatherService.Request, MockWeatherService.Response> weatherFunction1() {
return new MockWeatherService();
}
...
}
@Description
註解是可選的,它提供一個函式描述 (2),幫助模型理解何時呼叫該函式。這是一個重要的屬性,用於幫助 AI 模型確定要呼叫哪個客戶端函式。
提供函式描述的另一種選擇是在 MockWeatherService.Request
上使用 @JsonClassDescription
註解來提供函式描述
@Configuration
static class Config {
@Bean
public Function<Request, Response> currentWeather3() { // (1) bean name as function name.
return new MockWeatherService();
}
...
}
@JsonClassDescription("Get the weather in location") // (2) function description
public record Request(String location, Unit unit) {}
最佳實踐是使用資訊註解請求物件,以便該函式生成的 JSON schema 儘可能具有描述性,從而幫助 AI 模型選擇正確的函式進行呼叫。
FunctionCallWithFunctionBeanIT.java
演示了這種方法。
ToolCallback 包裝器
註冊函式的另一種方法是建立一個 ToolCallback
例項,如下所示
@Configuration
static class Config {
@Bean
public FunctionToolCallback weatherFunctionInfo() {
return FunctionToolCallback.builder("CurrentWeather", new MockWeatherService()) // (1) function name
.description("Get the current weather in a given location") // (2) function description
.inputType(MockWeatherService.Request.class) // (3) function input type
.build();
}
...
}
它包裝了第三方 MockWeatherService
函式,並將其註冊為 AzureAiChatModel
的 CurrentWeather
函式,並提供了描述 (2)。
預設的響應轉換器會對 Response 物件進行 JSON 序列化。 |
FunctionToolCallback 內部基於 MockWeatherService.Request 類解析函式呼叫簽名,並在內部為函式呼叫生成 JSON schema。 |
在聊天選項中指定函式
要讓模型知道並呼叫您的 CurrentWeather
函式,您需要在 prompt 請求中啟用它
AzureOpenAiChatModel chatModel = ...
UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?");
ChatResponse response = this.chatModel.call(new Prompt(List.of(this.userMessage),
AzureOpenAiChatOptions.builder().tools("CurrentWeather").build())); // (1) Enable the function
logger.info("Response: {}", response);
上面的使用者問題將觸發對 CurrentWeather
函式的 3 次呼叫(每個城市一次),最終響應將類似於這樣
Here is the current weather for the requested cities: - San Francisco, CA: 30.0°C - Tokyo, Japan: 10.0°C - Paris, France: 15.0°C
FunctionCallWithFunctionWrapperIT.java
測試演示了這種方法。
使用 Prompt 選項註冊/呼叫函式
除了自動配置之外,您還可以透過 prompt 請求動態地註冊回撥函式
AzureOpenAiChatModel chatModel = ...
UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris? Use Multi-turn function calling.");
var promptOptions = AzureOpenAiChatOptions.builder()
.toolCallbacks(List.of(FunctionToolCallback.builder("CurrentWeather", new MockWeatherService()) // (1) function name and instance
.description("Get the current weather in a given location") // (2) function description
.inputType(MockWeatherService.Request.class) // (3) function input type
.build()))
.build();
ChatResponse response = this.chatModel.call(new Prompt(List.of(this.userMessage), this.promptOptions));
在 prompt 中註冊的函式在此請求期間預設啟用。 |
這種方法允許根據使用者輸入動態選擇要呼叫的不同函式。
FunctionCallWithPromptFunctionIT.java
整合測試提供了一個完整示例,演示瞭如何向 AzureOpenAiChatModel
註冊函式並在 prompt 請求中使用它。