Grok（xAI）の API：画像入力を扱えるモデルを OpenAI の SDK（Node.js）と組み合わせる【生成AIで遊ぼ】

この記事は 12/29 に書いたのですが、後から ~~「[グラフィックス全般 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/graphics)」~~ ⇒「[生成AIで遊ぼ Advent Calendar 2024](https://qiita.com/advent-calendar/2024/seisei-ai-dayo)」の 18日目の記事としても後から登録してみました。
※ 生成AIで遊ぼ Advent Calendar 2024 のほうが、今回の内容がカレンダーのトピックとよりマッチしていそうなので、登録し直しました

### 記事の概要
今回の記事で扱う Grok（xAI）の API関連では、前に以下の記事を書いたことがあったのですが、今回は OpenAI の SDK（Node.js）を使った画像入力という内容で試してみます。

●Grok の API利用（xAI API による）がパブリックベータになった話の公式情報など ＋α【生成AI-2】 - Qiita
　https://qiita.com/youtoy/items/4d5ac59f52106e96a3e1

## 今回の内容
### 他の API の事例
今回、Grok（xAI）の API の画像入力を、OpenAI の Node.js の SDKを使って扱います。

このような「API提供元と、利用する SDK を別にできる事例」は他にも Gemini でもあります。それについては、以下の記事を書いたりもしました。

- [Gemini の API を OpenAI のパッケージ ＋ Node.js で試す（テキスト・複数の画像の入力）【生成AI−2】 - Qiita](https://qiita.com/youtoy/items/0a4539ce6b9160d55e60)
- [第3弾（Gemini 2.0 Flash編）：AIは「からあげ」と「とり天」を見分けられるのか【からあげ帝国-2】 - Qiita](https://qiita.com/youtoy/items/389c6ef7f284017ce35a)

### OpenAI の SDK と組み合わせる方法
それでは、以下の公式ドキュメントの記載で OpenAI の SDK を組み合わせる方法を見てみます。

●Welcome to the xAI documentation
　https://docs.x.ai/docs/overview

公式ドキュメントの中の、以下の項目の部分に説明が出ていました。
　https://docs.x.ai/docs/guides/migration

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/0be26df1-3d49-7112-5ad0-98e362f948d0.png)

とりあえず、以下の URL・モデル指定などがポイントになりそうです。

```javascript
const openai = new OpenAI({
  apiKey: $XAI_API_KEY,
  baseURL: "https://api.x.ai/v1",
});

// ...

const completion = await openai.chat.completions.create({
  model: "grok-2-latest",
  ...
```

#### 利用するモデルのモデル名
ここでモデル指定については、画像入力に対応した「`grok-2-vision-1212`」などにする必要がありそうでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/3e0be99b-bb8b-e28a-9741-e0c1a5f17736.png)

### 実際に試してみる
それでは、以下を使って実際の処理を試してみます。

●openai - npm
　https://www.npmjs.com/package/openai

お試し用のコードは、以下のとおりです。なお、以下のを実行するにあたり APIキーを環境変数として設定しています（※ XAI_API_KEY という名前の変数にしています）。

```javascript
import OpenAI from "openai";
import fs from "fs";

const apiKey = process.env["XAI_API_KEY"];
const baseURL = "https://api.x.ai/v1";

const openai = new OpenAI({
  apiKey,
  baseURL,
});

async function main() {
  const message = "これらの画像には何がうつってる？";
  console.log(message);

  const imagePaths = ["./input1.jpg", "./input2.jpg"];
  const imageBase64List = imagePaths.map((imagePath) => {
    const imageBuffer = fs.readFileSync(imagePath);
    return imageBuffer.toString("base64");
  });

  const response = await openai.chat.completions.create({
    model: "grok-vision-beta",
    // model: "grok-2-vision-1212",
    messages: [
      {
        role: "user",
        content: [
          { type: "text", text: message },
          {
            type: "image_url",
            image_url: {
              url: `data:image/jpeg;base64,${imageBase64List[0]}`,
            },
          },
          {
            type: "image_url",
            image_url: {
              url: `data:image/jpeg;base64,${imageBase64List[1]}`,
            },
          },
        ],
      },
    ],
  });
  console.log(response.choices[0].message);
}
main();
```

上記を実行してみた時のレスポンスは以下のとおりです。

https://x.com/youtoy/status/1873171211624292396

あと指定するモデルを `grok-vision-beta` にするのも試しましたが、似たような回答が得られました。