🧠

ChatGPTのfunction callingのGPT-3と4の相違点

2023/06/23に公開

function calling最高です

ChatGPTのfunction callingがリリースされましたね。

それが何かという解説は他の方がさんざん書いているのでバッサリ省略しますが、これがあればオレオレアレクサを誰でも簡単に作れるという真に破壊的な機能だと思います。

function callingを使えるモデルは現時点(2023/06/23)で、gpt-3.5-turbo-0613gpt-4-0613の二つです。

そこで、この二つのモデルでそれぞれfunction callingで比較実験して気づいたことをまとめました。

高速なGPT-3か、高品質なGPT-4か

3か4で迷うポイントとしては、GPT-3はレスポンスが高速、GPT-4は生成される結果テキストが高品質という事を予想すると思います。この想像を実際に計測してみました。

使った題材は、ChatGPTが登場してすぐのころに話題になった「覚えたい単語をいくつか羅列して、語学学習用にショートストーリーを作ってもらう」というテーマで実験しました。

作ったプロンプトは以下の通り。
プロンプトはChatGPTの最大能力を引き出すために英語で作り、作文する対象であるいわゆる「学習中の言語」はスペイン語ということにしました。プログラムはdartで書いてますがPythonだろうがTypeScriptだろうが同じはず。

これを各モデルで20回投げて結果を評価します。

ちなみに、関数としては「文章を作ってXMLにして、それを次のシステムに渡す」という関数にしています。関数の意味を表す動詞は「表示する」でも「保存する」でもよさそうでしたが、ChatGPTが「はい、それでは以下のXMLを、、、」という会話に陥らないように極力無機質な動詞にしています。(この考慮に効果があるかは未検証)

  Map<String, Object> createPrompt() {
    //final model = "gpt-4-0613";   //ここのコメントを付け替えて二つのモデルを切り替える
    final model = "gpt-3.5-turbo-0613";
    final prompt = {
      "model": model,
      "messages": [
        {
          "role": "user",
          "content": """
Please pass a story to the next system; the story should be short interesting Spanish story, using the words in a list below, enclosed in XML which only contain <story></story> tag, enclosing the words in the list with <strong originalWord="...">...</strong> tags.

              entregar
              cometer
              miembro
              acercar
              quejarse de

              """
        }
      ],
      "functions": [
        {
          "name": "passXMLStory",
          "description":
              "Takes a story in XML format and pass it to the next system.",
          "parameters": {
            "type": "object",
            "properties": {
              "xmlString": {
                "type": "string",
                "description":
                    """XML string to pass to the next system. The XML string should be enclosed in <story></story> tag, and the words in the list should be enclosed in <strong originalWord="...">...</strong> tags.
                    
                    This is an example of English story: If the specified word list is 

                      love
                      soccer 
                
                    And, for example, the generated sentence is "I loved to play soccer on the weekends.", then 

                    <?xml version="1.0" encoding="UTF-8"?>
                    <story>
                      I <strong originalWord="love">loved</strong> to play <strong originalWord="soccer">soccer</strong> on the weekends.
                    </story>
                    """
              },
            },
            "required": ["xmlString"]
          },
        },
      ],
    };
    return prompt;
  }

典型的なレスポンス

以下に参考までに典型的なレスポンスをそれぞれ挙げておきます。

一番の違いは、GPT-3がfunction_callの内容のみを純粋に返してくれるのに対し、GPT-4は無駄にcontent要素に"Sure, here is your story in XML format:..."などと重複した内容を出力しています。ただでさえ値段が高いのに、これでトークンを無駄にするかぐぬぬと思う状況です。

GPT-3

{
  "id": "chatcmpl-....",
  "object": "chat.completion",
  "created": 1687447538,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "function_call": {
          "name": "passXMLStory",
          "arguments": "{\n  \"xmlString\": \"<story>Desde que era un <strong originalWord=\\\"miembro\\\">miembro</strong> de la comunidad, siempre quise <strong originalWord=\\\"acercar\\\">acercar</strong> a las personas y <strong originalWord=\\\"entregar\\\">entregar</strong> mi tiempo para ayudar. Pero un día, cometí un error grave. Me <strong originalWord=\\\"quejarse de\\\">quejé de</strong> una situación sin saber toda la verdad. Me arrepentí y aprendí la importancia de investigar antes de <strong originalWord=\\\"cometer\\\">cometer</strong> juicios. A partir de ese día, siempre me aseguro de tener todos los hechos antes de formar una opinión.</story>\"\n}"
        }
      },
      "finish_reason": "function_call"
    }
  ],
  "usage": {
    "prompt_tokens": 283,
    "completion_tokens": 173,
    "total_tokens": 456
  }
}

GPT-4

