Ollama 関数呼び出し
関数呼び出し機能を使用するには Ollama 0.2.8 以降が必要であり、ストリーミングモードで使用するには Ollama 0.4.6 以降が必要です。 |
ツールをサポートするには、モデル (英語) を事前にトレーニングする必要があります。通常、このようなモデルには Tools タグが付けられます。 |
OllamaChatModel
を使用してカスタム Java 関数を登録し、Ollama デプロイモデルで、登録された関数の 1 つまたは複数を呼び出すための引数を含む JSON オブジェクトをインテリジェントに出力するように選択できます。これにより、LLM 機能を外部ツールや API に接続できます。Tools
ラベルでタグ付けされた Ollama モデル ( 完全なリスト (英語) を参照) は、関数を呼び出すタイミングを検出し、関数シグネチャーに準拠した JSON で応答するようにトレーニングされています。
Ollama API は関数を直接呼び出すのではなく、モデルが JSON を生成します。この JSON を使用してコード内で関数を呼び出し、結果をモデルに返して会話を完了します。Spring AI は、カスタム関数を登録して呼び出すための柔軟でユーザーフレンドリーな方法を提供します。一般に、カスタム関数は関数 name
、description
、関数呼び出し signature
(JSON スキーマとして) を提供して、関数が期待する引数をモデルに知らせる必要があります。description
は、モデルが関数を呼び出すタイミングを理解できます。
開発者は、AI モデルから送信された関数呼び出し引数を受け取り、その結果をモデルに返す関数を実装する必要があります。関数は、結果を提供するために他のサードパーティサービスを呼び出します。
Spring AI を使用すると、java.util.Function
を返す @Bean
定義を定義し、ChatModel
を呼び出すときにオプションとして Bean 名を指定するだけで、これが簡単になります。
内部的には、Spring は POJO (関数) を適切なアダプターコードでラップし、AI モデルとのやり取りを可能にするため、面倒な定型コードを記述する必要がなくなります。基盤となるインフラストラクチャの基礎は、FunctionCallback.java [GitHub] (英語) インターフェースと、Java コールバック関数の実装と登録を簡素化するコンパニオンビルダーユーティリティクラスです。
使い方
たとえば、特定の場所の現在の気温など、AI モデルが持っていない情報を応答するようにしたいとします。
AI モデルに、プロンプトを処理するときにその情報を取得するために使用できる独自の関数に関するメタデータを提供できます。
たとえば、プロンプトの処理中に、AI モデルが特定の場所の温度に関する追加情報が必要であると判断した場合、サーバー側で生成されたリクエスト / レスポンスのインタラクションを開始します。AI モデルはクライアント側の関数を呼び出します。AI モデルはメソッド呼び出しの詳細を JSON として提供し、その関数を実行してレスポンスを返すのはクライアントの責任です。
モデルとクライアントの対話は、Spring AI 関数呼び出しフロー図に示されています。
Spring AI は、関数呼び出しをサポートするために記述する必要があるコードを大幅に簡素化します。関数呼び出しの会話を仲介します。関数定義を @Bean
として提供し、プロンプトオプションで関数の Bean 名を提供するだけです。プロンプトで複数の関数 Bean 名を参照することもできます。
クイックスタート
独自の関数を呼び出して質問に答えるチャットボットを作成してみましょう。チャットボットのレスポンスをサポートするために、場所を取得してその場所の現在の天気を返す独自の関数を登録します。
モデルが "What ’ s the weather like in Boston?"
などの質問に答える必要がある場合、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
は、AI モデルを介して呼び出されるロジックを追加する FunctionCallback
のインスタンスを作成します。@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) {}
AI モデルが呼び出す正しい関数を選択できるように、その関数の生成された JSON スキーマが可能な限り説明的になるように、リクエストオブジェクトに情報をアノテーション付けすることがベストプラクティスです。
FunctionCallback
関数を登録する別の方法は、次のように FunctionCallback
を作成することです。
@Configuration
static class Config {
@Bean
public FunctionCallback weatherFunctionInfo() {
return FunctionCallback.builder()
.function("CurrentWeather", new MockWeatherService()) // (1) function name
.description("Get the weather in location") // (2) function description
.inputType(MockWeatherService.Request.class) // (3) function signature
.build();
}
}
サードパーティの MockWeatherService
関数をラップし、OllamaChatModel
とともに CurrentWeather
関数として登録します。また、関数が期待する引数をモデルに知らせるための説明 (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().function("CurrentWeather").build())); // Enable the function
logger.info("Response: {}", response);
上記のユーザーの質問により、CurrentWeather
関数が 3 回呼び出され (各都市に 1 回ずつ)、最終的なレスポンスは次のようになります。
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 [GitHub] (英語) テストでは、このアプローチをデモしています。
プロンプトオプションを使用した関数の登録 / 呼び出し
自動構成に加えて、Prompt
リクエストでコールバック関数を動的に登録できます。
OllamaChatModel chatModel = ...
UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?");
var promptOptions = OllamaOptions.builder()
.functionCallbacks(List.of(FunctionCallback.builder()
.function("CurrentWeather", new MockWeatherService()) // (1) function name and instance
.description("Get the weather in location") // (2) function description
.inputType(MockWeatherService.Request.class) // (3) function signature
.build())) // function code
.build();
ChatResponse response = this.chatModel.call(new Prompt(this.userMessage, this.promptOptions));
プロンプト内に登録された機能は、このリクエストの間、デフォルトで有効になります。 |
このアプローチにより、ユーザー入力に基づいて呼び出すさまざまな関数を動的に選択できます。
FunctionCallbackInPromptIT.java [GitHub] (英語) 統合テストは、関数を OllamaChatModel
に登録し、それをプロンプトリクエストで使用する方法の完全な例を提供します。
付録:
OllamaAPI 関数呼び出しフロー
次の図は、Ollama API のフローを示しています。
OllamaApiToolFunctionCallIT.java [GitHub] (英語) は、Ollama API 関数呼び出しの使用方法の完全な例を提供します。