Gemini 函數呼叫
警告:顯然 Gemini Pro 無法再正確處理函數名稱。平行函數呼叫也已消失。
函數呼叫讓開發人員可以在程式碼中建立函數的描述,然後將該描述傳遞給請求中的語言模型。來自模型的響應包括函數的名稱,該名稱與描述相符,以及調用它時的參數。
您可以向 VertexAiGeminiChatModel
註冊自訂 Java 函數,並讓 Gemini Pro 模型智慧地選擇輸出一個 JSON 物件,其中包含調用一個或多個已註冊函數的參數。這讓您可以將 LLM 功能與外部工具和 API 連接起來。VertexAI Gemini Pro 模型經過訓練,可以偵測何時應該調用函數,並以符合函數簽章的 JSON 回應。
VertexAI Gemini API 不會直接調用函數;相反地,模型會產生 JSON,您可以使用它在程式碼中調用函數,並將結果返回給模型以完成對話。
Spring AI 提供了彈性且使用者友善的方式來註冊和調用自訂函數。一般而言,自訂函數需要提供函數名稱
、描述
和函數調用簽章
(作為 Open API 綱要),以讓模型知道函數預期的參數。描述
有助於模型理解何時調用函數。
作為開發人員,您需要實作一個函數,該函數接收從 AI 模型傳送的函數調用參數,並以結果回應模型。您的函數可以進而調用其他第三方服務以提供結果。
Spring AI 使這一切變得非常容易,只需定義一個 @Bean
定義,該定義返回 java.util.Function
,並在調用 ChatModel
時提供 Bean 名稱作為選項即可。
在底層,Spring 會使用適當的配接器程式碼包裝您的 POJO(函數),以實現與 AI 模型的互動,從而讓您免於編寫繁瑣的樣板程式碼。底層基礎架構的基礎是 FunctionCallback.java 介面和配套的 Builder 实用程式類別,以簡化 Java 回調函數的實作和註冊。
運作方式
假設我們希望 AI 模型回應它沒有的資訊,例如給定位置的目前溫度。
我們可以向 AI 模型提供有關我們自己的函數的元數據,它可以利用這些元數據在處理您的提示詞時檢索該資訊。
例如,如果在處理提示詞期間,AI 模型判斷它需要有關給定位置溫度的額外資訊,它將啟動伺服器端產生的請求/回應互動。AI 模型調用用戶端函數。AI 模型以 JSON 格式提供方法調用詳細資訊,而用戶端有責任執行該函數並傳回回應。
Spring AI 大大簡化了您需要編寫以支援函數調用的程式碼。它為您仲介函數調用對話。您只需將函數定義作為 @Bean
提供,然後在您的提示詞選項中提供函數的 Bean 名稱。您也可以在提示詞中引用多個函數 Bean 名稱。
快速開始
讓我們建立一個聊天機器人,透過調用我們自己的函數來回答問題。為了支援聊天機器人的回應,我們將註冊我們自己的函數,該函數接收位置並傳回該位置的目前天氣。
當對模型的提示詞的回應需要回答諸如 "波士頓的天氣如何?"
之類的問題時,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
透過 VertexAiGeminiChatModel 自動配置,您有多種方法可以在 Spring 上下文中將自訂函數註冊為 Bean。
我們先從描述最 POJO 友善的選項開始。
純 Java 函數
在這種方法中,您可以在應用程式上下文中定義 @Beans
,就像您對任何其他 Spring 管理的物件所做的那樣。
在內部,Spring AI ChatModel
將建立一個 FunctionCallback
實例,該實例新增了透過 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 綱要盡可能具有描述性,以協助 AI 模型選擇正確的函數來調用。
FunctionCallWithFunctionBeanIT.java 示範了這種方法。
FunctionCallback 包裝器
註冊函數的另一種方法是建立 FunctionCallback
實例,如下所示
@Configuration
static class Config {
@Bean
public FunctionCallback weatherFunctionInfo() {
return FunctionCallback.builder()
.description("Get the current weather in a given location") // (2) function description
.schemaType(SchemaType.OPEN_API_SCHEMA) // (3) schema type. Compulsory for Gemini function calling.
.function("CurrentWeather", new MockWeatherService()) // (1) function name and instance
.inputType(MockWeatherService.Request.class) // (4) input type
.build();
}
...
}
它包裝了第三方 MockWeatherService
函數,並將其註冊為 VertexAiGeminiChatModel
的 CurrentWeather
函數。它還提供了描述 (2)、要轉換為 Open API 類型的綱要類型 (3) 和用於產生函數調用的 Open API 綱要的輸入類型 (4)。
預設回應轉換器對 Response 物件進行 JSON 序列化。 |
FunctionCallback 在內部基於 MockWeatherService.Request 類別解析函數調用簽章,並在內部產生函數調用的 Open API 綱要。 |
在聊天選項中指定函數
為了讓模型知道並調用您的 CurrentWeather
函數,您需要在提示詞請求中啟用它
VertexAiGeminiChatModel 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),
VertexAiGeminiChatOptions.builder().withFunction("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 測試示範了這種方法。
使用提示詞選項註冊/調用函數
除了自動配置之外,您還可以使用提示詞請求動態註冊回調函數
VertexAiGeminiChatModel chatModel = ...
UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris? Use Multi-turn function calling.");
var promptOptions = VertexAiGeminiChatOptions.builder()
.withFunctionCallbacks(List.of(FunctionCallback.builder()
.schemaType(SchemaType.OPEN_API_SCHEMA) // IMPORTANT!!
.description("Get the weather in location")
.function("CurrentWeather", new MockWeatherService())
.inputType(MockWeatherService.Request.class)
.build()))
.build();
ChatResponse response = this.chatModel.call(new Prompt(List.of(this.userMessage), this.promptOptions));
對於此請求的持續時間,預設情況下會啟用提示詞中註冊的函數。 |
這種方法允許根據使用者輸入動態選擇要調用的不同函數。
FunctionCallWithPromptFunctionIT.java 整合測試提供了一個完整的範例,說明如何使用 VertexAiGeminiChatModel
註冊函數並在提示詞請求中使用它。