概要
GPT-4V(GPT-4 Trubo with Vision)が登場して数ヶ月。日本語は苦手とのこと1だったので、そんな使えないんだろうと思ってましたが、実は結構イケるとも聞いたので今回触ってみようと思います。
本記事の目的は、GPT-4Vを触ったことがない人に向けて、1分くらいで「あぁ、こんな感じなのね」とか「がんばればアレに使えそうだな」といったことを感じてもらうことを目的としています。
今回のタスク
本記事では、コインパーキングの看板情報を読み取ることをタスクをとして設定します。
看板からの情報だけでも、1時間毎の料金、土日や時間帯による金額の差、入庫から何時間まではいくら、といったように様々な情報や表記があります。今回はシンプルなタスクにしたいので、ある1社(タイムズ)の看板だけを対象とします。また単位時間あたりの課金額(基本料金というらしい)の読み取りを対象とします。
※図はコインパーキング各社の看板。住所や電話番号は記事に貼り付ける際、塗りつぶしています。
方針
精度良く情報を抽出するにはプロンプトエンジニアリングを頑張る必要があります。ただ闇雲に様々なテクニックを試すのは大変なのでAzure OpenAI ServiceのGPT-4 Turbo with Vision を使用したプロンプト設計の概要を参考にします。
今回のタスクでは「例の追加(adding-examples)」を試すと精度が上がりそうです。これはいわゆるFew Shot Learningと呼ばれる方法で、ユーザーが準備した入出力の例をプロンプトに入れて回答精度を上げる方法です。
※図はGPT-4Vのfew shot learningの例(GPT-4 Turbo with Vision を使用したプロンプト設計の概要より)
コード
tips
コードは公式サイトに乗っているコードとほぼ同じなので解説は省略します。細かい留意点のみ以下にまとめます。
-
Few Shotの書き方
- Few Shotの入出力例はそれぞれ
user
とassistant
ロールに記載しました - すべて
user
ロールに書く意見も見かけましたが2、GPT-4Vで私が試した所ロールを分けたほうが回答が安定するため分けることにします - 私見:いつもlangchainに頼り切っているので、どちらのほうが適切なのか把握していません。もし知っている方がいましたら教えてください<(_ _)>
- Few Shotの入出力例はそれぞれ
-
max_tokens(出力トークン数の上限)
- デフォルトのmax_tokensは非常に小さいため、適当な値を設定しましょう
- 私見:とりあえず、最大の4096を設定しておけば良いのでは?
-
detail
- 入力画像を解像度高く読み取る
detail : high
か、粗く読み取るdetail : low
か選ぶことができます - lowの場合、消費トークン数は85tokenで固定です
- hightのトークン数の計算は少し複雑です3。先程の看板画像程度なら1000token弱程度ですが、画像のピクセル数に応じて増加します
- 私見:今回の看板から文字を読取る場合だと、lowでは難しそうでした
- 入力画像を解像度高く読み取る
FewShotコード例
以下の4つの画像をFew-Shotに使用し、出力してほしい回答文を4つ作成します。質問文も出力してほしい回答文と整合性があるような質問文を設定します。
question ="""この看板の画像から、基本料金の情報を抽出し箇条書きで出力してください。
出力方法は「* XXの基本料金はYY分ごとにZZ円です。」という形式で出力してください。
最大料金は記載してはいけません。"""
qa_examples = [
{
"input_path":"./sampleimgs/signboard_001.png",
"output":"* 8:00-22:00の基本料金は40分ごとに220円です。\n* 22:00-8:00の基本料金は60分ごとに110円です。"
},
{
"input_path":"./sampleimgs/signboard_002.png",
"output":"* 8:00-22:00の基本料金は60分ごとに330円です。\n* 22:00-8:00の基本料金は60分ごとに110円です。"
},
{
"input_path":"./sampleimgs/signboard_003.png",
"output":"* 8:00〜20:00の基本料金は12分ごとに440円です。\n* 20:00〜8:00の基本料金は60分ごとに110円です。"
},
{
"input_path":"./sampleimgs/signboard_004.png",
"output":"* 終日の基本料金は12分ごとに110円です。"
},
]
few_shot_messages = []
for qa_example in qa_examples:
few_shot_messages.append({
"role": "user",
"content": [
{"type": "text", "text":question},
{"type": "image_url","image_url": {"url": f"data:image/jpeg;base64,"+encode_image(qa_example['input_path']), "detail":"high"}},
],
})
few_shot_messages.append({
"role": "assistant",
"content":[{"type": "text", "text": qa_example['output']}]
})
Few Shotを会話履歴の先頭に付けて、実行します。
image_path = "./sampleimgs/signboard_005.png"
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4-vision-preview",
messages= few_shot_messages + [
{
"role": "user",
"content":[
{"type": "text", "text": question},
{"type": "image_url","image_url": {
"url": f"data:image/jpeg;base64,"+encode_image(image_path),
"detail":"high"
}},
],
},
],
max_tokens=4096,
)
print(response)
結果
9つの画像で、GPT-4V + Few-Shotを使用して情報抽出した結果をまとめます。
というわけで、だいたい正確に回答できますが、画像が荒い場合やフォーマットが少し異なる場合上手く回答できないこともあるようです。また今回は、回答文を短く指定したためChain of Thoughtをさせることができなかったことも、精度を挙げられなかった理由かもしれません。
ちなみに、
- 回答ひとつあたり応答時間は10数秒程度でした
- 金額は入力が5000token(0.05ドル)、出力が50token(0.0015ドル)程度のため8円くらいですかね
- 高いですね、画像を4枚も使ってfew-shotしてるからでしょう
GPT-4Vをさらに使いこなすには
Xで見かけたのですが、画像に座標を埋め込んでおくと精度が上がるらしいです。
-
。
Non-English: The model may not perform optimally when handling images with text of non-Latin alphabets, such as Japanese or Korean.
https://platform.openai.com/docs/guides/vision/limitations ↩ -
https://community.openai.com/t/few-shot-learning-with-gpt-4-is-it-needed-and-what-is-best-practice/455716 ↩