APIによるStable Diffusion 3およびStable Diffusion 3 Turboの画像生成

Stable Diffusion 3が使えるようになりましたね。Fireworks AIと提携して99.9%のSLAも提供するとのこと。

https://ja.stability.ai/blog/stable-diffusion-3-api

API呼び出しして画像を生成してみましょう。

**実行サンプル**
![スクリーンショット 2024-04-19 16.09.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44645/b955d344-164e-8ecb-8881-eb8d3918453e.png "実行サンプル")

公式ドキュメントはこちらなのでとりあえず開くと良いと思いますが、現時点では多少説明が古い部分もあるようです。

https://platform.stability.ai/docs/api-reference#tag/Generate/paths/~1v2beta~1stable-image~1generate~1sd3/post

まずはAPIキーを取得して、cURLで画像を生成できるか試してみましょう。
```sh
curl -f -sS "https://api.stability.ai/v2beta/stable-image/generate/sd3" \
  -H "authorization: Bearer 取得したAPIキー" \
  -H "accept: image/*" \
  -F prompt="Lighthouse on a cliff overlooking the ocean" \
  -F output_format="jpeg" \
  -o "./lighthouse.jpeg"
```

うまく行けば実行したフォルダーに画像が作成されます。

![lighthouse.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44645/39e8da71-0519-0d38-beba-a3d15eee3fb1.jpeg)

Webアプリケーションに組み込む場合、Base64形式で取得できた方が取り回ししやすい場合もあります。`accept`ヘッダーに`application/json`を指定すると、json形式のレスポンスを指定できます。
```sh
curl -f -sS "https://api.stability.ai/v2beta/stable-image/generate/core" \
  -H "authorization: Bearer 取得したAPIキー" \
  -H "accept: application/json" \
  -F prompt="Lighthouse on a cliff overlooking the ocean" \
  -F output_format="png" \
  -o "./lighthouse.txt"
```

この場合、Base64形式のデータはレスポンスのimage値として戻ります。

```lighthouse.json
{"image":"iV...(省略)","finish_reason":"SUCCESS","seed":1241615284}
```

これを踏まえて、Webアプリケーションに組み込んでみましょう。サンプルコードを示した後、順番に説明していきます。

```typescript
import FormData from 'form-data';

function createFormData(data:any) {
  const form = new FormData();
  Object
    .keys(data)
    .forEach(key => form.append(key, data[key]));
  return form;
}

async function generateStableDiffusionImages(prompt:string, model:string):Promise<GenerateImageResponse[]> {
  const output_format = 'png';

  let apiUrl = `https://api.stability.ai/v2beta/stable-image/generate/core`;
  let formData:any = {
    prompt,
    // model: model,
    output_format,
  };

  if (model === 'stable-diffusion-3' || model === 'stable-diffusion-3-turbo') {
    apiUrl = `https://api.stability.ai/v2beta/stable-image/generate/sd3`;
    formData.model = model;
  }

  const headers = { 
    Authorization: `Bearer ${process.env.STABILITYAI_API_KEY}`, 
    Accept: 'application/json',
  };
  const response = await fetch(
    apiUrl, 
    {
      method: 'POST',
      headers,
      body: createFormData(formData) as any,
    }
  );
  const json = await response.json() 

  if (response.status !== 200) {
    const errors:string[] = json.errors
    console.log(json.name, errors.join('\n'), prompt);
    throw new Error(`${response.status} ${response.statusText} ${json.name} ${errors.join(' ')}`);
  }
  if (json.finish_reason !== 'SUCCESS') {
    console.log(json.finish_reason, prompt);
    throw new Error(`Unexpected finish_reason: ${json.finish_reason}`);
  }

  const imageUrl = `data:image/${output_format};base64,` + json.image;

  return [{url: imageUrl, model}];
}
```

まず、`multipart/form-data`形式でPOSTする必要があるため、FormData形式でパラメーターを用意します。`import FormData`は、node.jsで実行する時に必要となります。

次に、モデルですが、もともとあったStable Image Coreと、Stable Diffusion 3およびStable Diffusion 3 Turboの3種類があり、エンドポイントと、ヘッダーが異なるので分岐しています。ちなみに費用も違っていて、Stable Image Coreは画像1つ生成するごとに3クレジット、Stable Diffusion 3とStable Diffusion 3 Turboはそれぞれ6.5クレジット、4クレジットとなっています。1024x1024の画像が1000クレジットあたり10ドルなので、およそ1回の生成辺り`$0.03`, `$0.065`, `$0.04`となります（エラーやポリシー違反などで生成できなかった場合はカウント外だそうです）。

`application/json`を指定して、`data:image/png;base64,`と繋げることで、Base64形式のData URIスキームの文字列に変換しているので、このまま`image`タグの`src`に指定するなどすれば表示可能となります。

エラーについて、ドキュメントでは`errors`が文字列配列形式でエラーの詳細が入っていると記載されているのですが、パラメーターに誤りがあり400が返ってきた時など、`errors`が`undefined`の場合もあります。cURLで確実にレスポンスが得られていることを確認してからアプリケーションの組み込みに進むと良いでしょう。

また、ドキュメントに記載がありませんが、クレジット不足の時は402が返ってきます。

----

冒頭で画面キャプチャーしたWebアプリケーションでは、ChatGPTのFunction Callingと繋ぎこんで、各種画像生成モデルにて同じプロンプトを渡して同時に生成されるようにしています。具体的には、下記の各モデルに同時にリクエストを投げています。

- DALL·E 2
- DALL·E 3
- Stable Diffusion 2 (Hugging Face)
- Stable Image Core
- Stable Diffusion 3
- Stable Diffusion 3 Turbo

上記で説明した部分に相当するコードはこちらです。

https://github.com/twxxk/mulai3/blob/d8642c81b195f29bad22bd5f0ec3814b1d5e843e/app/ai-action.tsx#L160-L214

コード全体はこちらからご確認ください。必要な環境変数を設定した手元で動かせるはずです。

https://github.com/twxxk/mulai3/

デモアプリケーションは下記です。課金が増えたら予告なく閉じる場合がありますことをご了承ください。

https://mulai3.vercel.app/

ドキュメントにあるように、ほかにもネガティブプロンプトの指定など色んなパラメーターを設定可能ですのでお試しください。