結論、画像を Data URI スキームにして url
パラメータとして送信します。
OPENAI_API_KEY=sk-proj-xxxxxxx
FILENAME=001.jpg
DATA_URI='data:image/jpeg;base64,'$(base64 -w0 ${FILENAME})
SYSTEM_PROMPT='このシステムは画像の内容を分析して、その説明を生成します。分析結果を日本語で回答します。'
USER_PROMPT='画像の中には何が映っていますか?'
RESULT=$(curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" -d @- << _EOJ_
{
"model": "gpt-4o",
"messages": [
{
"role": "system",
"content": "${SYSTEM_PROMPT}"
},
{
"role": "user",
"content": [
{ "type": "text", "text": "${USER_PROMPT}" },
{ "type": "image_url", "image_url": { "url": "${DATA_URI}" } }
]
}
],
"max_tokens": 300
}
_EOJ_
)
echo "$RESULT"
実行例 (echo には追加で jq を利用しています)
❯ OPENAI_API_KEY=sk-proj-xxxxxxx
❯ FILENAME=001.jpg
❯ DATA_URI='data:image/jpeg;base64,'$(base64 -w0 ${FILENAME})
❯ SYSTEM_PROMPT='このシステムは画像の内容を分析して、その説明を生成します。分析結果を日本語で回答します。'
❯ USER_PROMPT='画像の中には何が映っていますか?'
❯ RESULT=$(curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" -d @- << _EOJ_
{
"model": "gpt-4o",
"messages": [
{
"role": "system",
"content": "${SYSTEM_PROMPT}"
},
{
"role": "user",
"content": [
{ "type": "text", "text": "${USER_PROMPT}" },
{ "type": "image_url", "image_url": { "url": "${DATA_URI}" } }
]
}
],
"max_tokens": 300
}
_EOJ_
)
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 135k 100 1071 100 134k 111 14246 0:00:09 0:00:09 --:--:-- 235
❯ echo $RESULT | jq .
{
"id": "chatcmpl-9PjP4Gt4yeusAqrsqvAn5NIzem90x",
"object": "chat.completion",
"created": 1715919758,
"model": "gpt-4o-2024-05-13",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "画像には、東京羽田空港の夜景が映っています。滑走路や駐機場に飛行機が駐機している様子が確認できます。画像上部には「LIVE CAM 東京 羽田空港」と表示されています。\n\nまた、画像の左側には温湿度計が置かれており、温度が24.6℃、 湿度が52%と表示されています。右下には日時が表示されており、「2024-05-16 22:30:00」となっています。"
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 1151,
"completion_tokens": 117,
"total_tokens": 1268
},
"system_fingerprint": "fp_927397958d"
}
解説
OpenAI の GPT-4o は、マルチモーダルモデルであり、画像をプロンプトとして渡すことができます。具体的には url
というパラメータに、対象となる画像をセットします。Quick Start の curl サンプルコード では Wikimedia Commons の URL が使われています。
ローカルの画像は Uploading base 64 encoded imagesにもあるように、Data URI として送信できるのですが、サンプルコードが Python のみです。
そこで curl で送る方法を残しておいたというのが、この記事の趣旨になります。
Bash 上での 画像の Data URI 化
base64
等、Base64 エンコーディングができるコマンドがあれば、Data URI 化できます。以下は 001.jpg
ファイルを base64
コマンドを使って Data URI 化しています。
FILENAME=001.jpg
DATA_URI='data:image/jpeg;base64,'$(base64 -w0 ${FILENAME})
- PNG なら
data:image/png;base64,
です - base64 コマンドの注意点としては、デフォルトは 76 バイトで改行されます。
-w 0
として改行が起こらないように指定することです(もしかすると-b 0
の場合もあります)
金額
API は実行毎に課金が発生します。1920x1080の画像を gpt-4oで扱うと、一回当たり0.005525 USD(約0.9円)です。実行例のように、実行結果を変数に格納しておくことをおススメします。
解像度に対する金額は Pricing のページで確認できます。ちなみに gpt-4-turbo より、gpt-4oの方が安価です。
あとがき
シェル芸の記事になってしまった → シェル芸の部分を分離。参考記事をご覧くださいな。
参考記事
- Bashで「Argument list too long」が発生した時の対策
- Bashのコマンド置換+ヒアドキュメントで「warning: command substitution: 1 unterminated here-document」が発生した時の対策
EoT