GPTは「からあげ」と「とり天」を見分けられるのか。出たばかりのAzure Open AIのGPT-4 Turbo with Visionを試す


一昨日(2023/12/12)、Azure Open AIでVision API（GPT-4 Turbo with Vision）が使えるようになりました。

https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/gpt-with-vision

Azure Open AIのVision APIをJavaScriptから触ってみつつ、
皆さんが気になっている **GPTは「からあげ」と「とり天」を見分けられるのか**を見ていきます。

> <img src="https://i.gyazo.com/c6487e4024b981a0b5bbeae398da8368.jpg" width="200px" /> <img src="https://i.gyazo.com/f6f6535e99cad0637845eecb01b8421f.png" width="200px" />


- 検証1: GPTはからあげの画像を説明できるのか？
- 検証2: GPTはとり天の画像を唐揚げではなくとり天だと認識できるのか？

を試してみます。気になりますね。
（ **からあげ帝国アドベントカレンダー** の記事なので **「からあげとAI」がマスト** な感じですね。）

インターネット上にも気になってる人は多数（？)
> https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1035213620
> ![スクリーンショット 2023-12-13 15.08.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/d52f24af-aece-ed24-4dd5-41262fc35d76.png "スクリーンショット 2023-12-13 15.08.25.png")

## 「からあげ」と「とり天」

唐揚げは皆さん知ってると思いますが、とり天はどうでしょう。

