関数呼び出し API
このページでは、関数呼び出し API の以前のバージョンについて説明します。このバージョンは非推奨となり、次のリリースで削除される予定です。現在のバージョンはツール呼び出しで入手できます。詳細については、移行ガイドを参照してください。 |
AI モデルに機能サポートを統合すると、モデルがクライアント側機能の実行をリクエストできるようになり、必要な情報にアクセスしたり、必要に応じてタスクを動的に実行したりできるようになります。
Spring AI は現在、次の AI モデルのツール / 関数呼び出しをサポートしています。
Anthropic Claude: Anthropic Claude ツール / 関数呼び出しを参照してください。
Azure OpenAI: Azure OpenAI ツール / 関数呼び出しを参照してください。
Amazon Bedrock Converse: Amazon Bedrock 逆ツール / 関数呼び出しを参照してください。
Google VertexAI Gemini: Vertex AI Gemini ツール / 関数呼び出しを参照してください。
Groq: Groq ツール / 関数呼び出しを参照してください。
Mistral AI: Mistral AI ツール / 関数呼び出しを参照してください。
Ollama: Ollama ツール / 関数呼び出しを参照してください
OpenAI: OpenAI ツール / 関数呼び出しを参照してください。
ChatClient
にカスタム Java 関数を登録し、AI モデルが登録された関数の 1 つまたは複数を呼び出すための引数を含む JSON オブジェクトをインテリジェントに出力するように選択できます。これにより、LLM 機能を外部ツールや API に接続できます。AI モデルは、関数を呼び出すタイミングを検出し、関数シグネチャーに準拠した JSON で応答するようにトレーニングされています。
API は関数を直接呼び出すのではなく、代わりにモデルが JSON を生成し、それを使用してコード内で関数を呼び出し、結果をモデルに返して会話を完了します。
Spring AI は、カスタム関数を登録して呼び出すための柔軟でユーザーフレンドリーな方法を提供します。一般に、カスタム関数は、関数 name
、description
、関数呼び出し signature
(JSON スキーマとして) を提供して、関数が期待する引数をモデルに知らせる必要があります。description
は、モデルが関数を呼び出すタイミングを理解できます。
開発者は、AI モデルから送信された関数呼び出し引数を受け取り、その結果をモデルに返す関数を実装する必要があります。関数は、結果を提供するために他のサードパーティサービスを呼び出します。
Spring AI を使用すると、java.util.Function
を返す @Bean
定義を定義し、ChatClient
を呼び出すとき、またはプロンプトリクエストで関数を動的に登録するときにオプションとして Bean 名を指定するだけで、これが簡単になります。
内部的には、Spring は POJO (関数) を適切なアダプターコードでラップし、AI モデルとのやり取りを可能にするため、面倒な定型コードを記述する必要がなくなります。基盤となるインフラストラクチャの基礎は、FunctionCallback.java [GitHub] (英語) インターフェースと、Java コールバック関数の実装と登録を簡素化するコンパニオンビルダーユーティリティクラスです。
使い方
たとえば、特定の場所の現在の気温など、AI モデルが持っていない情報を応答するようにしたいとします。
AI モデルに、プロンプトを処理するときにその情報を取得するために使用できる独自の関数に関するメタデータを提供できます。
たとえば、プロンプトの処理中に、AI モデルが特定の場所の温度に関する追加情報が必要であると判断した場合、サーバー側で生成されたリクエスト / レスポンスのやり取りを開始します。AI モデルは、最終的なレスポンスメッセージを返す代わりに、関数名と引数 (JSON 形式) を指定して、特別なツール呼び出しリクエストを返します。このメッセージを処理し、指定された関数を実行して、レスポンスをツールレスポンスメッセージとして AI モデルに返すのは、クライアントの責任です。
Spring AI は、関数呼び出しをサポートするために記述する必要があるコードを大幅に簡素化します。関数呼び出しの会話を仲介します。関数定義を @Bean
として提供し、プロンプトオプションで関数の Bean 名を提供するか、プロンプトリクエストオプションで関数をパラメーターとして直接渡すだけです。
プロンプトで複数の関数 Bean 名を参照することもできます。
使用例
関数呼び出しがどのように機能するかを説明する例として使用できる簡単なユースケースを定義しましょう。独自の関数を呼び出して質問に答えるチャットボットを作成しましょう。チャットボットのレスポンスをサポートするために、場所を取得してその場所の現在の天気を返す独自の関数を登録します。
モデルが "What ’ s the weather like in Boston?"
などの質問に答える必要がある場合、AI モデルは関数に渡される引数として場所の値を提供するクライアントを呼び出します。この RPC のようなデータは JSON として渡されます。
関数は、SaaS ベースの天気予報サービス API を呼び出し、天気予報のレスポンスをモデルに返して会話を完了します。この例では、さまざまな場所の気温をハードコードする MockWeatherService
というシンプルな実装を使用します。
次の MockWeatherService
クラスは天気予報サービス API を表します。
Java
Kotlin
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);
}
}
class MockWeatherService : Function1<Request, Response> {
override fun invoke(request: Request) = Response(30.0, Unit.C)
}
enum class Unit { C, F }
data class Request(val location: String, val unit: Unit) {}
data class Response(val temp: Double, val unit: Unit) {}
サーバー側登録
Bean としての機能
Spring AI は、Spring コンテキストでカスタム関数を Bean として登録する複数の方法を提供します。
まず、POJO に最も適したオプションについて説明します。
単純な関数
このアプローチでは、他の Spring 管理対象オブジェクトと同様に、アプリケーションコンテキストで @Bean
を定義します。
内部的には、Spring AI ChatModel
は、AI モデルを介して呼び出されるロジックを追加する FunctionCallback
のインスタンスを作成します。@Bean
の名前は関数名として使用されます。
Java
Kotlin
@Configuration
static class Config {
@Bean
@Description("Get the weather in location") // function description
public Function<MockWeatherService.Request, MockWeatherService.Response> currentWeather() {
return new MockWeatherService();
}
}
@Configuration
class Config {
@Bean
@Description("Get the weather in location") // function description
fun currentWeather(): (Request) -> Response = MockWeatherService()
}
@Description
アノテーションはオプションであり、モデルが関数をいつ呼び出すかを理解するのに役立つ関数の説明を提供します。これは、AI モデルがどのクライアント側関数を呼び出すかを決定するのに役立つ重要なプロパティです。
関数の説明を提供する別のオプションは、MockWeatherService.Request
で @JsonClassDescription
アノテーションを使用することです。
Java
Kotlin
@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) {}
@Configuration
class Config {
@Bean
fun currentWeather(): (Request) -> Response { // bean name as function name
return MockWeatherService()
}
}
@JsonClassDescription("Get the weather in location") // function description
data class Request(val location: String, val unit: Unit)
AI モデルが呼び出す正しい関数を選択できるように、その関数の生成された JSON スキーマが可能な限り説明的になるように、リクエストオブジェクトに情報をアノテーション付けすることがベストプラクティスです。
FunctionCallback
関数を登録する別の方法は、次のように FunctionCallback
を作成することです。
Java
Kotlin
@Configuration
static class Config {
@Bean
public FunctionCallback weatherFunctionInfo() {
return 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) input type to build the JSON schema
.build();
}
}
import org.springframework.ai.model.function.withInputType
@Configuration
class Config {
@Bean
fun weatherFunctionInfo(): FunctionCallback {
return FunctionCallback.builder()
.function("CurrentWeather", MockWeatherService()) // (1) function name and instance
.description("Get the weather in location") // (2) function description
// (3) Required due to Kotlin SAM conversion being an opaque lambda
.inputType<MockWeatherService.Request>()
.build();
}
}
サードパーティの MockWeatherService
関数をラップし、ChatClient
とともに CurrentWeather
関数として登録します。また、説明 (2) と、モデルが期待するとおりにレスポンスをテキストに変換するためのオプションのレスポンスコンバーターも提供します。
デフォルトでは、レスポンスコンバーターは Response オブジェクトの JSON 直列化を実行します。 |
FunctionCallback.Builder は、MockWeatherService.Request クラスに基づいて関数呼び出しシグネチャーを内部的に解決します。 |
Bean 名で機能を有効にする
モデルに CurrentWeather
関数を知らせて呼び出すには、プロンプトリクエストでそれを有効にする必要があります。
ChatClient chatClient = ...
ChatResponse response = this.chatClient.prompt("What's the weather like in San Francisco, Tokyo, and Paris?")
.functions("CurrentWeather") // Enable the function
.call().
chatResponse();
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
FunctionCallbackWithPlainFunctionBeanIT.java [GitHub] (英語) テストでは、このアプローチをデモしています。
クライアント側登録
自動構成に加えて、コールバック関数を動的に登録できます。関数呼び出しまたはメソッド呼び出しのいずれかのアプローチを使用して、ChatClient
または ChatModel
リクエストで関数を登録できます。
クライアント側の登録により、デフォルトで関数を登録できるようになります。
関数呼び出し
ChatClient chatClient = ...
ChatResponse response = this.chatClient.prompt("What's the weather like in San Francisco, Tokyo, and Paris?")
.functions(FunctionCallback.builder()
.function("currentWeather", (Request request) -> new Response(30.0, Unit.C)) // (1) function name and instance
.description("Get the weather in location") // (2) function description
.inputType(MockWeatherService.Request.class) // (3) input type to build the JSON schema
.build())
.call()
.chatResponse();
このリクエストの期間中、オンザフライ機能はデフォルトで有効になります。 |
このアプローチにより、ユーザー入力に基づいて呼び出すさまざまな関数を動的に選択できます。
FunctionCallbackInPromptIT.java [GitHub] (英語) 統合テストは、関数を ChatClient
に登録し、それをプロンプトリクエストで使用する方法の完全な例を提供します。
メソッド呼び出し
MethodInvokingFunctionCallback
は、JSON スキーマの生成とパラメーター変換を自動的に処理しながら、リフレクションによるメソッド呼び出しを可能にします。これは、AI モデルのインタラクション内で呼び出し可能な関数として Java メソッドを統合する場合に特に便利です。
MethodInvokingFunctionCallback
は FunctionCallback
インターフェースを実装し、以下を提供します。
メソッドパラメーターの JSON スキーマの自動生成
静的メソッドとインスタンスメソッドの両方をサポート
任意の数のパラメーター(なしも含む)と戻り値 (無効を含む)
任意のパラメーター / 戻り値の型 (プリミティブ、オブジェクト、コレクション)
ToolContext
パラメーターの特別な処理
次のように MethodInvokingFunctionCallback
を作成するには FunctionCallback.Builder
が必要です。
// Create using builder pattern
FunctionCallback methodInvokingCallback = FunctionCallback.builder()
.method("MethodName", Class<?>...argumentTypes) // The method to invoke and its argument types
.description("Function calling description") // Hints the AI to know when to call this method
.targetObject(targetObject) // Required instance methods for static methods use targetClass
.build();
以下に使用例をいくつか示します。
静的メソッド呼び出し
ToolContext を使用したインスタンスメソッド
public class WeatherService {
public static String getWeather(String city, TemperatureUnit unit) {
return "Temperature in " + city + ": 20" + unit;
}
}
// Usage
FunctionCallback callback = FunctionCallback.builder()
.method("getWeather", String.class, TemperatureUnit.class)
.description("Get weather information for a city")
.targetClass(WeatherService.class)
.build();
public class DeviceController {
public void setDeviceState(String deviceId, boolean state, ToolContext context) {
Map<String, Object> contextData = context.getContext();
// Implementation using context data
}
}
// Usage
DeviceController controller = new DeviceController();
String response = ChatClient.create(chatModel).prompt()
.user("Turn on the living room lights")
.functions(FunctionCallback.builder()
.method("setDeviceState", String.class,boolean.class,ToolContext.class)
.description("Control device state")
.targetObject(controller)
.build())
.toolContext(Map.of("location", "home"))
.call()
.content();
OpenAiChatClient メソッド呼び出し関数コールバック IT [GitHub] (英語) 統合テストでは、FunctionCallback.Builder を使用してメソッド呼び出し FunctionCallbacks を作成する方法の追加例が提供されます。
ツールコンテキスト
Spring AI は、ツールコンテキストを介して関数コールバックに追加のコンテキスト情報を渡すことをサポートするようになりました。この機能により、AI モデルによって渡される関数引数とともに、関数実行内で使用できるユーザー提供の追加データを提供できます。
ToolContext [GitHub] (英語) クラスは、追加のコンテキスト情報を渡す方法を提供します。
ツールコンテキストの使用
関数呼び出しの場合、java.util.BiFunction
の 2 番目の引数として渡されるコンテキスト情報。
メソッド呼び出しの場合、コンテキスト情報は ToolContext
型のメソッド引数として渡されます。
関数呼び出し
チャットオプションを構築するときにツールコンテキストを設定し、コールバックに BiFunction を使用できます。
BiFunction<MockWeatherService.Request, ToolContext, MockWeatherService.Response> weatherFunction =
(request, toolContext) -> {
String sessionId = (String) toolContext.getContext().get("sessionId");
String userId = (String) toolContext.getContext().get("userId");
// Use sessionId and userId in your function logic
double temperature = 0;
if (request.location().contains("Paris")) {
temperature = 15;
}
else if (request.location().contains("Tokyo")) {
temperature = 10;
}
else if (request.location().contains("San Francisco")) {
temperature = 30;
}
return new MockWeatherService.Response(temperature, 15, 20, 2, 53, 45, MockWeatherService.Unit.C);
};
ChatResponse response = chatClient.prompt("What's the weather like in San Francisco, Tokyo, and Paris?")
.functions(FunctionCallback.builder()
.function("getCurrentWeather", this.weatherFunction)
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build())
.toolContext(Map.of("sessionId", "1234", "userId", "5678"))
.call()
.chatResponse();
この例では、weatherFunction
は、リクエストとツールコンテキストの両方をパラメーターとして受け取る BiFunction として定義されています。これにより、関数ロジック内でコンテキストに直接アクセスできます。
このアプローチにより、セッション固有またはユーザー固有の情報を関数に渡すことができ、よりコンテキストに応じたパーソナライズされたレスポンスが可能になります。
メソッド呼び出し
public class DeviceController {
public void setDeviceState(String deviceId, boolean state, ToolContext context) {
Map<String, Object> contextData = context.getContext();
// Implementation using context data
}
}
// Usage
DeviceController controller = new DeviceController();
String response = ChatClient.create(chatModel).prompt()
.user("Turn on the living room lights")
.functions(FunctionCallback.builder()
.method("setDeviceState", String.class,boolean.class,ToolContext.class)
.description("Control device state")
.targetObject(controller)
.build())
.toolContext(Map.of("location", "home"))
.call()
.content();