AI Edge Function Calling SDK(FC SDK)は、デベロッパーがデバイス上の LLM で関数呼び出しを使用できるようにするライブラリです。関数呼び出しを使用すると、モデルを外部ツールや API に接続できます。これにより、モデルは必要なパラメータを使用して特定の関数を呼び出し、現実世界のアクションを実行できます。
FC SDK を使用する LLM は、テキストを生成するだけでなく、最新情報の検索、アラームの設定、予約などのアクションを実行する関数への構造化された呼び出しを生成できます。
このガイドでは、FC SDK を使用して LLM 推論 API を Android アプリケーションに追加する基本的なクイックスタートについて説明します。このガイドでは、オンデバイス LLM に関数呼び出し機能を追加することに焦点を当てています。LLM 推論 API の使用について詳しくは、Android 向け LLM 推論ガイドをご覧ください。
クイックスタート
Android アプリで FC SDK を使用する手順は次のとおりです。このクイックスタートでは、Hammer 2.1(15 億)で LLM 推論 API を使用します。LLM 推論 API は、Google Pixel 8 や Samsung S23 以降などのハイエンド Android デバイス向けに最適化されており、デバイス エミュレータは確実にサポートしていません。
依存関係を追加する
FC SDK は com.google.ai.edge.localagents:localagents-fc ライブラリを使用し、LLM 推論 API は com.google.mediapipe:tasks-genai ライブラリを使用します。両方の依存関係を Android アプリの build.gradle ファイルに追加します。
dependencies {
implementation 'com.google.mediapipe:tasks-genai:0.10.24'
implementation 'com.google.ai.edge.localagents:localagents-fc:0.1.0'
}
Android 12(API 31)以上を搭載したデバイスの場合、ネイティブ OpenCL ライブラリの依存関係を追加します。詳細については、uses-native-library タグに関するドキュメントをご覧ください。
次の uses-native-library タグを AndroidManifest.xml ファイルに追加します。
<uses-native-library android:name="libOpenCL.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-car.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-pixel.so" android:required="false"/>
モデルのダウンロード
Hugging Face から 8 ビット量子化形式で Hammer 1B をダウンロードします。使用可能なモデルの詳細については、モデルのドキュメントをご覧ください。
hammer2.1_1.5b_q8_ekv4096.task フォルダの内容を Android デバイスにプッシュします。
$ adb shell rm -r /data/local/tmp/llm/ # Remove any previously loaded models
$ adb shell mkdir -p /data/local/tmp/llm/
$ adb push hammer2.1_1.5b_q8_ekv4096.task /data/local/tmp/llm/hammer2.1_1.5b_q8_ekv4096.task
関数定義を宣言する
モデルで使用可能にする関数を定義します。このプロセスを説明するために、このクイックスタートには、ハードコードされたレスポンスを返す静的メソッドとして 2 つの関数が含まれています。より実用的な実装では、REST API を呼び出す関数やデータベースから情報を取得する関数を定義します。
次のコードは、getWeather 関数と getTime 関数を定義します。
class ToolsForLlm {
public static String getWeather(String location) {
return "Cloudy, 56°F";
}
public static String getTime(String timezone) {
return "7:00 PM " + timezone;
}
private ToolsForLlm() {}
}
FunctionDeclaration を使用して各関数を記述し、それぞれに名前と説明を付け、型を指定します。これにより、関数が何を行うか、いつ関数呼び出しを行うかをモデルに通知します。
var getWeather = FunctionDeclaration.newBuilder()
.setName("getWeather")
.setDescription("Returns the weather conditions at a location.")
.setParameters(
Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties(
"location",
Schema.newBuilder()
.setType(Type.STRING)
.setDescription("The location for the weather report.")
.build())
.build())
.build();
var getTime = FunctionDeclaration.newBuilder()
.setName("getTime")
.setDescription("Returns the current time in the given timezone.")
.setParameters(
Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties(
"timezone",
Schema.newBuilder()
.setType(Type.STRING)
.setDescription("The timezone to get the time from.")
.build())
.build())
.build();
関数宣言を Tool オブジェクトに追加します。
var tool = Tool.newBuilder()
.addFunctionDeclarations(getWeather)
.addFunctionDeclarations(getTime)
.build();
推論バックエンドを作成する
LLM Inference API を使用して推論バックエンドを作成し、モデルのフォーマッタ オブジェクトを渡します。FC SDK Formatter(ModelFormatter)は、フォーマッタとパーサーの両方の役割を果たします。このクイックスタートでは Gemma-3 1B を使用するため、GemmaFormatter を使用します。
var llmInferenceOptions = LlmInferenceOptions.builder()
.setModelPath(modelFile.getAbsolutePath())
.build();
var llmInference = LlmInference.createFromOptions(context, llmInferenceOptions);
var llmInferenceBackend = new llmInferenceBackend(llmInference, new GemmaFormatter());
詳細については、LLM 推論の構成オプションをご覧ください。
モデルをインスタンス化する
GenerativeModel オブジェクトを使用して、推論バックエンド、システム プロンプト、ツールを接続します。推論バックエンドとツールはすでに存在するため、システム プロンプトを作成するだけで済みます。
var systemInstruction = Content.newBuilder()
.setRole("system")
.addParts(Part.newBuilder().setText("You are a helpful assistant."))
.build();
GenerativeModel を使用してモデルをインスタンス化します。
var generativeModel = new GenerativeModel(
llmInferenceBackend,
systemInstruction,
List.of(tool),
)
チャット セッションを開始する
わかりやすくするため、このクイックスタートでは単一のチャット セッションを開始します。複数の独立したセッションを作成することもできます。
GenerativeModel の新しいインスタンスを使用して、チャット セッションを開始します。
var chat = generativeModel.startChat();
sendMessage メソッドを使用して、チャット セッションを通じてモデルにプロンプトを送信します。
var response = chat.sendMessage("How's the weather in San Francisco?");
モデルのレスポンスを解析する
プロンプトをモデルに渡した後、アプリケーションはレスポンスを調べて、関数呼び出しを行うか、自然言語テキストを出力するかを判断する必要があります。
// Extract the model's message from the response.
var message = response.getCandidates(0).getContent().getParts(0);
// If the message contains a function call, execute the function.
if (message.hasFunctionCall()) {
var functionCall = message.getFunctionCall();
var args = functionCall.getArgs().getFieldsMap();
var result = null;
// Call the appropriate function.
switch (functionCall.getName()) {
case "getWeather":
result = ToolsForLlm.getWeather(args.get("location").getStringValue());
break;
case "getTime":
result = ToolsForLlm.getWeather(args.get("timezone").getStringValue());
break;
default:
throw new Exception("Function does not exist:" + functionCall.getName());
}
// Return the result of the function call to the model.
var functionResponse =
FunctionResponse.newBuilder()
.setName(functionCall.getName())
.setResponse(
Struct.newBuilder()
.putFields("result", Value.newBuilder().setStringValue(result).build()))
.build();
var functionResponseContent = Content.newBuilder()
.setRole("user")
.addParts(Part.newBuilder().setFunctionResponse(functionResponse))
.build();
var response = chat.sendMessage(functionResponseContent);
} else if (message.hasText()) {
Log.i(message.getText());
}
このサンプルコードは、実装を簡略化しすぎたものです。アプリケーションがモデルのレスポンスを検査する方法の詳細については、形式設定と解析をご覧ください。
仕組み
このセクションでは、Android 用関数呼び出し SDK の基本コンセプトとコンポーネントについて詳しく説明します。
モデル
Function Calling SDK には、フォーマッタとパーサーを備えたモデルが必要です。FC SDK には、次のモデル用の組み込みのフォーマッタとパーサーが含まれています。
FC SDK で別のモデルを使用するには、LLM 推論 API と互換性のある独自のフォーマッタとパーサーを開発する必要があります。
フォーマットと解析
関数呼び出しサポートの重要な部分は、プロンプトのフォーマットとモデル出力の解析です。これらは 2 つの別々のプロセスですが、FC SDK は ModelFormatter インターフェースを使用してフォーマットと解析の両方を処理します。
フォーマッタは、構造化された関数宣言をテキストに変換し、関数レスポンスの形式を設定し、会話ターンの開始と終了を示すトークンと、それらのターンのロール(「ユーザー」、「モデル」など)を挿入します。
パーサーは、モデルのレスポンスに関数呼び出しが含まれているかどうかを検出します。パーサーが関数呼び出しを検出すると、構造化データ型に解析します。それ以外の場合は、テキストを自然言語レスポンスとして扱います。
制約付きデコード
制約付きデコードは、LLM の出力生成をガイドして、JSON オブジェクトや Python 関数呼び出しなどの事前定義された構造化形式に準拠させる手法です。これらの制約を適用することで、モデルは事前定義された関数とその対応するパラメータ型に沿った形式で出力を生成します。
制約付きデコードを有効にするには、ConstraintOptions オブジェクトで制約を定義し、ChatSession インスタンスの enableConstraint メソッドを呼び出します。有効にすると、この制約により、レスポンスは GenerativeModel に関連付けられたツールのみを含むように制限されます。
次の例は、制約付きデコードを構成して、レスポンスをツール呼び出しに制限する方法を示しています。ツール呼び出しが接頭辞 ```tool_code\n で始まり、接尾辞 \n``` で終わるように制約します。
ConstraintOptions constraintOptions = ConstraintOptions.newBuilder()
.setToolCallOnly( ConstraintOptions.ToolCallOnly.newBuilder()
.setConstraintPrefix("```tool_code\n")
.setConstraintSuffix("\n```"))
.build(); chatSession.enableConstraint(constraintOptions);
同じセッション内でアクティブな制約を無効にするには、disableConstraint メソッドを使用します。
chatSession.disableConstraint();