見出し画像

OpenAI の Function Calling を使った天気予報プラグインの実装例

上記の記事で実装した天気予報プラグインを改良した。これで「宮城県仙台市の明日から一週間の天気を教えて下さい」という要求にもきちんと応えることができた。参考にしたコードをかなり改良した。折角なので具体的に内容を説明してみようと思う。

以下が最初の messages の内容である。"role":"system" の "content" で指示しているプロンプトが、Function Calling で期待通りの arguments を取得するために必要な部分である。元のコードの "description" を大幅に書き直している。

"messages" : [
  {
    "content" : "You may infer what values should be entered into the function, but do not make assumptions without evidence. Ask the user for clarification if the request is ambiguous.",
    "role" : "system"
  },
  {
    "content" : "宮城県仙台市の明日から一週間の天気を教えて下さい。",
    "role" : "user"
  }
],

次に function 本体の内容。"get_current_weather" は今日の天気予報の取得用で、"get_n_day_weather_forecast"  が日数で天気予報を取得する function である。そして、各 properties の "description" の内容が重要である。この記述を "role":"system" の "content" で記した内容と整合性が合う記述にしないと、期待通りに arguments を抽出してくれないので注意。要は矛盾した記述にすると API サーバ側でループするのか overload error となる。

また、"date" という項目も独自に追加している。これは入力メッセージ内の「今日」「明日」「明後日」という情報を抽出するためである。この情報は天気予報を取得する基準日として利用できる。"num_days" という項目に日数が設定されるので、"date" の基準日と "num_days" の日数で、取得した天気予報の範囲を決定できる。

"functions" : [
  {
    "name" : "get_current_weahter",
    "parameters" : {
      "type" : "object",
      "properties" : {
        "location" : {
          "type" : "string",
          "description" : "The city and state that user want to get the weather. If the user does not specify a location, set the English \"current\" to \"location\"."
        }
      },
      "required" : [
        "location"
      ]
    },
    "description" : "Get the current weather in a given location."
  },
  {
    "name" : "get_n_day_weather_forecast",
    "parameters" : {
      "type" : "object",
      "properties" : {
        "date" : {
          "type" : "string",
          "enum" : [
            "today",
            "tomorrow",
            "day after tomorrow",
            "other"
          ],
          "description" : "The date to be used for forecast. Infer this from the users message."
        },
        "location" : {
          "type" : "string",
          "description" : "The city and state that user want to get the weather. If the user does not specify a location, set the English \"current\" to \"location\"."
        },
        "num_days" : {
          "type" : "integer",
          "description" : "The number of days to forecast. Infer this from the users message. You can specify up to 9 days."
        }
      },
      "required" : [
        "location",
        "date",
        "num_days"
      ]
    },
    "description" : "Get an N-day weather forecast."
  }
]

API サーバからは次のように "function_call" が作成されて返ってくる。

"function_call" : {
  "name" : "get_n_day_weather_forecast",
  "arguments" : "{\n  \"date\": \"tomorrow\",\n  \"location\": \"宮城県仙台市\",\n  \"num_days\": 7\n}"
}

"location" に指定した「宮城県仙台市」の値と、"date" に「明日」を意味する "tomorrow"、"num_days" に「一週間」を表す "7" が期待通りに設定されている。あとは、この値を天気予報を取得するプログラムで利用するだけである。

もし利用者が場所を明示的に指定しなかった場合には、"location" に "current" という値が設定される。これは、iOS アプリでプラグイン機能を実装しているからである。"current" の値が設定されている場合、アプリが CoreLocation を使って現在地を測位して、その場所の天気予報データを取得する仕組みにしている。

次に示すスクリーンショットは実行したのが2023年6月22日木曜日である。「明日から一週間」の範囲で正しく天気予報を表示している。予報の精度は WeatherKit の値なので参考程度だね。

明日から一週間の天気の結果

実際のデータのログは次のような内容。ふたつめのオレンジ色の吹き出しが WeatherKit から得た天気予報の情報を JSON データに加工した内容である。今回は必要最小限のデータのみを使っている。ウェブサービスで利用するなら、WeatherKit 以外の他の天気予報 API から取得したデータを好みに加工して API サーバに送れば良い。


function_call と function の内容

OpenAI の Function Calling を使って天気予報を良い感じにやり取りできるようになった。以下のファイルは本文で示した "role":"system" を含んだテキストと "functions" の内容を含んだテキストである。文字コードは UTF-8 かな。必要に応じて活用してね。

最初に "messages" の内容全部を含んだファイル。

次は "functions" 全体のコード。

最後にちょっとだけ。"role":"system" に記述するプロンプトと "functions" の "properties" の "description" に記述する内容は、英語で指示した方が精度がかなり良くなる。日本語に翻訳して使って、上手く機能しないと言いそうな人が出て来るかもしれないので、念のため。


この記事が気に入ったらサポートをしてみませんか?