[農林水産省のページ](https://www.maff.go.jp/j/keikaku/syokubunka/k_ryouri/search_menu/menu/toriten_oita.html)に載っている情報によると 「`とり天は、骨のない鶏肉を食べやすい大きさに切り、天ぷら衣をつけて揚げた料理です。とり天は、唐揚げよりさっぱりしていて、ポン酢などを付けて食べます。`」とのことです。天ぷら粉かどうかなのかな、割と難しい。

↑の画像の **「からあげ」と「とり天」どっちがどっちか割と難しい**ですよね。


> <img src="https://i.gyazo.com/d06270a048c2793638b7cb8b7ce12d2a.png" width="300px" />

判別できるのでしょうか。

## AzureでGPT-4 Turbo with Visionの準備

Azure Open AIでOpenAIのVison APIを使ってみます。
Teachable Machineなどで、からあげとり天判定の独自モデルを作るわけではなく、OpenAIのモデルを利用します。

### 使えるリージョン

[公式ドキュメント](https://learn.microsoft.com/ja-jp/azure/ai-services/openai/concepts/models#gpt-4-and-gpt-4-turbo-preview-model-availability)を見ると、現時点だと`オーストラリア東部`/`スウェーデン中部`/`スイス北部`/`米国西部`の4つのリージョンで使える模様です。

> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/5572bafc-01ad-6c3e-09fe-416259cc1aa4.png" width="300px" />

ということで`WestUS`（米国西部）でOpenAIのインスタンスを作成してみます。

> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/a8f985cd-c7ea-8588-bbf8-f27a71532fb4.png" width="300px" />

### モデルのデプロイ

モデルのデプロイをします。モデルは`gpt-4`を選択し、モデルバージョンは`vision-preview`を選択、デプロイ名は任意の名前です。（`n0bisuke-vision`にしました。）

> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/c5e0bf77-6651-6013-429a-a98a0baec4fa.png" width="400px" />

## Node.jsからAPIを叩いてみる

ライブラリのインストールをして進めます。

```bash
$ npm i @azure/openai
```

### アクセス情報

他のOpenAIのAPIを使う時と同様でAPIキー、エンドポイント、デプロイ名を使ってアクセスします。

https://qiita.com/n0bisuke/items/703943870d5a04fc2205

### 以下のコードで実行

```js
const { OpenAIClient,AzureKeyCredential } = require("@azure/openai");

const endpoint = `https://XXXXXXX.openai.azure.com/`; //エンドポイント
const azureApiKey = `YYYYYYYYYY`; //APIキー
const deploymentId = "ZZZZZZZZZZ"; //デプロイ名 さっきn0bisuke-visionにしてた

const url = `https://i.gyazo.com/a7cba41711444c05b059de7f372bf0ac.png`; //読み込ませたい画像

async function main(){
    const client = new OpenAIClient(endpoint, new AzureKeyCredential(azureApiKey));
    const messages = [
        {role: "system", content: "You are a helpful assistant."},
        {role: "user", content: [
            {type: "text", text: "Describe this picture:" },
            {
                type: "image_url",
                imageUrl: {
                    url,
                    detail: "auto"
                }
            }
        ]}
    ];
    const result = await client.getChatCompletions(deploymentId, messages);
    console.log(`Chatbot: ${result.choices[0].message?.content}`);
}

main().catch((err) => {
  console.error("The sample encountered an error:", err);
});

```


## まずは試しに犬を読ませてみた

ぱくたその犬の画像を読ませてみました。

> <img src="https://i.gyazo.com/199d971370d52d3b0d4e7c785b049fad.jpg" width="300px" />
> https://www.pakutaso.com/20231006284post-48113.html

`The picture shows a cute, light brown toy poodle sitting in front of a`

といい感じに説明を返してくれました。 **いいですね。。**

途中で文章が途切れてる雰囲気ありますが、max_tokensの指定をしてないからだと思います。

### プロンプトをかえてみたら返事が遅くなりすぎた

日本語にしつつ、丁寧に説明してねと。してみました。

```js
    const messages = [
        {role: "system", content: "あなたは画像の説明が上手い優秀なアシスタントです。"},
        {role: "user", content: [
            {type: "text", text: "この画像に何が写っているのかを小学生にも分かるように丁寧に説明をしてください。:" },
            {
                type: "image_url",
                imageUrl: {
                    url: url,
                    detail: "auto"
                }
            }
        ]}
    ];
```

ものすごく色々と考えてくれているのかずっと返事がないまま止まっていました。たぶんStreamのAPIを使って実装すると良い気がします。

> ![スクリーンショット 2023-12-13 14.32.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/2b60a058-74f1-db11-5060-03cfef92e94f.png "スクリーンショット 2023-12-13 14.32.00.png")


やっと帰ってきたと思ったら

```
nobisuke@nobisuke-PS5 azuregpt4v % node test.js
Chatbot: この写真は、パソコンに向かっている
```

あっさりだなおい、、

これはトークン設定が大事ですね。たぶん省略されてるだけで本当は長い文章の回答があるんだと思います。

## 検証1.「からあげ」の画像を読み込ませてみる

いよいよ「からあげ」の画像の判定です。こちらもぱくたそさんの画像になります。

> ![](https://i.gyazo.com/f6f6535e99cad0637845eecb01b8421f.png)
> https://www.pakutaso.com/20150240035post-5143.html

### プロンプトはこんな感じ

`You are an excellent image description assistant. You answer carefully so that even a blind person can understand what the image looks like. All your answers will be given in Japanese.`
(あなたは優秀な画像説明アシスタントです。目の見えない人にも画像の様子が伝わるように丁寧に回答します。あなたの回答は全て日本語で回答します。)

読ませたら

```
$ node test.js
Chatbot: 黒い四角い皿の上にカラッと揚げられたカラアゲが何個か盛り付けられています。カラアゲは金茶色で、衣がふっくらとしていて外はカリッとしてそうです。皿の端にはレモンの薄切りが一切れと、緑のレタスの葉が少し添えられており、彩りを加えています。下に敷かれたキッチンペーパーは油を吸収していて、カラアゲをより美味しそうに見せています。全体の雰囲気はシンプルでありながら、食欲をそそるものになっています。
```

**素晴らしい。。**

## 検証2.「とり天」の画像を読み込ませてみる

プロンプトは「からあげ」と同様です。

画像はこちらで農林水産省さんのページにあったものを使っています。

> <img src="https://i.gyazo.com/c6487e4024b981a0b5bbeae398da8368.jpg" width="400px" />
> https://www.maff.go.jp/j/keikaku/syokubunka/k_ryouri/search_menu/menu/toriten_oita.html

**さて結果は。。。**

・
・
・


```bash
$ node test.js
Chatbot: 白い皿に盛り付けられた天ぷらです。軽い金黄色の衣がサクサクとした感じをうかがわせ、熱々の出来立てに見えます。いくつかの天ぷらは厚みがあり、具が大きいことを示しています。一方で、他の何片かは、細かい具が入っているように見えます。どれも外側はカリカリしながら、中は柔らかそうです。皿の隅には、小さな茶色の器に入ったマスタードらしきものが添えられており、味のアクセントになっていそうです。天ぷらの下にはサッと摺られたキッチンペーパーが敷いてあり、余分な油を吸い取りつつも盛り付けの美しさを保っています
```

・
・
・

> ![スクリーンショット 2023-12-13 14.59.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/0bdfbe84-2c8a-0469-48aa-01f76debdf0c.png "スクリーンショット 2023-12-13 14.59.33.png")

・
・
・

> ![スクリーンショット 2023-12-14 16.54.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/562ff1fe-30a4-ef2d-6484-237ec8f7e808.png "スクリーンショット 2023-12-14 16.54.30.png")


**すごいですね。「からあげ」ではなく「天ぷら」だと認識しています。**

ただ中身が鶏肉かどうかの判断はできてなさそうなので、とり天かどうかまでは分かってなさそうです。
まぁでもこれは人間が見てもわからないと思われます。

## おまけ: からあげ先生の画像を読み込ませてみる

かの有名なからあげ先生の画像を読み込ませてみます。

> <img src="https://i.gyazo.com/b8b3ab62020c27b508380b289400dcf1.png" width="400px" />

```
Chatbot: 画像には、ニコニコとした表情をした白いピロー（枕）のキャラクターが描かれています。キャラクターの頭の上には赤い帽子のような形をした物が載っており、その右端には茶色のヘタがついています。これはおそらくリンゴを模した帽子と思われます。キャラクターの顔はシンプルで、閉じた目に幸せそうな笑顔を見せており、左側には目尻に近い少し離れた位置に長いまつげが三本描かれています。また、キャラクターは右口元から出ている白い枝状の物を咥えており、その端には褐色の装飾が付いていて、まるで木の枝を咥えて
```

説明途中でトークン切れな感じでしたがだいぶ丁寧に説明してくれてますね！


## まとめ

優秀ですね。

「天ぷら」か「からあげ」かは判定してくれそうな感じでした。

ここまで来て思ったのは天ぷらとからあげの対比構造な気がしたので、「とり天」「からあげ」ではなく「とり天」「とりから」を判定できるかの方が概念的に良かったのかもしれません。

まぁどちらかが「とり天」、どちらかが「からあげ」という2択の判定ゲームだとしたらちゃんと判定してくれそうな雰囲気でした。

少なくとも料理解像度が低い僕がとり天の画像だけ渡されたらからあげと答えそうな気がしたので僕より優秀だと思います。

とり天食べたくなってきました。