{
  "id": "chatcmpl-....",
  "object": "chat.completion",
  "created": 1687446230,
  "model": "gpt-4-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Sure, here is your story in XML format:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<story>\nHoy mi <strong originalWord=\"miembro\">miembro</strong> de la familia decidió <strong originalWord=\"entregar\">entregar</strong> una queja. Mi primo se <strong originalWord=\"quejarse de\">quejó de</strong> los constantes errores que solía <strong originalWord=\"cometer\">cometer</strong> en su trabajo. Se <strong originalWord=\"acercar\">acercó</strong> a mí buscando ayuda, estaba realmente desesperado.\n</story>\n```\n\nNow, I will pass this XML story to the next system.\n\n",
        "function_call": {
          "name": "passXMLStory",
          "arguments": "{\n  \"xmlString\": \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\\n<story>\\nHoy mi <strong originalWord=\\\"miembro\\\">miembro</strong> de la familia decidió <strong originalWord=\\\"entregar\\\">entregar</strong> una queja. Mi primo se <strong originalWord=\\\"quejarse de\\\">quejó de</strong> los constantes errores que solía <strong originalWord=\\\"cometer\\\">cometer</strong> en su trabajo. Se <strong originalWord=\\\"acercar\\\">acercó</strong> a mí buscando ayuda, estaba realmente desesperado.\\n</story>\"\n}"
        }
      },
      "finish_reason": "function_call"
    }
  ],
  "usage": {
    "prompt_tokens": 283,
    "completion_tokens": 310,
    "total_tokens": 593
  }
}

結果と考察

個人的にこの語学学習ネタは通常のChatGPT画面でもさんざんやっていて、生成されるショートストーリーの品質は圧倒的にGPT-4が良いということはわかっています。

したがって、この語学学習などの目的であればぜひともGPT-4を使いたいところですが、単純にそうとも言い切れないというのが今回の実験でわかりました。

function calling成功率

プロンプトにfunctions要素を渡したとしても、毎回必ず「あ!これはfunction callingの出番か?」と気づいてもらえるとは限りません。

失敗すると、単純にいつものお話モードで返事が返ってきます。

このfunction calling成功率に関してはもう圧倒的にGPT-3が良い!

成功 失敗
gpt-3.5-turbo-0613 20回 0回
gpt-4-0613 11回 9回

これに関してはもしかしたらGPT-3は長い間github copilotで使われていたことによる一日の長があるのかも。(想像)

処理時間

以下が平均の処理時間です。いずれもfunction callingが成功した場合の処理時間のみで計算しています。

平均処理時間
gpt-3.5-turbo-0613 5.2秒
gpt-4-0613 36.4秒

当たり前ですが、GPT-3は非常にレスポンスが速い。しかし、GPT-3でも5秒かかるのは今回の題材が文章の生成まで行わせているからだと思います。

品質

ここまで見ると圧倒的にGPT-3でいいのではと思うのですが、GPT-3の欠点は結果のテキストの品質です。

文章の品質というのはふんわりしててわからないので、もっと明確に判定できる指標として、結果のXMLにきちんとXML宣言<?xml version="1.0" encoding="UTF-8"?>を付けているかどうかをカウントして判定しました。

いずれもfunction callingが成功した場合の中での、XML宣言付与率を計算しました。

XML宣言付与率
gpt-3.5-turbo-0613 60%
gpt-4-0613 100%

プロンプトではXMLを返すようにとか、作成するテキストの例にもXML宣言を明記しているので、ぜひつけてほしいところですが、GPT-3ではそこまで気持ちを汲んでいないようです。

ただこれは「XML宣言を付けるように」と明示すればいいと考えられます。ただ、ChatGPTのプロンプトというのはあまり長くなると明らかにその他の部分の精度が下がりますのでプロンプトを短く保ちながら正しい返答をしてくれるGPT-4は品質の面では優秀といえます。

さらに言うと、実験中に一度だけGPT-3は結果に含めるXMLを二重にエスケープしていて、結果をパースできないエラーが発生しました。こうことがまれに起こるのもGPT-3の欠点だと思います。

まとめと感想

このようにモデルの癖はあるのですが、とにかくfunction callingはすごい。

これまで、ChatGPTの出力をjsonやyamlに強制しようと四苦八苦していましたが、かなりの確率でお話し調で「はい、わかりました。以下のjsonにすればいいでしょう云々」のような前口上がついて、プログラムからの利用が煩雑だったと思います。

この点が劇的に改善されています。少なくともGPT-3を使えばほぼ100%狙ったフォーマットで結果を取得できるでしょう。
上で紹介した例は割と単純な引数のフォーマットでしたが、「string二つとbool一つからなるオブジェクトの配列」のような複雑なjsonも非常にうまく生成できることがわかっています。

スマホの音声認識、ChatGPTのfunction calling、スマホのテキスト読み上げ機能を連続で実行すれば、ただちにオレオレアレクサが完成すると思いますし、なんならアレクサより頭がいいものになるでしょう。(Amazonは恐怖しているのでは)

今回挙げた例は「文章生成+function calling」という例です。これができるのはすごい可能性があると思っていて、例えば「ChatGPT人狼ゲーム」とか、「ChatGPT占いアプリ」とか、特定フォーマットの文章を要求するシステムは全て開発が容易になるでしょう。

実用上は処理速度(とお値段)を考えるとGPT-3一択だと思いますが、数年以内にはこの機能が洗練されてGPT-4に世代交代すると予想しています。

この爆速の進化には全力でついていくしかない!!

Discussion