JSON データで回答をもらう Function calling

9d2c38e6fe48e61528f6b2d34370768f

この章で学ぶこと

JSON データで回答をもらう Function calling を体験してみましょう。

Function calling とは

a1f7897a372818e2ff4434090aa0589e

Web 版の ChatGPT や、通常の ChatGPT API のレスポンスを使ってしまうと、このように人間にわかる言葉で返してしまうので、IT の他の仕組みに使う上では、再度、人間の言葉をプログラムに合うように、特定の文字列判定や、名詞や品詞などを文章の中から取り出す形態素解析が必要になって扱いづらいところがあります。

023c1f6c8e309c3e38a1afe378a6e853

Function calling とは、人間のわかる自然な言葉ではなく、私たちからあらかじめ決めた JSON データのルールにしたがって、IT の他の仕組みで扱いやすい JSON データで返答してくれる機能です。

今日動かす仕組み

d4a61f659270023b5d896c2736238e5b

このように IoT 的なライトのオンオフを想定した返答を返す仕組みです。

「ライトをつけて」とお願いすれば {"command":"on"} という JSON データを返答し、「ライトを消して」とお願いすれば {"command":"off"} という JSON データを返答します。

プログラムを編集

起動してる Codedpace で、エクスプローラから sample02.js をダブルクリックしてエディタで開きます。

// OpenAI API キー
const OPENAI_API_KEY = "OPENAI_API_KEY";

// openai ライブラリの読み込み
const OpenAI = require("openai");

// OpenAI の API を使うために上記の設定を割り当てて準備
// 以後 openai というオブジェクトで使える
const openai = new OpenAI({
  apiKey: OPENAI_API_KEY
});

// async つきで実行
// 外部の API (OpenAPI) とのやり取りが伴うので待つ処理が必要
async function main() {

  // 質問内容
  const questionText = `ライトをつけて`;

  // 実際に ChatGPT にお願いするテキスト
  // テンプレートリテラルのバッククォート「`」を使っているので複数行できる
  const promptText = `
- 「ライトをつけて」とお願いしたら on_command を使います
- 「ライトを消して」とお願いしたら off_command を使います

今回のお願いは「${questionText}」です。
`;

  console.log("実際に ChatGPT にお願いするテキスト");
  console.log(promptText);

  // Function calling の設定
  const functions = [
    {
        "name": "on_command",
        "description": "「ライトをつけて」とお願いしたときに使います。",
        "parameters": {
            "type": "object",
            "properties": {
                "command": {
                    "type": "string",
                    "description": "on が固定値で入ります"
                }
            },
            "required": [
                "command"
            ]
        }
    },
    {
        "name": "off_command",
        "description": "「ライトを消して」とお願いしたときに使います。",
        "parameters": {
            "type": "object",
            "properties": {
                "command": {
                    "type": "string",
                    "description": "off が固定値で入ります"
                }
            },
            "required": [
                "command"
            ]
        }
    }
  ];

  // ChatGPT API に実際にアクセス
  // https://platform.openai.com/docs/guides/gpt/chat-completions-api?lang=node.js
  // https://platform.openai.com/docs/guides/gpt/function-calling
  const completion = await openai.chat.completions.create({
    messages: [
      // 質問内容
      { role: "user", content: promptText }
    ],
    // Function calling を使うためにモデルは gpt-3.5-turbo-0613 を使います。
    model: "gpt-3.5-turbo-0613",
    functions:functions,
    function_call: "auto"
  });

  // function calling の結果取得
  if (completion.choices[0].message.function_call) {
    const functionData = JSON.parse(completion.choices[0].message.function_call.arguments);

    console.log("function calling の結果取得");
    console.log(functionData);
  }

}

// 実行
main();

OpenAI API キーを反映します。

// OpenAI API キー
const OPENAI_API_KEY = "OPENAI_API_KEY";

"OPENAI_API_KEY" のダブルクオーテーションは残して OpenAI 社の API キーを入力します。

もし、API キーが ABCDEFGHIJKLMNOPQRSTUV だとすると、ダブルクオーテーションは残して

// OpenAI API キー
const OPENAI_API_KEY = "ABCDEFGHIJKLMNOPQRSTUV";

と変更します。

プログラムの解説

  // ChatGPT API に実際にアクセス
  // https://platform.openai.com/docs/guides/gpt/chat-completions-api?lang=node.js
  // https://platform.openai.com/docs/guides/gpt/function-calling
  const completion = await openai.chat.completions.create({
    messages: [
      // 質問内容
      { role: "user", content: promptText }
    ],
    // Function calling を使うためにモデルは gpt-3.5-turbo-0613 を使います。
    model: "gpt-3.5-turbo-0613",
    functions:functions,
    function_call: "auto"
  });

まず、ChatGPT API に実際にアクセスする部分です。

Function calling を使うためにモデルは gpt-3.5-turbo-0613 を使います。そのほか Function calling 用に functions 値や、複数の function calling 候補が挙がった場合にに自動で選ばせる auto 値があります。

  // Function calling の設定
  const functions = [
    {
        "name": "on_command",
        "description": "「ライトをつけて」とお願いしたときに使います。",
        "parameters": {
            "type": "object",
            "properties": {
                "command": {
                    "type": "string",
                    "description": "on が固定値で入ります"
                }
            },
            "required": [
                "command"
            ]
        }
    },
    {
        "name": "off_command",
        "description": "「ライトを消して」とお願いしたときに使います。",
        "parameters": {
            "type": "object",
            "properties": {
                "command": {
                    "type": "string",
                    "description": "off が固定値で入ります"
                }
            },
            "required": [
                "command"
            ]
        }
    }
  ];

