12
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

バッチ処理革命。コンバータもgpt-3.5-turbo (ChatGPT API)でほぼ作れてしまうという話

Posted at

結論

gpt-3.5-turbo が下記の性能をもつため、バッチシステムのコンバータでの商用利用が十分可能そうです

  1. コストが比較的安い (1000 tokenで0.002USD)
  2. messages の工夫とtemperature=0の指定で出力形式が安定する(システムに組み込むために重要)
  3. messages の工夫で性能を改善できる(コードが全く書けなくても!コードが書ける人でも普通にコード書くよりも全然早く作れそう)

検証内容

今回、対象にしたコンバータは経産省の住所変換コンポーネントです。ここのreadmeに記載のアウトプットのフォーマットは以下です

{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "霞が関2-1-10",
    "都道府県": "東京都",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C13000",
    "市区町村": "千代田区",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C13101",
    "町名": "霞が関",
    "丁目": "2",
    "番地": "1",
    "号": "10"
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "35.675551",
    "経度": "139.750413"
  }
}

これはinputもjson形式で書く必要がありますが、文字列を受け付けてそれっぽく返すか検証します。

検証結果

messages に指定するための文字列です。*ここのパターンの工夫次第で性能はまだまだあがりそうです

role_system ='日本の住所をパースする機能。IMI語彙記法の規約に従う'

question_1 = "霞が関2-1-10"
answer_1 = '''{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "霞が関2-1-10",
    "都道府県": "東京都",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C13000",
    "市区町村": "千代田区",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C13101",
    "町名": "霞が関",
    "丁目": "2",
    "番地": "1",
    "号": "10"
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "35.675551",
    "経度": "139.750413"
  }
}'''
question_2 = "霞が関 二の一の十"
answer_2 = '''{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "霞が関2-1-10",
    "都道府県": "東京都",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C13000",
    "市区町村": "千代田区",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C13101",
    "町名": "霞が関",
    "丁目": "2",
    "番地": "1",
    "号": "10"
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "35.675551",
    "経度": "139.750413"
  }
}'''

question_3 = "東京都千代田区霞が関2丁目1番地10号"
answer_3 = '''{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "霞が関2-1-10",
    "都道府県": "東京都",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C13000",
    "市区町村": "千代田区",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C13101",
    "町名": "霞が関",
    "丁目": "2",
    "番地": "1",
    "号": "10"
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "35.675551",
    "経度": "139.750413"
  }
}'''


問い合わせてみます

ask = "東京都千代田区千代田1番1号"

res = openai.ChatCompletion.create(
  model="gpt-3.5-turbo-0301",
  messages=[
        {"role": "system", "content": role_system},
        {"role": "user", "content": question_1},
        {"role": "assistant", "content": answer_1},
        {"role": "user", "content": question_2},
        {"role": "assistant", "content": answer_2},
        {"role": "user", "content": question_3},
        {"role": "assistant", "content": answer_3},
        {"role": "user", "content": ask}
    ]
)
print(res["choices"][0]["message"]["content"])

その出力

{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "千代田1-1",
    "都道府県": "東京都",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C13000",
    "市区町村": "千代田区",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C13101",
    "町名": "千代田",
    "丁目": "1",
    "番地": "1",
    "号": ""
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "35.693840",
    "経度": "139.753136"
  }
}

地理座標もだいたい正しく(番地単位では不正確)、市区町村コードも正しい結果が返ってきました。

以降、askの変数だけのせます

Qiita社の住所
入力

ask = "愛知県名古屋市中村区名駅3-28-12"

結果

{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "愛知県名古屋市中村区名駅3-28-12",
    "都道府県": "愛知県",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C23000",
    "市区町村": "名古屋市中村区",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C23208",
    "町名": "名駅",
    "丁目": "3",
    "番地": "28",
    "号": "12"
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "35.170764",
    "経度": "136.881032"
  }
}

すげぇ!!!

https://qiita.com/miya0001/items/598070abcdf0799daebc を参考に鼻血がでそうな入力で試します

入力

ask = "京都府京都市東山区大和大路通正面下る大和大路2"

出力

{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "京都府京都市東山区大和大路通正面下る大和大路2",
    "都道府県": "京都府",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C26000",
    "市区町村": "京都市東山区",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C26105",
    "町名": "",
    "丁目": "",
    "番地": "大和大路通正面下る",
    "号": "2"
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "34.994032",
    "経度": "135.771858"
  }
}

入力

ask = "七尾市藤橋町亥45番地1"

出力

{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "七尾市藤橋町亥45-1",
    "都道府県": "石川県",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C17000",
    "市区町村": "七尾市",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C17206",
    "町名": "藤橋町",
    "丁目": "",
    "番地": "亥45",
    "号": "1"
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "37.042778",
    "経度": "136.964167"
  }
}

おしい!

最後にプロンプトをチューニングしたらいけるか検証

answer_4 = '''{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "京都府京都市東山区大和大路通正面下る大和大路2",
    "都道府県": "京都府",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C26000",
    "市区町村": "京都市東山区",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C26105",
    "町名": "大和大路",
    "丁目": "2",
    "番地": "",
    "号": ""
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "34.990157",
    "経度": "135.771012"
  }
}'''

question_5 = "七尾市藤橋町亥45番地1"
answer_5 = '''{
  "@type": "場所型",
  "住所": {
    "@type": "住所型",
    "表記": "石川県七尾市藤橋町亥45-1",
    "都道府県": "石川県",
    "都道府県コード": "http://data.e-stat.go.jp/lod/sac/C17000",
    "市区町村": "七尾市",
    "市区町村コード": "http://data.e-stat.go.jp/lod/sac/C17205",
    "町名": "藤橋町",
    "丁目": "1",
    "番地": "45",
    "号": "1"
  },
  "地理座標": {
    "@type": "座標型",
    "緯度": "37.037160",
    "経度": "136.953824"
  }
}'''

ask = "京都府京都市東山区大和大路通正面下る大和大路1"

res = openai.ChatCompletion.create(
  model="gpt-3.5-turbo-0301",
  messages=[
        {"role": "system", "content": role_system},
        {"role": "user", "content": question_1},
        {"role": "assistant", "content": answer_1},
        {"role": "user", "content": question_2},
        {"role": "assistant", "content": answer_2},
        {"role": "user", "content": question_3},
        {"role": "assistant", "content": answer_3},
        {"role": "user", "content": question_4},
        {"role": "assistant", "content": answer_4},
        {"role": "user", "content": question_5},
        {"role": "assistant", "content": answer_5},
        {"role": "user", "content": ask}
    ],
  temperature=0
)

print(res["choices"][0]["message"]["content"])

出力

申し訳ありませんが、京都市東山区には「大和大路通正面下る大和大路1」という住所は存在しません。もう一度住所を確認していただけますか?

流石に難しいか

気になるお値段ですが、Qiita社の住所のケースで1027tokenだったので、約0.002USDです。本当に大量に使う場合はChatGPT APIを叩く前にキャッシュするとか工夫できそうですが、0から開発するコストを考えるとかなり安いはずです。

今回はすでに公開されている開発済みのコンバータの再現なので、そのままの需要はなさそうですが、新規で新しいコンバータを開発するさいは、こんな感じで入出力のサンプルだけ用意しておけば、かなりの性能が出ますし、自前で開発してもどうせエッジケースの処理は苦しむので、まずは試してみる!が良さそうです

これはバッチ処理でも革命が起こりそうです

12
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?