OpenAIã®FunctionCallingãçè§£ãã
2023/06/13 OpenAIã®å€§ããªã¢ããããŒããçºè¡šãããŸããã
ãã®äžã§ãæ°ãã«å ãã£ãç®çæ©èœãFunction callingã§ãã
ãã®Function callingãäžèŠãããšãAPIã®ã¬ã¹ãã³ã¹ãããæãã®JSONã«ããŠãããã®ããªïŒããšæã£ãŠããŸãã®ã§ãããããã¯äœ¿ãæ¹ã®äžéšã§æ¬è³ªã§ã¯ãããŸãã*ãæ¬èšäºã§ã¯ããã®å°ãæŠå¿µããããããFunction callingãæ©ããæ£ç¢ºã«çè§£ã§ããããã«å ·äœçãªå®è£ ã亀ããŠã玹ä»ããŸãã
*èšäºã®æåŸã«ã¬ã¹ãã³ã¹ãJSONã«ããæ¹æ³ãã玹ä»ã¯ããŸãã
Function callingãšã¯
Function callingãšã¯ãOpenAI API(以éOpenAI)ã®ã¬ã¹ãã³ã¹ãå€éšé¢æ°ã®åŒã³åºããæ€ç¥ããæããŠãããä»çµã¿ã§ããããã«ãããOpenAIãšå€éšã®ã·ã¹ãã 飿ºããã¹ãªãæ£ç¢ºã«è¡ãããšãã§ããããã«ãªããŸãã

å ·äœäŸãšããŠããã倩æ°ãå§ãããã£ãããããããOpenAIã䜿ã£ãŠäœãããšãèããŠã¿ãŸããããGPTã¯çŽè¿ã®å€©æ°äºå ±ã®æ å ±ã¯æã£ãŠããªãã®ã§ãæ£ãã倩æ°ãåŸãã«ã¯å€éšã®é¢æ°(倩æ°ã®API)ãåŒã³åºãå¿ èŠããããŸããæµããšããŠã¯ä»¥äžã®ããã«ãªãã§ãããã

ããããããã§1ã€åé¡ãèµ·ããŸãããã€å€©æ°ã®APIãåŒã³åºãã°ããã®ã§ããããïŒ
ãŠãŒã¶ãŒã¯å€©æ°ä»¥å€ã®ããšãèªç±ã«å
¥åã§ããŸããã倩æ°ãå§ãããšéè«ãããæããããããããŸããç¬ Function Callingã®ãªãOpenAIã§ã¯ããã®å€©æ° APIãåŒã³åºãã¿ã€ãã³ã°ãæ€ç¥ããããšãå°é£ã§ããã

ããã§ç»å Žããã®ããFunction callingã§ããFunction callingãå©çšããããšã§ãäŒè©±ã®äžã§å€©æ°ååŸé¢æ°ã®åŒã³åºããå¿ èŠã«ãªã£ãããOpenAIã®ã¬ã¹ãã³ã¹ãæããŠãããŸãã
ãµãŒããŒã¯ã¬ã¹ãã³ã¹ãã颿°ã®å®è¡æç€ºãåãåºããŠãé©å®å¿ èŠãªé¢æ°åŒã³åºããè¡ãã°è¯ãããã§ãã ððŒ

