前の 2 つのセクションの基礎を持っているので、次は少し強度を上げる必要があります。関数呼び出し - 関数の呼び出し。
では、関数呼び出しが何を意味するのでしょうか?公式の説明は次のとおりです:
OpenAiChatClient にカスタムの Java 関数を登録し、OpenAI モデルが登録された関数のいずれかを呼び出すための引数を含む JSON オブジェクトを出力するようにインテリジェントに選択することができます。これにより、LLM の機能を外部ツールや API と接続することができます。 OpenAI モデルは、関数を呼び出すべき時期を検出し、関数シグネチャに準拠する JSON で応答するようにトレーニングされています。
OpenAiChatClient を使用してカスタムの Java 関数を登録し、OpenAI モデルが登録された関数のいずれかを呼び出すための引数を含む JSON オブジェクトを出力することができます。これにより、LLM の機能を外部ツールや API と接続することができます。 OpenAI モデルは、関数を呼び出すべき時期を検出し、関数シグネチャに準拠する JSON で応答するようにトレーニングされています。
よく知られているように、OpenAI の ChatGPT はオフラインで動作しないため、Function Calling を使用することでモデルに最新のデータを提供することができます。
例えば、ChatGPT に「天気」プラグインを追加して、GPT に北京と上海の最新の天気を教えて、どの服を着るべきかをまとめてもらうことができます。または、「トレンド」プラグインを追加して、AI に最新のトレンドをまとめてもらうこともできます。
関数の作成#
関数の作成には、Function インターフェースを実装する必要があります。
public class MockWeatherService implements Function<MockWeatherService.Request, MockWeatherService.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) {
System.err.println("MockWeatherService.apply");
return new Response(30.0, Unit.C);
}
}
ここでは、固定値である 30°C を返していますが、実際にはインターフェースを呼び出して実際のデータを返すことができます。
関数の登録#
関数を作成したら、登録する必要があります。登録には 2 つの方法があります。
モデル作成時の登録#
モデルを作成する際に関数を登録することができます。例えば、
var openAiApi = new OpenAiApi("https://xxx", "sk-xxx");
OpenAiChatClient chatClient = new OpenAiChatClient(openAiApi, OpenAiChatOptions.builder()
.withModel("gpt-3.5-turbo-1106")
.withTemperature(0.4F)
.withFunctionCallbacks(List.of(
FunctionCallbackWrapper.builder(new MockWeatherService())
.withName("weather").withDescription("Get the weather in location").build()))
.build());
withFunctionCallbacks()
は関数の登録を示しており、FunctionCallbackWrapper.builder
は関数を構築するために使用されます。withName("weather").withDescription("Get the weather in location")
は関数の名前と説明を示しています。できるだけ英語を使用し、操作に関連する説明を行うことで、AI がいつ特定の関数を使用するかを判断しやすくします。
動的登録#
動的登録も推奨される方法であり、質問に応じて対応する関数を選択することができます。
var promptOptions = OpenAiChatOptions.builder().withFunctionCallbacks(List.of(
FunctionCallbackWrapper.builder(new MockWeatherService()).withName("weather").withDescription("Get the weather in location").build(),
FunctionCallbackWrapper.builder(new WbHotService()).withName("wbHot").withDescription("Get the hot list of Weibo").build(),
FunctionCallbackWrapper.builder(new TodayNews()).withName("todayNews").withDescription("60s watch world news").build())).build();
ChatResponse response = chatClient.call(new Prompt(message, promptOptions));
return response.getResult().getOutput().getContent();
ここでは、3 つの関数が登録されています。
- weather は上記で作成した天気関数です。
- wbHot は API を呼び出して取得した Weibo のホットリストです。
- todayNews は API を呼び出して取得した 60 秒の世界ニュースです。
異なるプロンプトに基づいて、AI は最も適切な関数を呼び出すことを選択します。
以下は Weibo のホットリストの関数の例です。
public class WbHotService implements Function<WbHotService.Request, WbHotService.Response> {
public record Request(String wb) {}
public record Response(WbHot wbHot) {}
/**
* Applies this function to the given argument.
*
* @param request the function argument
* @return the function result
*/
@Override
public Response apply(Request request) {
System.err.println("微博热榜哦,表哥我进来了哦(*/ω\*)(*/ω\*)");
// 使用hutool请求接口
String result = HttpUtil.get("https://api.vvhan.com/api/hotlist/wbHot");
WbHot bean = JSONUtil.toBean(result, WbHot.class);
return new Response(bean);
}
}
実際には、インターフェースから返される JSON をオブジェクトに変換する必要はなく、そのまま AI に返すことができます。
ただし、現在の Function Calling には問題があり、関数の結果は常に AI によって処理されます。
例えば、私には画像関数があり、AI に「エロい画像を見せて」と言って、この関数を呼び出した場合、関数は単純な URL を返すだけで十分です。AI に処理させる必要はありません。もし AI が「おい、お前の趣味は本当に奇妙だな」と言ってきたら🤣 ただし、以前にもISSUESが報告されています。
推奨事項#
Function Calling の具体的なアプリケーションについては、次の記事を参照してください。
Spring AI アプリケーション - スマートジャーナリスト
完全なコードはこのgistで確認できます。
Spring AI Chat のシンプルな例
韓小韓 API インターフェースサイト - 無料の API データインターフェース呼び出しサービスプラットフォーム
韓小韓 API インターフェースサイト -