ChatGPT APIの新機能「Function calling」を試してみた。
はじめに
本日、2023年6月14日 ChatGPTのAPIの新機能として「Function calling」が公開されました。
Function callingとは
これまで公開されていたChatGPTの「プラグイン」機能は、下記の画像のように、ブラウザのChatGPTから外部サービスを自然言語で利用可能にするものでした。
今回発表された「Function calling」を利用すると、ChatGPTからだけではなく、例えばLINEのような外部サービスから、食べログのようなサービスを利用することが可能になります。
(厳密には、食べログはChatGPTプラグインは公開しておりますが、APIは公開していないため、LINEから食べログの利用はできなそうです。)
GASでFunction callingを触ってみた。
Function callingの公式ドキュメント( https://platform.openai.com/docs/guides/gpt/function-calling )に記載されている天気の情報を取得するサンプルコードを、GASで動くように書いてみました。
それに加えて、2点間の距離を問われた場合にはGoogle MapsのAPIを利用して答えるような処理をテスト的に追加してみました。
const OPENAI_APIKEY = PropertiesService.getScriptProperties().getProperty('OPENAI_APIKEY');
const CHAT_GPT_URL = 'https://api.openai.com/v1/chat/completions';
function myFunction() {
const userMessage = '東京から大阪までの距離を教えて。';
try {
const chatGptMessage = getChatGPTResponse(userMessage);
console.log(chatGptMessage);
} catch (error) {
console.error(error);
}
}
function getChatGPTResponse(userMessage) {
const response = sendGptRequest(userMessage);
if (response.choices[0].message.function_call) {
const function_name = response.choices[0].message.function_call.name;
console.log('function_name: ' + function_name);
const function_arguments = JSON.parse(response.choices[0].message.function_call.arguments);
let function_response;
if (function_name === 'get_current_weather') {
const location = function_arguments.location;
function_response = getCurrentWeather(location);
} else if (function_name === 'get_distance_between_locations') {
const start_location = function_arguments.start_location;
const end_location = function_arguments.end_location;
function_response = getRoute(start_location, end_location);
}
return sendGptRequestWithFunction(userMessage, response.choices[0].message, function_name, function_response);
} else {
return response.choices[0].message.content.trim();
}
}
function sendGptRequest(userMessage) {
const requestOptions = createRequestOptions(userMessage);
try {
const response = UrlFetchApp.fetch(CHAT_GPT_URL, requestOptions);
return JSON.parse(response.getContentText());
} catch (error) {
console.error(error);
throw new Error('GPT API request failed.');
}
}
function sendGptRequestWithFunction(userMessage, message, functionName, functionResponse) {
const requestOptions = createRequestOptionsWithFunction(userMessage, message, functionName, functionResponse);
try {
const response = UrlFetchApp.fetch(CHAT_GPT_URL, requestOptions);
return JSON.parse(response.getContentText()).choices[0].message.content.trim();
} catch (error) {
console.error(error);
throw new Error('GPT API request with function failed.');
}
}
function createRequestOptions(userMessage) {
return {
"method": "post",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer " + OPENAI_APIKEY
},
"payload": JSON.stringify({
"model": "gpt-3.5-turbo-0613",
"messages": [{ "role": "user", "content": userMessage }],
"functions": getFunctionDefinitions(),
})
};
}
function createRequestOptionsWithFunction(userMessage, message, functionName, functionResponse) {
return {
"method": "post",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer " + OPENAI_APIKEY
},
"payload": JSON.stringify({
"model": "gpt-3.5-turbo-0613",
'messages': [
{ "role": "user", "content": userMessage },
message,
{
"role": "function",
"name": functionName,
"content": functionResponse,
},
],
"functions": getFunctionDefinitions(),
})
};
}
function getFunctionDefinitions() {
return [
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
},
{
"name": "get_distance_between_locations",
"description": "Get the distance between two locations using Google Maps API",
"parameters": {
"type": "object",
"properties": {
"start_location": {
"type": "string",
"description": "The starting location, e.g. Tokyo, Japan"
},
"end_location": {
"type": "string",
"description": "The ending location, e.g. Osaka, Japan"
},
"unit": {
"type": "string",
"enum": ["kilometers", "miles"],
"description": "The unit of distance measurement"
}
},
"required": ["start_location", "end_location"]
}
}
];
}
function getCurrentWeather(location, unit = "celsius") {
var weatherInfo = {
"location": location,
"temperature": "33",
"unit": unit,
"forecast": ["sunny", "windy"]
};
return JSON.stringify(weatherInfo);
}
function getRoute(start_location, end_location) {
var apiKey = PropertiesService.getScriptProperties().getProperty('GOOGLE_MAPS_APIKEY');
var url = 'https://maps.googleapis.com/maps/api/directions/json?origin=' + start_location + '&destination=' + end_location + '&key=' + apiKey;
var options = {
method: 'GET'
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
if (data.status != "OK") {
Logger.log("Error: " + data.status);
return;
}
var routes = data.routes;
var distance_info = {};
for (var i = 0; i < routes.length; i++) {
var route = routes[i];
var legs = route.legs;
for (var j = 0; j < legs.length; j++) {
var leg = legs[j];
distance_info = {
"Start": leg.start_address,
"End": leg.end_address,
"Distance": leg.distance.text,
"Duration": leg.duration.text
}
}
}
return JSON.stringify(distance_info);
}
実行結果
天気に関する質問をすると、get_current_weatherのfunctionが利用され、天気取得API(モック)が叩かれる
2点間の距離に関する質問をすると、get_distance_between_locationsのfunctionが利用され、GoogleMapsのAPIが叩かれる
定義したfunctionと無関係なメッセージを送信すると、functionは利用されず、通常のGPTが応答する
最後に
「Function calling」の機能により、ChatGPTを経由して、異なるサービス間のデータの受け渡しを自然言語でやり取りできるようになりました。
具体的には、LINEから特定のアカウントに日本語で「◯月◯日に大阪でホテルの予約をしたい。」のようなメッセージを送信して、Booking.comでホテルを予約する、といったことが実現可能になります。
ChatGPTのプラグインの機能をAPIで利用できるように、いつかはなるだろうと思っていましたが、もうできてしまいましたね。OpenAI社のスピード感は素晴らしいです。
ChatGPTを利用したチャットボット等の開発に興味がある方は、ぜひお気軽にご相談ください。
参考文献
この記事が気に入ったらサポートをしてみませんか?