Mistral AI 函數呼叫

您可以向 MistralAiChatModel 註冊自訂 Java 函數,並讓 Mistral AI 模型智慧地選擇輸出 JSON 物件,其中包含呼叫一個或多個已註冊函數的引數。這讓您可以將 LLM 功能與外部工具和 API 連接。 open-mixtral-8x22bmistral-small-latestmistral-large-latest 模型經過訓練,可以偵測何時應呼叫函數,並以符合函數簽章的 JSON 回應。

Mistral AI API 不會直接呼叫函數;相反地,模型會產生 JSON,您可以使用該 JSON 在程式碼中呼叫函數,並將結果傳回模型以完成對話。

Spring AI 提供彈性且使用者友善的方式來註冊和呼叫自訂函數。一般來說,自訂函數需要提供函數名稱描述和函數呼叫簽章 (以 JSON Schema 形式),以讓模型知道函數預期的引數。 描述有助於模型理解何時呼叫函數。

作為開發人員,您需要實作一個函數,該函數會接收從 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

透過 MistralAiChatModel 自動組態,您有多種方法可以在 Spring 內容中將自訂函數註冊為 bean。

我們先描述最適合 POJO 的選項。

純 Java 函數

在此方法中,您在應用程式內容中定義 @Bean,就像定義任何其他 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> currentWeather() {
		return new MockWeatherService();
	}

}

@Description 註解是選用的,並提供函數描述,以協助模型理解何時呼叫函數。 這是設定的重要屬性,有助於 AI 模型確定要調用哪個用戶端函數。

提供函數描述的另一個選項是在 MockWeatherService.Request 上使用 @JsonClassDescription 註解

@Configuration
static class Config {

	@Bean
	public Function<Request, Response> currentWeather() { // bean name as function name
		return new MockWeatherService();
	}

}

@JsonClassDescription("Get the weather in location") // // function description
public record Request(String location, Unit unit) {}

最佳實務是使用資訊註解請求物件,以便該函數產生的 JSON Schema 盡可能具有描述性,以協助 AI 模型選擇要調用的正確函數。

PaymentStatusBeanIT.java 示範了此方法。

Mistral AI PaymentStatusBeanOpenAiIT 使用 OpenAI API 實作相同的函數。 在這方面,Mistral AI 與 OpenAI 幾乎相同。

FunctionCallback 包裝器

註冊函數的另一種方法是建立像這樣的 FunctionCallback

@Configuration
static class Config {

	@Bean
	public FunctionCallback weatherFunctionInfo() {

    return FunctionCallback.builder()
        .description("Get the weather in location") // (2) function description
		.function("CurrentWeather", new MockWeatherService()) // (1) function name and instance
		.inputType(MockWeatherService.Request.class) // (3) function signature
        .build();
	}

}

它包裝了第三方 MockWeatherService 函數,並將其註冊為具有 MistralAiChatModelCurrentWeather 函數。 它還提供描述 (2) 和函數簽章 (3),以讓模型知道函數預期的引數。

預設情況下,回應轉換器會執行回應物件的 JSON 序列化。
FunctionCallback 在內部根據 MockWeatherService.Request 類別解析函數呼叫簽章。

在聊天選項中指定函數

為了讓模型知道並呼叫您的 CurrentWeather 函數,您需要在提示請求中啟用它

MistralAiChatModel chatModel = ...

UserMessage userMessage = new UserMessage("What's the weather like in Paris?");

ChatResponse response = this.chatModel.call(new Prompt(this.userMessage,
		MistralAiChatOptions.builder().withFunction("CurrentWeather").build())); // Enable the function

logger.info("Response: {}", response);

上述使用者問題將觸發 3 次對 CurrentWeather 函數的呼叫 (每個城市一次),最終回應將如下所示

使用提示選項註冊/呼叫函數

除了自動組態之外,您還可以動態地使用您的 Prompt 請求註冊回呼函數

MistralAiChatModel chatModel = ...

UserMessage userMessage = new UserMessage("What's the weather like in Paris?");

var promptOptions = MistralAiChatOptions.builder()
	.withFunctionCallbacks(List.of(FunctionCallback.builder()
        .description("Get the weather in location") // (2) function description
		.function("CurrentWeather", new MockWeatherService()) // (1) function name and instance
		.inputType(MockWeatherService.Request.class) // (3) function signature
        .build())) // function code
	.build();

ChatResponse response = this.chatModel.call(new Prompt(this.userMessage, this.promptOptions));
預設情況下,提示中註冊的函數在此請求的持續時間內啟用。

此方法允許根據使用者輸入動態選擇要呼叫的不同函數。

PaymentStatusPromptIT.java 整合測試提供了一個完整的範例,說明如何在 MistralAiChatModel 中註冊函數並在提示請求中使用它。

附錄

Mistral AI API 函數呼叫流程

下圖說明了 Mistral AI 低階 API 的函數呼叫流程,如 函數呼叫所示

mistral ai function calling flow

PaymentStatusFunctionCallingIT.java 提供了一個完整的範例,說明如何使用 Mistral AI API 函數呼叫。 它基於 Mistral AI 函數呼叫教學課程