函式呼叫

您需要 Ollama 0.2.8 或更新版本。
您需要預先訓練用於工具支援的 模型。通常,這類模型會標記 Tools 標籤。例如 mistralfirefunction-v2llama3.1:70b
目前,Ollama API (0.3.8) 不支援串流模式中的函式呼叫。

您可以向 OllamaChatModel 註冊自訂 Java 函式,並讓部署的 Ollama 模型智慧地選擇輸出 JSON 物件,其中包含呼叫一個或多個已註冊函式的引數。這可讓您將 LLM 功能與外部工具和 API 連接。標記 Tools 標籤的 Ollama 模型(請參閱完整列表)經過訓練,可以偵測何時應呼叫函式,並以符合函式簽章的 JSON 回應。

Ollama API 不會直接呼叫函式;相反地,模型會產生 JSON,您可以使用它在程式碼中呼叫函式,並將結果傳回模型以完成對話。Spring AI 提供彈性且使用者友善的方式來註冊和呼叫自訂函式。一般而言,自訂函式需要提供函式namedescription和函式呼叫signature(以 JSON 結構描述的形式),以讓模型知道函式預期的引數。description 有助於模型了解何時呼叫函式。

作為開發人員,您需要實作一個函式,該函式接受從 AI 模型傳送的函式呼叫引數,並將結果回應給模型。您的函式可以進而調用其他第三方服務以提供結果。

Spring AI 使此過程變得非常簡單,只需定義一個 @Bean 定義,該定義傳回 java.util.Function,並在調用 ChatModel 時提供 bean 名稱作為選項即可。

在底層,Spring 會使用適當的配接器程式碼封裝您的 POJO(函式),以便與 AI 模型互動,從而讓您免於編寫繁瑣的樣板程式碼。底層基礎架構的基礎是 FunctionCallback.java 介面和隨附的 Builder 实用程式類別,以簡化 Java 回呼函式的實作和註冊。

運作方式

假設我們希望 AI 模型回應它沒有的資訊,例如,給定位置的目前溫度。

我們可以向 AI 模型提供關於我們自己的函式的元數據,以便在處理您的提示詞時可以使用這些函式來檢索該資訊。

例如,如果在處理提示詞期間,AI 模型判斷它需要關於給定位置溫度的額外資訊,它將啟動伺服器端產生的請求/回應互動。AI 模型調用用戶端函式。AI 模型以 JSON 形式提供方法調用詳細資訊,而用戶端有責任執行該函式並傳回回應。

模型-用戶端互動在 Spring AI 函式呼叫流程 圖表中說明。

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

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

我們先描述最 POJO 友善的選項。

純 Java 函式

在此方法中,您可以像定義任何其他 Spring 管理的物件一樣,在應用程式內容中定義 @Bean

在內部,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 結構描述盡可能具有描述性,以協助 AI 模型選擇正確的函式來調用。

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
		.inputType(MockWeatherService.Request.class) // (3) function signature
        .build();
	}

}

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

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

在聊天選項中指定函式

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

OllamaChatModel chatModel = ...

UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?");

ChatResponse response = this.chatModel.call(new Prompt(this.userMessage,
		OllamaOptions.builder().withFunction("CurrentWeather").build())); // 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

OllamaFunctionCallbackIT.java 測試示範了此方法。

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

除了自動組態之外,您還可以透過 Prompt 請求動態註冊回呼函式

OllamaChatModel chatModel = ...

UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?");

var promptOptions = OllamaOptions.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));
預設情況下,在提示詞中註冊的函式會在此請求期間啟用。

此方法可讓您根據使用者輸入動態選擇要呼叫的不同函式。

FunctionCallbackInPromptIT.java 整合測試提供了關於如何向 OllamaChatModel 註冊函式並在提示詞請求中使用它的完整範例。

附錄

Spring AI 函式呼叫流程

下圖說明了 OllamaChatModel 函式呼叫的流程

ollama chatmodel function call

OllamaAPI 函式呼叫流程

下圖說明了 Ollama API 的流程

ollama function calling flow

OllamaApiToolFunctionCallIT.java 提供了關於如何使用 Ollama API 函式呼叫的完整範例。