2023年6月18日日曜日

OpenAI API の関数呼び出しで自作 Web API からデータ取得をしてみる

OpenAI API で新しく関数呼び出しという機能が追加されましたね。使えるモデルは gpt-4-0613 と gpt-3.5-turbo-0613 になります。

まだ全然理解が追いついていないのですが、せっかくだから雰囲気で何か作ってみよう!

……ということで、この新機能を使って、青果物市況情報の自作 Web API からデータの取得をしてみました。

今回取得を試みるは、東京都中央卸売市場大田市場のだいこんのデータです。以下のような JSON 形式となっています。

{"Date":"2023/06/17","MarketName":"大田","MarketCode":"13310","だいこん":{"ItemCode":"30100","青森":{"ProductionAreaCode":"002","ItemsTotal":"145.4","IncomingVolume":"87.7","HighPrice":"1404","MediumPrice":"1188","LowPrice":"1080","Grade":"A","Class":"L","VarietyName":"青首","WeightPerPackage":"10.0","MarketTrend":"弱保合"},"千葉":{"ProductionAreaCode":"012","ItemsTotal":"nan","IncomingVolume":"20.7","HighPrice":"-","MediumPrice":"432","LowPrice":"-","Grade":"nan","Class":"L","VarietyName":"青首","WeightPerPackage":"10.0","MarketTrend":"nan"}}}


・function_calling.py

import openai
import json
import requests
import urllib3

openai.api_key = "OpenAI API キー"

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def get_mcdata(mc, ic):
    url = "https://api.cultivationdata.net/mcdata"
    parameters = {
        "mc": mc,
        "ic": ic}
    response = requests.get(url, params=parameters, verify=False)
    if response.status_code == 200:
        data = response.json()
        return json.dumps(data)
    else:
        return None

path = 'pr.txt'
with open(path) as f:
    pr = f.read()

mcdata_function =  {
    "name": "get_mcdata",
      "description": "https://api.cultivationdata.net/mcdata から青果物市況情報を取得",
      "parameters": {
          "type": "object",
          "properties": {
              "mc": {
                  "type": "number",
                  "description": "市場コード",
              },
              "ic": {
                  "type": "string",
                  "description": "品目コード",
              },
          },
          "required": ["mc", "ic"],
      },
}

def main(que):
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=[{"role": "system", "content": pr},
                  {"role": "user", "content": que}
        ],
        functions=[mcdata_function],
        function_call="auto"
    )
    message = response["choices"][0]["message"]
    if message.get("function_call"):
        function_name = message["function_call"]["name"]
        arguments=json.loads(message["function_call"]["arguments"])
        function_response = get_mcdata(
            mc=arguments.get("mc"),
            ic=arguments.get("ic"),
        )
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=[
                {"role": "system", "content": pr}, 
                {"role": "user", "content": que},
                message,
                {
                    "role": "function",
                    "name": function_name,
                    "content": function_response,
                },
            ]
        )
        return second_response.choices[0]["message"]["content"].strip()

print(main("大田市場のだいこんの情報"))


・pr.txt

system ロールに渡す市場コードと品目コードの情報。記述は JSON 形式が間違いなさそう。(トークン数を少なくするために、一部のみ記載)

{
  "市場コード(mc)": {
    "東京都中央卸売市場豊洲市場": "30100",
    "東京都中央卸売市場大田市場": "13310",
  },
  "品目コード(ic)": {
    "だいこん":	"30100"
    "かぶ":	"30200"
  }
}


・実行結果

うまくいくと、こんな感じでデータの取得ができます。

【大田市場】
品目:だいこん
品目コード:30100

【青首】
産地コード:002
出荷総量:145.4トン
入荷量:87.7トン
最高価格:1,404円/10kg
平均価格:1,188円/10kg
最低価格:1,080円/10kg
等級:A
品質:L
品種名:青首
1パックあたりの重量:10.0kg
市場の動向:弱保合

【千葉】
産地コード:012
出荷総量:データなし
入荷量:20.7トン
最高価格:データなし
平均価格:432円/10kg
最低価格:データなし
等級:データなし
品質:L
品種名:青首
1パックあたりの重量:10.0kg
市場の動向:データなし

以上が大田市場におけるだいこんの情報です。

ただ、安定的にデータの取得ができるわけではなく、取れたり取れなかったり、取れても一部だけだったり、【青森】になってほしいところが【青首】になってたりするようです。

temperature を0で指定することで、安定的にデータを取得できないだろうかとも思って試してみたのですが、これはダメでした。逆に「大田市場のだいこんの情報は見つかりませんでした。申し訳ありません。」と、常に取得に失敗するようになりました。奥が深いですね。

ちなみに、今回は関数呼び出し機能を試すためにやっていますが、実際に何かのプログラムに組み込むとしたら Web API からのデータ取得を AI 経由にする必要はなさそうです(データを取得してから AI に渡した方がよさそう)。




独習Python
独習Python

by SimpleImageLink


***

日に日に進歩していきますね。とりあえず、よく分からなくてもさわっておくのが大事かなと思っています。


ベランダで咲いた白桔梗


Twitter (@nkkmd) 日々更新中です。