詊ããŠã¿ã
æŠå¿µãçè§£ã§ãããšããã§ãå®éã«ã倩æ°ãå§ãããã£ããããããå®è£ ããªãããFunction Callingã詊ããŠã¿ãŸããããã³ãŒãã¯ãã¡ãã«å ¬éããŠããŸããæå ã§åããããæ¹ã¯ã©ããã
functionsã®å®çŸ©
æåã«å€éšé¢æ°ã«åœããfunctionsããããã£ãå®çŸ©ããŸãã
ä»åå®è¡ããã倩æ°ååŸAPIã®é¢æ°ã以äžã®ãããªãã®ã ãšããŸãã
type WeatherAPIResponse = {
date: string;
location: string;
weather: string;
};
export const getWeather = (
location: string,
date: string
): Promise<WeatherAPIResponse> => {
// NOTE: ã¢ãã¯ã®å®è£
å®éã«ã¯éåæã®APIãªã¯ãšã¹ããå
¥ãã
return new Promise((resolve) => resolve({ date, location, weather: "æŽã" }));
};
ãã®getWeathre颿°ã®åŒã³åºãã®ã€ã³ã¿ãŒãã§ãŒã¹ã«åãããŠãfunctionsããããã£ãå®çŸ©ããŸããåããããã£ã®æå³ã¯ã³ã¡ã³ãã§è¿œèšããŠãããŸããããã詳ããå®çŸ©ã¯ããã¥ã¡ã³ããã芧ãã ããã
const functions: FunctionObject[] = [
{
# 颿°ã®åå
name: "get_weather",
# 颿°ã®èª¬æ
description: "æå®ãããå Žæãšæ¥ä»ã®å€©æ°ãååŸãã",
# ãã©ã¡ãŒã¿
parameters: {
type: "object",
# åŒæ°
properties: {
location: {
type: "string",
description: "éœéåºçãåžãçºã®åå, e.g. æ±äº¬éœæäº¬åº",
},
date: {
type: "string",
description: "Date formatted in YYYY/mm/dd, e.g. 2023/06/13",
},
},
# åŒæ°ã®äžã§å¿
é ã®ãã®
required: ["location", "date"],
},
},
];
Completion APIã®åŒã³åºã
ã§ã¯ããã®functionsãããããã£ã«å«ããŠãCreate Completion APIãåŒã³åºããŸãã
const conversation = new Conversation();
conversation.addMessage("user", "ææ¥ã®æ±äº¬ã®å€©æ°ããããŸããïŒ");
const response: CompletionAPIResponse = await chatCompletionRequest(
conversation.messages,
functions
);
cnosole.log(response)
ã¬ã¹ãã³ã¹ã¯ä»¥äžã®ããã«ãªããŸãã
éåžžã®ã¡ãã»ãŒãžã®ã¬ã¹ãã³ã¹ãšã¯ç°ãªãã
-
finish_reasonãfunction_call -
contentã¯null -
functions_callã«é¢æ°å(name)ãšstringifyããjson圢åŒã®åŒæ°(arguments)
ãå«ãŸããŠããããšãããããŸãã
{
// ...
choices: [
{
index: 0,
message: {
role: "assistant",
content: null,
// 颿°åŒã³åºã
function_call: {
// 颿°å
name: "get_tommorow_weather",
// åŒæ°
arguments: '{\n "location": "æ±äº¬",\n "date": "2023/06/14"\n}'
}
},
ãããã// 颿°ã®åŒã³åºããæå³ãã
finish_reason: "function_call"
}
]
}
ã¬ã¹ãã³ã¹ãåãåã£ãããfinish_reasonãfunction_call ã§ããã°ãargumentså
ã®jsonãããŒã¹ããŠã颿°(倩æ°ã®API)ãå®è¡ããã°ããããã§ããððŒ
// 颿°ã®åŒã³åºããå¿
èŠã
if (response.choices[0].finish_reason === "function_call") {
const functionCall = firstResponse.choices[0].message.function_call;
// åŒæ°ãparse
const { location, date } = JSON.parse(functionCall.arguments);
// åŒæ°ã䜿ã£ãŠå€©æ°APIãå®è¡
const weather = await getWeather(location, date);
}
role: function messageã䜿ã£ãŠåçã®çæããé¡ããã
ç¶ããŠã倩æ°APIããååŸããã¬ã¹ãã³ã¹ããŠãŒã¶ãŒã«è¿åŽããåçã«ãã©ãŒãããããŸãã
ãŸãæãã€ãã®ã¯ä»¥äžã®ããã«ãã©ãŒãããããŠããŸãæ¹æ³ã§ãã
`${date}ã®${location}倩æ°ã¯${weathre}ã§ã`ã// ex 2023/06/14ã®æ±äº¬ã®å€©æ°ã¯æŽãã§ã
ããã§ãããã®ã§ãããå®ã¯æ°ãã«è¿œå ãããmessage role:functionã䜿ã£ãŠãAPIåŽã«åçãçæããŠããããããšãã§ããŸãã
å ·äœçã«ã¯ãªã¯ãšã¹ãã以äžã®ããã«ããŸãããã€ã³ãã¯ãcontentã«é¢æ°(倩æ°API)ã®å®è¡çµæãæž¡ããŠããç¹ã§ãã
{
model: "gpt-3.5-turbo-0613",
messages: [
{ role: "user", content: "ææ¥ã®æ±äº¬ã®å€©æ°ããããŸããïŒ", name: undefined },
ãã // 颿°ã衚ãã¡ãã»ãŒãž
{
role: "function",
ããã // 颿°ã®å®è¡çµæãjson stringifyãããã®
content: '{"date":"2023/06/13","location":"æ±äº¬","weather":"æŽã"}',
name: "get_weather"
}
],
functions: [
{
name: "get_weather",
description: "æå®ãããå Žæãšæ¥ä»ã®å€©æ°ãååŸãã",
parameters: {
type: "object",
properties: { location: [Object], date: [Object] },
required: [ "location", "date" ]
}
}
]
}
ã¬ã¹ãã³ã¹ã¯ä»¥äžã§ãã
messagesã®å
容ãèŠãŠãããæãã«åçãçæããŠãããŸãã
{
//...
choices: [
{
index: 0,
// ããæãã«ãã©ãŒãããããåçãçæããŠããã
message: { role: "assistant", content: "ææ¥ã®æ±äº¬ã®å€©æ°ã¯æŽãã§ãã" },
finish_reason: "stop"
}
]
}
ã³ãŒãã¯ä»¥äžã®ããã«ãªããŸãããªã¯ãšã¹ãã¯1åå¢ããŸãããmessageã«èŠçŽ ã远å ããã ãã§ã·ã³ãã«ãªåœ¢ã§æžãããšãã§ããŸãã
const weather = await getWeather(location, date);
// role: messageã远å
conversation.addMessage(
"function",
JSON.stringify(weather),
functionCall.name
);
// ãªã¯ãšã¹ã
const secondResponse: CompletionAPIResponse = await chatCompletionRequest(
conversation.messages,
functions
);
// => message: { role: "assistant", content: "ææ¥ã®æ±äº¬ã®å€©æ°ã¯æŽãã§ãã" },
ãçªå€ãFunciton callingã䜿ã£ãŠãAPIã®ã¬ã¹ãã³ã¹ãJSONã«ããŒã¹ãã
åé ã«Function callingã¯Open AI APIã®ã¬ã¹ãã³ã¹ãJSONã«ãã©ãŒããããããã®ã§ã¯ãªããšãäŒãããŸããã
ããããå®ã¯å°ã工倫ããŠãããå®çŸããããšãã§ããŸããåçã颿°åŒã³åºãã«ãªãããã«å®çŸ©ããŠãããã®ã§ãã
äŸãèŠãŠã¿ãŸãããã
以åèªåãéçºãããAIæ¬å±ããã§ã¯åçãJSON圢åŒã§ãããããã«ä»¥äžã®ãããªããã³ãããæžããŠããŸããã
ããããã®æ¬ãæããŠãã ããã
åºåã¯ä»¥äžã®ãã©ãŒãããã«åŸã£ãŠãã ããã
\`\`\`json
{
title: string, // æ¬ã®ã¿ã€ãã«
description: string // æ¬ã®èª¬æ
}
\`\`\`
ããã«çµæãparseããŠJSONã«ããŠããŸãã
export const parseGPTResponse = (gptResponse: string): GPTBook[] => {
const regex = /```json([\s\S]*?)```/gm
const match = regex.exec(gptResponse)
if (match === null || match?.[1] === null) {
throw new Error("JSON content not found in the string")
}
const jsonData: object = JSON.parse(match[1])
return jsonData as GPTBook[]
}
ããã§ããJSON以å€ã®æååãè¿ã£ãŠããããããŸãparseã§ããªãã£ãããšããããã®ç¢ºçã§ãšã©ãŒã«ãªããŸãã
åããã以äžã®JSONã ãè¿ããŠãããã°çæ³ã§ãã
{
title: string, // æ¬ã®ã¿ã€ãã«
description: string // æ¬ã®èª¬æ
}
ãããFunctionCallingã䜿ã£ãŠå®çŸããŸããåè¿°ã®éããåççµæã颿°ã®åŒã³åºãã«ãªãããã«ããã°è¯ãã®ã§ãã
å
·äœçã«ã¯ä»¥äžã®ãããªrecommend_book 颿°ãå®çŸ©ããŸãã
const functions: FunctionObject[] = [
{
name: "recommend_book",
description: "ããããã®æ¬ã1å玹ä»ãã",
parameters: {
type: "object",
properties: {
title: {
type: "string",
description: "æ¬ã®ã¿ã€ãã«",
},
description: {
type: "string",
description: "æ¬ã®å
容",
},
},
required: ["title", "description"],
},
},
]
ããã§ãæ¬ã®ãããããèãã°ãfunction_call.args ã«çæ³ã®JSONãå«ããŠè¿ããŠãããŸãã
const conversation = new Conversation()
conversation.addMessage(
"user",
"æ©ãããŠã©ã³ãããã«ããããã®æ¬ãæããŠãã ããã"
)
const response: CompletionAPIResponse = await chatCompletionRequest(
conversation.messages,
functions,
{ name: "recommend_book" }
)
const functionCall = response.choices[0].message.function_call
const bookJSON = JSON.parse(functionCall.arguments)
console.log(bookJSON)
// {
// title: "幞ãã«ãªãããã®ãŠã©ã³ãããã®é",
// description: "ãŠã©ã³ãããã®ããã®å¹žãã®ç§èš£ã玹ä»ããæ¬ã§ãã幞ããªãŠã©ã³ãããã«ãªãããã®å¿ã®æã¡æ¹ãè¡åã®ã³ãã詳ãã解説ãããŠããŸããæ¯éèªãã§ã¿ãŠãã ããïŒ"
// }
åè
Function calling and other API updates
openai-cookbook/examples/How_to_call_functions_with_chat_models.ipynb at main · openai/openai-cookbook
OpenAI API
ä»åŸãAIã䜿ã£ããµãŒãã¹éçºã«ã€ããŠçºä¿¡ããŠãããŸãã®ã§ããã²Twitterãªã©ãã©ããŒãé¡ãããŸãã
ã³ãŒãã£ã³ã°ãAIã§èªååãããµãŒãã¹ãèããŸãã®ã§ãèå³ããæ¹ãã²äºåç»é²ãé¡ãããŸãð
Discussion