OpenAI ChatGPT API の画像認識 Vision に Node-RED で画像を読み込んでやりとりするメモです。
OpenAI ChatGPT API の画像認識 Vision 文献
2024/7/17 時点の情報で進めます。
文献はこちらです。
ここの base64 データでやりとりする内容を参考にします。2024/07/17 現在 image_url の部分に base64 でデータを入力するといいようです。
ローカルに画像をダウンロードしておく
今回は クリスマスベルの無料アイコン2 をダウンロードしておきます。今回は PNG ファイルで動作するようにしています。
Node-RED から呼び出せるようファイルパスのフルパスをメモしておきます。
Node-RED のフロー
Node-RED のフローです。
上部の「画像パス指定」という change ノードで設定したファイルパスを隣の「読み込み→base64」と書かれている file in ノードで読み込むと base64 データが流れていき、下部の 「API 設定」と書かれている change ノードで OpenAI の Vision の API を設定、「message 設定」で先ほどのファイルの base64 データを API 設定の JSON データに追加して http request ノードで OpenAI API とやり取りするフローです。
[{"id":"8f3094007e83c327","type":"inject","z":"fd3f534ff253d004","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":1060,"wires":[["72b09a5db87cefae"]]},{"id":"9217f1a2670ed9de","type":"file in","z":"fd3f534ff253d004","name":"読み込み→base64","filename":"filename","filenameType":"msg","format":"utf8","chunk":false,"sendError":false,"encoding":"base64","allProps":false,"x":630,"y":1060,"wires":[["b93c8ec05275813c"]]},{"id":"72b09a5db87cefae","type":"change","z":"fd3f534ff253d004","name":"画像パス指定","rules":[{"t":"set","p":"filename","pt":"msg","to":"ファイルパスを指定","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":1060,"wires":[["9217f1a2670ed9de"]]},{"id":"b93c8ec05275813c","type":"change","z":"fd3f534ff253d004","name":"API 設定","rules":[{"t":"set","p":"payloadImage","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.model","pt":"msg","to":"gpt-4o","tot":"str"},{"t":"set","p":"payload.messages","pt":"msg","to":"[]","tot":"json"},{"t":"set","p":"url","pt":"msg","to":"https://api.openai.com/v1/chat/completions","tot":"str"},{"t":"set","p":"OpenAIToken","pt":"msg","to":"OpenAIキーを指定","tot":"str"},{"t":"set","p":"headers.Authorization","pt":"msg","to":"\"Bearer \" & OpenAIToken","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":200,"y":1180,"wires":[["cee9e1ce4bf80a33"]]},{"id":"63a765a27f8fab05","type":"http request","z":"fd3f534ff253d004","name":"","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":570,"y":1180,"wires":[["4cf66512296c6784"]]},{"id":"4cf66512296c6784","type":"debug","z":"fd3f534ff253d004","name":"payload.choices[0].message.content","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.choices[0].message.content","targetType":"msg","statusVal":"","statusType":"auto","x":830,"y":1180,"wires":[]},{"id":"d46308317fe2380c","type":"comment","z":"fd3f534ff253d004","name":"画像読み込み","info":"","x":190,"y":1020,"wires":[]},{"id":"cee9e1ce4bf80a33","type":"template","z":"fd3f534ff253d004","name":"message 設定","field":"payload.messages.0","fieldType":"msg","format":"json","syntax":"mustache","template":"{\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"この画像は?\"\n },\n {\n \"type\": \"image_url\",\n \"image_url\": {\n \"url\": \"data:image/png;base64,{{{payloadImage}}}\"\n }\n }\n ]\n}\n","output":"json","x":380,"y":1180,"wires":[["63a765a27f8fab05"]]},{"id":"22c94503b83d1a17","type":"comment","z":"fd3f534ff253d004","name":"ChatGPT Vision (gpt-4o)","info":"","x":250,"y":1220,"wires":[]}]
こちらの JSON フローをインポートします。
設定を行う
画像パス指定と書かれている change ノードをダブルクリックします。
「ファイルパスを指定」と書かれている、対象の値という項目に先ほど保存したファイルパスのフルパスで上書き完了をクリックします。
API 設定と書かれている change ノードをダブルクリックします。
いろいろと設定されていますが msg.OpenAIToken で「OpenAIキーを指定」書かれている対象の値の自分の OpenAI の API キーで上書きして完了をクリックします。
デプロイをクリックして設定を反映します。
動かしてみる
message 設定の template ノードの中では、
このように image_url に base64 形式で読み込んだデータ設定しています。今回はめちゃくちゃシンプルな「この画像は?」という質問です。
ということで inject ノードのボタンをクリックしましょう。
しばらく待っていると、Vision API からデータが返ってきてこの debug ノードで結果の JSON から内容を取得します。
このように今回のクリスマスベルが画像認識されて説明されています。