Function calling の設定はこのようになっています。まず、最上部は配列でルールを複数指定できます。

それ以下は、

  • name
    • 質問側から見た名指しできる名前です
    • この後、実際の質問内容でどう関連するか説明します
    • 今回は on_command がオンのルール、off_commandがオフのルールになっています。
  • description
    • 質問内容に応じてどういう役割かの説明です。
    • 分岐を決めるので、とても大切。通常の質問作成時と同じパワーで練る。
  • parameters
    • 該当したルールがあった時のデータの内容
  • parameters.type
    • 最上部の値のタイプ
    • 今回の object は JSON オブジェクトで受け取れる意味合い
    • number・boolean・array・string も指定できる
  • properties
    • 実際の値の中身
    • "command": { と書いているのは command 値を作ってねという意味
    • command の中身
      • type
        • それぞれの値のタイプ
        • string なので文字列という意味
      • description
        • 今回は固定値でほしいので「off が固定値で入ります」

このような意味合いになっています。

  // 質問内容
  const questionText = `ライトをつけて`;

  // 実際に ChatGPT にお願いするテキスト
  // テンプレートリテラルのバッククォート「`」を使っているので複数行できる
  const promptText = `
- 「ライトをつけて」とお願いしたら on_command を使います
- 「ライトを消して」とお願いしたら off_command を使います

今回のお願いは「${questionText}」です。
`;

そして、通常の質問は、さきほどの name を元に作っています。今回は on_command がオンのルール、off_commandがオフのルールになっているので、このような分岐を箇条書きしていて 今回のお願いは「${questionText}」です。 という形で「ライトをつけて」を判定するようにしています。

この「ライトをつけて」の部分は、センサーから来る値だったり、音声入力で文字起こしされたテキストであったり、外部から来る入力値になります。

プログラムの起動

ターミナルで以下のコマンド入力します。

node sample02.js

Enter キーを押してプログラムを実行します。

e015c36e79530271089e9e176aa8ed55

このような返答が ChatGPT API から返答されるはずです。

実際に ChatGPT にお願いするテキスト

- 「ライトをつけて」とお願いしたら on_command を使います
- 「ライトを消して」とお願いしたら off_command を使います

今回のお願いは「ライトをつけて」です。

function calling の結果取得
{ command: 'on' }

ライトを消してで試してみましょう

  // 質問内容
  const questionText = `ライトをつけて`;

「ライトをつけて」を「ライトを消して」にして実行して { command: 'off' } が来るか試してみましょう。

すこしブレさせて試してみましょう

他にも「つけて」「オフにして」など多少言葉をブレさせてみても結構受け止められるので試してみましょう。

もはや言葉で作るプログラムに近い

f7ff60ba26e5b688ceef9ddcc7e4f2f9

Function calling を体験してみましたが、これはもはや言葉で作るプログラムに近いです。まず、通常の質問で良い具合に動く内容ができたら Function calling 用に分解するといいと思います。

参考資料

こちらも体験してみましょう。

functions 値は以下に変更します。

[
    {
        "name": "rgb_json",
        "description": "色名から RGB 値の情報を得られた場合",
        "parameters": {
            "type": "object",
            "properties": {
                "type": {
                    "type": "string",
                    "description": "led という値が固定値を入力されます"
                },
                "result": {
                    "type": "boolean",
                    "description": "色名が RGB値 で認識されたので true は認識が入ります。"
                },
                "r": {
                    "type": "number",
                    "description": "色名から RGB 値の情報を得たときの R 値"
                },
                "g": {
                    "type": "number",
                    "description": "色名から RGB 値の情報を得たときの G 値"
                },
                "b": {
                    "type": "number",
                    "description": "色名から RGB 値の情報を得たときの B 値"
                },
                "message": {
                    "type": "string",
                    "description": "色名がRGB値に認識されたときの追加の説明。"
                }
            },
            "required": [
                "type",
                "result",
                "r",
                "g",
                "b",
                "message"
            ]
        }
    },
    {
        "name": "rgb_json_not_found",
        "description": "色名から RGB 値の情報を得られなかった場合",
        "parameters": {
            "type": "object",
            "properties": {
                "type": {
                    "type": "string",
                    "description": "led という値が固定値を入力されます"
                },
                "result": {
                    "type": "boolean",
                    "description": "色名が RGB値 で認識されなかったので false が入ります。"
                },
                "message": {
                    "type": "string",
                    "description": "色名が RGB 値に認識されなかったときの説明。あるいは、色名がRGB値に認識されなかったときの説明。色名の例外は「色名が認識されない例外処理です」と説明します。"
                }
            },
            "required": [
                "type",
                "result",
                "message"
            ]
        }
    }
]

promptText 値は以下に変更します。

  // 質問内容
  const questionText = `赤でお願いします。`;

  // 実際に ChatGPT にお願いするテキスト
  // テンプレートリテラルのバッククォート「`」を使っているので複数行できる
  const promptText = `
今回は「${questionText}」という色名がRGB値で返答ください。
色名がRGB値で認識されたら rgb_json を使います。
色名がRGB値で認識されない場合は rgb_json_not_found を使います。
`;

results matching ""

    No results matching ""