Skip to content

Instantly share code, notes, and snippets.

@PonDad
Last active September 3, 2023 23:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PonDad/5f8bfb014ee76d34c05d46b3210893df to your computer and use it in GitHub Desktop.
Save PonDad/5f8bfb014ee76d34c05d46b3210893df to your computer and use it in GitHub Desktop.
Function calling Guide

Function calling(機能呼び出し)

API呼び出しにおいて、gpt-3.5-turbo-0613およびgpt-4-0613に関数を説明し、モデルが関数を呼び出すための引数を含むJSONオブジェクトを出力するように選択できます。Chat completions APIは関数を呼び出しません。代わりに、モデルは関数を呼び出すためのJSONを生成し、コード内でその関数を呼び出すために使用できます。

最新のモデル(gpt-3.5-turbo-0613およびgpt-4-0613)は、関数が呼び出されるべきかどうかを検出し(入力に依存)、関数のシグネチャに準拠したJSONで応答するように微調整されています。この機能には潜在的なリスクも伴います。ユーザーを代表して世界に影響を与える行動(メールの送信、オンラインへの投稿、購入など)を起こす前に、ユーザー確認フローを構築することを強くお勧めします。

Note 関数は、モデルが訓練された構文でシステムメッセージに注入されます。これは関数がモデルのコンテキスト制限に対してカウントされ、入力トークンとして請求されることを意味します。コンテキスト制限に達する場合、関数の数や関数パラメータの長さを制限することをお勧めします。

関数呼び出しを使用すると、モデルからより信頼性のある構造化データを取得できます。例えば、次のことができます:

  • 外部APIを呼び出して質問に答えるチャットボットを作成する(例:ChatGPTプラグインのような)
    • 例:send_email(to: string, body: string)もしくはget_current_weather(location: string, unit: 'celsius' | 'fahrenheit')のような関数を定義する。
  • 内部APIを呼び出すか、自然言語をAPI呼び出しに変換する
    • 例: "トップ顧客は誰ですか?"をget_customers(min_revenue: int, created_before: string, limit: int)に変換し、内部APIを呼び出す。
  • テキストから構造化データを抽出する。
    • 例:名前: string、誕生日: stringを含むextract_data(name: string, birthday: string)という関数を定義する、またはsql_query(query: string)を定義する

...など、さまざまな用途に活用できます!

関数呼び出しの基本的な手順は次のとおりです:

  1. ユーザーのクエリとfunctionsパラメータで定義された一連の関数を使用してモデルを呼び出します。
  2. モデルは関数を呼び出すことを選択できます。その場合、コンテンツはカスタムスキーマに従った文字列化されたJSONオブジェクトです(注意:モデルは無効なJSONを生成したり、パラメーターを作り出す可能性があります)。
  3. 文字列をJSONに解析し、提供された引数が存在する場合はそれらを使用して関数を呼び出します。
  4. モデルを再度呼び出し、関数の応答を新しいメッセージとして追加し、モデルに結果を要約させてユーザーに返します。

以下の例で、これらのステップの実際の動作を確認できます

import openai
import json

# 例の仮の関数、同じ天気を返すようにハードコードされています
# 本番では、これはバックエンドAPIまたは外部APIであるかもしれません
def get_current_weather(location, unit="fahrenheit"):
    """指定した場所の現在の天気を取得します"""
    weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["晴れ", "風が強い"],
    }
    return json.dumps(weather_info)

def run_conversation():
    # ステップ1: 会話と利用可能な関数をGPTに送信
    messages = [{"role": "user", "content": "ボストンの天気はどうですか?"}]
    functions = [
        {
            "name": "get_current_weather",
            "description": "指定した場所の現在の天気を取得します",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "都市と州、例:サンフランシスコ、CA",
                    },
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["location"],
            },
        }
    ]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=functions,
        function_call="auto",  # autoはデフォルトですが、明示的に指定します
    )
    response_message = response["choices"][0]["message"]

    # ステップ2: GPTが関数を呼び出すことを希望しているか確認します
    if response_message.get("function_call"):
        # ステップ3: 関数を呼び出します
        # 注意: JSONの応答が常に有効でない場合があるため、エラーを処理することを確認してください
        available_functions = {
            "get_current_weather": get_current_weather,
        }  # この例では関数が1つだけですが、複数持つことができます
        function_name = response_message["function_call"]["name"]
        fuction_to_call = available_functions[function_name]
        function_args = json.loads(response_message["function_call"]["arguments"])
        function_response = fuction_to_call(
            location=function_args.get("location"),
            unit=function_args.get("unit"),
        )

        # ステップ4: 関数呼び出しと関数の応答情報をGPTに送信します
        messages.append(response_message)  # アシスタントの返信と会話を拡張
        messages.append(
            {
                "role": "function",
                "name": function_name,
                "content": function_response,
            }
        )  # 関数の応答と会話を拡張
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=messages,
        )  # GPTから新しい応答を取得し、関数の応答が見えるようにします
        return second_response

print(run_conversation())

Note 関数呼び出し時の幻覚的な出力は、システムメッセージを使用することでしばしば緩和できます。例えば、モデルが提供されていない関数を使用して関数呼び出しを生成している場合、次のようなシステムメッセージを使用してみてください:"提供された関数のみを使用してください。"

上記の例では、関数の応答をモデルに送り返し、次のステップをモデルに決定させました。モデルはユーザー向けのメッセージでユーザーにボストンの気温を伝えましたが、クエリに応じて、再び関数を呼び出すことを選択することがあります。

例えば、モデルに「週末のボストンの天気を調べて、土曜日に2人用のディナーを予約し、カレンダーを更新してください」と尋ね、これらのクエリに対応する関数を提供する場合、モデルはこれらの関数を連続して呼び出し、最後にユーザー向けのメッセージを生成することを選択するかもしれません。

特定の関数をモデルに呼び出させる場合、function_call: {"name": "<insert-function-name>"} と設定できます。また、モデルにユーザー向けのメッセージを生成させる場合は、function_call: "none" と設定できます。デフォルトの動作(function_call: "auto")では、モデルは自分で関数を呼び出すかどうか、そして呼び出す場合にどの関数を呼び出すかを自動で決定します。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment