2023年11月7日火曜日

OpenAI ChatGPTのFunction Callingを使ってPL/SQLプロシージャを呼び出す

新しい記事で更新されています。

OpenAI Chat Completions APIのツール呼び出しを使ってPL/SQLファンクションを呼び出す
https://apexugj.blogspot.com/2024/04/chat-with-generative-ai-fc-sample-app.html

以下は過去の内容です。

以前にOpenAIのChatGPTのAPIを呼び出すサンプル・アプリケーションを作成しました。そのときの記事は「OpenAIのChatGPTのAPIを呼び出すAPEXアプリを作る」です。

今回は、以前の記事で作成したAPEXアプリケーションにFunction Callingを扱うコードを追加してみました。

OpenAIのブログ記事「Function calling and other API updates」を元にサンプルを実装しています。この記事では、都市を指定して現在の天気を質問しています。OpenAIの記事での質問は「What is the weather like in Boston?」ですが、今回作成したサンプル・アプリケーションには、「現在の東京の天気を教えてください。」と質問しています。

最初に質問を投げたときは、Function Set(これはOpenAIのAPIの引数ではなく、今回のサンプル・アプリケーションで作った設定です)の指定が無いため、API呼び出しに属性functionsが含まれず、ChatGPTからは「申し訳ありませんが、私は情報を提供することができません。」と返されています。2回目はFunction Callingが行われて外部の天気APIサービス(Open-Meteo.comを呼び出しています)より現在の東京の天気を取得しているため、「現在の東京の天気は「晴れ」です。」と回答されています。


上記のAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/chatgpt-app-fc.zip

以下より追加した実装について紹介します。

最初にfunction callingの呼び出し対象となるファンクションを登録する表を作成します。

クイックSQLの以下のモデルより、表OPENAI_FUNCTIONSOPENAI_FUNCTION_SETを作成します。


OPENAI_FUNCTIONSには、ファンクションの名前(APIでは属性name)、ファンクションの説明(属性description)およびファンクションのパラメータ定義(属性parameters)を定義します。手っ取り早く開発するため、parametersにはJSON形式のドキュメントをそのまま記述します。

OPENAI_FUNCTION_SETでは、表OPENAI_FUNCTIOINSに定義したファンクションをひとまとめにします。ChatGPTのAPIを呼び出す際に、ここで設定したファンクションセット名を指定することで、そのセットに含まれるファンションをAPIの属性functionsに含めます。

今回は表OPENAI_FUNCTIONSおよびOPENAI_FUNCTION_SETにデータが投入できるアプリケーションがあればよいので、クイックSQLによる表の生成からアプリケーションの作成までを、続けて実施します。


生成されたSQLスクリプトを即時実行した後、アプリケーションの作成を開始します。次に開く確認画面でも、アプリケーションの作成をクリックします。


アプリケーション作成ウィザードが起動します。表OPENAI_FUNCTIONSOPENAI_FUNCTION_SETレポートとフォームのページが追加済みになっています。

アプリケーションの名前OpenAI Function Callingとし、アプリケーションの作成を実行します。


アプリケーションが作成されます。

アプリケーションを実行し、ChatGPTから呼び出すファンクションを設定します。


OpenAIのブログ記事に従って、ファンクションget_current_weatherを定義します。

Functionsを開きます。


作成をクリックします。


Function nameとしてget_current_weatherDescriptionとしてGet the current weather in a given locationParametersには以下のJSONドキュメントを記述します。
{
  "type": "object",
  "properties": {
    "location": {
      "type": "string",
      "description": "The city and state, e.g. San Francisco, CA"
    },
    "unit": {
      "type": "string",
      "enum": [
        "celsius",
        "fahrenheit"
      ]
    }
  },
  "required": [
    "location"
  ]
}

ファンクションget_current_weatherが登録されました。このget_current_weatherは必ずPL/SQLのファンクションとして、CLOBの引数が1つ(JSONが渡されることを想定)、戻り値はCLOB(こちらもJSONが返されることを想定)であることを前提としています。

ファンクションget_current_weatherのコードは以下です。

都市名から緯度経度を求めるために、アマノ技研様が公開している「世界の百万都市の位置データ Location Data of Megacities」のCSVデータをダウンロードし、表AMANO_CITY_LOCATIONS(新規作成)にロードしています。データのロードには、SQLワークショップデータ・ワークショップを使用しています。

また、weathercodeについては「気象関連コード表」に記載されているWMO 4501のHTML表をデータ・ワークショップにコピペし、表WMO4501(新規作成)にロードしています。

ファンクションの登録は以上です。

Function Setのページを開き、作成をクリックします。


Functionとして先ほど作成したget_current_weatherを選択します。Function Set NameWeatherとします。

作成をクリックします。


ファンクション・セットWeatherが登録されました。


以前に作成したChatGPTのAPIを呼び出すアプリケーションに機能を追加します。

最初にプロシージャcall_openai_apiを作成します。以前は動的アクションサーバー側のコードを実行にコードを直書きしていましたが、コードが長くなりすぎ制限を超えてしまいました。

送信するアイテムは、P1_USER_MESSAGEP1_FUNCTION_SETです。戻すアイテムP1_REQUESTP1_RESPONSEです。戻すアイテムは両方ともデバッグ用途で、無くても問題ありません。


ファンクション・セットを指定するページ・アイテムを作成します。

識別名前P1_FUNCTION_SETタイプ選択リストです。ラベルFunction Setとします。LOVタイプSQL問合せを選択し、SQL問合せとして以下を記述します。

select function_set_name d, id r from openai_function_set
追加値の表示オフNULL値の表示オンとして、NULL表示値-- No function set assigned --を記述します。


デバッグ用にタイプ表示のみのページ・アイテムP1_REQUESTおよびP1_RESPONSEを作成します。


以上でFunction Callingの機能追加は完了です。アプリケーションを実行すると、記事の先頭のGIF動画のように動作します。

今回の記事は以上です。

Oracle APEXのアプリケーション作成の参考になれば幸いです。