🗿
FunctionCallingを試してみた
背景
社内でAIチャットボットを作る際にMCPを使う運びとなりました。
MCPクライアントを作る際、Function Calling
という機能を使って、MCPサーバの呼び出しをしているようです。
本記事では、Function Calling
とは何か を確認してみます。
対象読者
- LLM初心者
環境
項目 | バージョン |
---|---|
OS | Windows 10 |
ランタイム | Node.js:22.04 + JavaScript |
LLM | Azure OpenAI:2024-12-01-preview |
事前準備
- Node.jsのインストール
- Azure Open AIでLLM(デプロイ)のセットアップ[1]
Function Callingとは
- Function Callingとは、LLMの機能の一つで、
ユーザの入力(プロンプト)に回答するために、LLMが関数を呼び出す「準備をする」機能です。 - プロンプトから適切な関数を決定し、必要な引数を整理する事で、アプリケーションが関数を簡単に呼び出す事が出来るようになります。
- LLMのベンダー毎に、Function Callingの使い方は異なります。 今回はLLMとして、
Azure Open AI
を利用して流れを理解していきます。
概要
- OpenAI公式[2]の天気予報(温度)を取得するサンプルを元に動きを確認していきます。
1. toolに登録する関数の作成
- { 緯度、経度 } を引数に温度を取得する関数を定義します。
async function getWeather(latitude, longitude) {
const response = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,wind_speed_10m&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`);
const data = await response.json();
return data.current.temperature_2m;
}
2. 関数の呼び出し判定
-
tools
に1で作成した関数の概要と引数を定義します。 - ユーザーメッセージと
tools
を使用して、LLMを呼び出します。
import { AzureOpenAI } from "openai";
// apiKey、endpoint、deploymentを環境に合わせて設定
const openai =new AzureOpenAI( {
apiKey: "",
apiVersion: "2024-12-01-preview",
endpoint: "https://xxxx.openai.azure.com/",
deployment: "gpt-4.1-mini",
} );
const tools = [{
type: "function",
function: {
name: "get_weather",
description: "Get current temperature for provided coordinates in celsius.",
parameters: {
type: "object",
properties: {
latitude: { type: "number" },
longitude: { type: "number" }
},
required: ["latitude", "longitude"],
additionalProperties: false
},
strict: true
},
}];
const userMessage = "What's the weather like in Paris today?";
const response = await openai.chat.completions.create ({
model: "",
messages: [{ role: "user", content: userMessage }],
tools: tools,
tool_choice: "auto", // 必要に応じてツールを呼び出す
});
console.log(JSON.stringify(response, null, 2));
- LLMは
choices
に結果を返します。 - 関数を呼び出すことを決定(
finish_reason
)し、呼び出す関数の情報(tool_calls
)を返します。 - 関数の情報は、名前(
name
)とjson型の引数(arguments
)です。- Parisの緯度・経度がユーザプロンプトにない場合、LLMが自動的に取得します。
{
"choices": [
{
"content_filter_results": {},
"finish_reason": "tool_calls",
"index": 0,
"logprobs": null,
"message": {
"annotations": [],
"content": null,
"refusal": null,
"role": "assistant",
"tool_calls": [
{
"function": {
"arguments": "{\"latitude\":48.8566,\"longitude\":2.3522}",
"name": "get_weather"
},
"id": "call_nKkomccjfFx1trM9PQAoTmGh",
"type": "function"
}
]
}
}
],
...
}
3. 関数の呼び出し
- 呼び出す関数の情報(
tool_calls
)を元に、関数を呼び出します。
const message = response.choices[0].message;
const toolCall =message.tool_calls[0];
const args = JSON.parse(toolCall.function.arguments);
const result = await getWeather(args.latitude, args.longitude);
4. 回答の作成
- LLMに{ ユーザーメッセージ、AIのツール呼び出しリクエスト、ツールの実行結果 }を渡し、最終回答を作成させます。
// AIにツールの結果を渡して応答を得る
const finalResponse = await openai.chat.completions.create({
model: "",
messages: [
{ role: "user", content: userMessage }, // ユーザーメッセージ
message, // AIのツール呼び出しリクエスト
{
role: "tool",
tool_call_id: toolCall.id,
content: result.toString()
}, // ツールの実行結果
],
});
console.log(finalResponse.choices[0].message.content);
- AIの回答
The weather in Paris today is around 17.1°C. If you'd like more details such as conditions or forecast, let me know!
まとめ
- LLMを使って、関数の呼び出し判定と引数の準備が出来る事が確認出来ました。
- 一般的な情報であれば、引数を指定しなくてもLLMが推測してくれることも分かりました。
-
Function Calling
と呼ばれていますが、関数を呼ぶ準備
をする仕組みであり実際に関数を呼び出す部分は別途準備が必要です。 - 関数を呼び出す部分を個別で実装すると、関数が増えた場合にコード量が多くなってしまいます。
- 呼び出し部分を簡単に書くための、LangchainやMastra等のフレームワークについて調べてみたいと思います。
Discussion