🧑‍🎨

Next.js14でDall-E(open ai)を使えるようにしてみた(その1)

2023/12/05に公開

こんにちは、近藤です。

commmune Advent Calendar 2023 4日目の記事は『Next.js14でDall-E(open ai)を使えるようにしてみた』です

Dall-Eとは、OpenAIによって開発されたAIプログラムで、テキストの説明から画像を生成する能力を持っています。また、Dall-Eはapiが公開されており、アプリケーションに組み込むことが可能です。

今回は表題の通り、Next.js14でDall-E(open ai)を使えるようにしてみました。

まだまだ試したいことがあるので、表題はその1としていますが続けるかわかりません
続かなかった場合、その1はそのうち消えると思います

成果物

今回作成したリポジトリです
https://github.com/yoshifumi-kondo/dalle-nextjs-demo/tree/feat/enable-open-api

作成したアプリでは下記のようにDall-E3を使用しテキストによって画像を出力できます(画像右)
アプリのキャプチャ

アプリの概要

このプロジェクトでは、Next.jsを用いてDall-E(OpenAIのAIプログラム)と連携するアプリケーションを開発しました。このアプリケーションは、以下のプロセスに従って動作します:

  1. ユーザー入力: ユーザーはNext.jsベースのクライアントアプリケーションにテキストを入力します。
  2. クライアントからAPIへのリクエスト: クライアントは入力されたテキストを含むリクエストをNext.jsサーバー上のAPIに送信します。
  3. APIからOpenAIへのリクエスト転送: APIは受け取ったテキストをOpenAIのDall-E APIに転送します。
  4. OpenAIからAPIへの画像URL返却: Dall-E APIはテキストに基づいて生成した画像のURLをAPIに返却します。
  5. APIからクライアントへの画像描画: APIは画像URLをクライアントに返却し、クライアントはそのURLを使用して画像を描画します。

クライアントの実装: Next.jsでDall-E APIの統合

このセクションでは、ユーザーがテキストを入力してDall-E APIを通じて画像を生成し、表示するプロセスについて説明します。主にNext.jsのフロントエンドでの処理に焦点を当てます。

コンポーネントの概要

DallE3Interface は、画像生成と表示のための主要な機能を備えたReactコンポーネントです。

  • 画像URLの管理: useState フックを使い、APIから返される画像のURLを保存します。
  • APIリクエストの状態管理: リクエスト中の状態を示すisExecuting ステートを使用して、ユーザーにフィードバックを提供します。
  • テキスト入力と画像の表示: ユーザーからのテキスト入力をTextPromptFormで受け取り、ImageWrapperで画像を表示します。

APIリクエストの処理

  • リクエストの送信: ユーザーのテキスト入力をJSONとしてAPIにPOSTリクエストで送信します。
  • 応答の処理: APIからの応答を受け取り、画像URLをimageUrl ステートにセットします。

UIの構成

  • フォーム: TextPromptForm でユーザーの入力を受け付けます。
  • 画像表示: ImageWrapper でAPIからの画像を表示します。

コード

以下にDallE3Interface コンポーネントの実装を示します。

// src/components/organisms/DallEV3_Interface.tsx
"use client";
import React, { FC, useState } from "react";
import { SubmitHandler } from "react-hook-form";
import { Typography } from "@mui/joy";
import {
  TextPromptForm,
  TextPromptFormInputs,
} from "@/components/molecules/TextPromptForm";
import { ImageWrapper } from "@/components/molecules/ImageWrapper";

export const DallE3Interface: FC = () => {
  const [imageUrl, setImageUrl] = useState<string | null>(null);
  const [isExecuting, setIsExecuting] = useState<boolean>(false);

  const onSubmit: SubmitHandler<TextPromptFormInputs> = async (data) => {
    setIsExecuting(true);
    const response = await fetch("/api/open-ai/dall-e-v3", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data),
    });

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    const result = await response.json();
    setImageUrl(result.srcUrl);
    setIsExecuting(false);
  };

  return (
    <div className="w-full max-w-md flex-col flex gap-2 flex-wrap border-2 border-gray-300 rounded-md p-4 justify-start m-4">
      <Typography level="h2">Dall-E 3</Typography>
      <TextPromptForm onSubmit={onSubmit} isExecuting={isExecuting} />
      <ImageWrapper src={imageUrl} />
    </div>
  );
};

このセクションでは、Next.jsでDall-E APIと連携するためのクライアントサイドの基本的な実装を紹介しました。次に、サーバーサイドでのAPIの実装について説明します。

APIエンドポイントの処理

このセクションでは、Next.jsのAPIルートにて行われるテキスト入力の処理について詳しく説明します。クライアントからのリクエストを受け取り、適切に処理することが目的です。

リクエストの処理

クライアントからのリクエストを受け、以下の手順で処理します:

  1. テキストの抽出: リクエストからJSON形式でテキストプロンプトを抽出します。
  2. 入力検証: 受け取ったテキストが文字列型であることを確認し、そうでない場合はエラーを返します。

APIエンドポイントのコード(link)

// src/app/api/open-ai/dall-e-v3/route.ts
import { generateImageWithDallE3 } from "@/services/open-ai";

export async function POST(req: Request) {
  const { textPrompt } = await req.json();

  if (typeof textPrompt !== "string") {
    return new Response(
      JSON.stringify({ error: "textPrompt must be a string" }),
      { status: 400 }
    );
  }

  const srcUrl = await generateImageWithDallE3(textPrompt);
  return new Response(JSON.stringify({ srcUrl }), { status: 200 });
}

Dall-E APIへのアクセス: 画像生成

次に、Dall-E APIへのアクセスと画像生成のプロセスについて説明します。この部分では、OpenAIのライブラリを使用してDall-Eにリクエストを送り、画像を生成します。

画像生成の実装

generateImageWithDallE3 関数は、以下のステップでDall-E APIにアクセスし、画像を生成します:

  • OpenAIライブラリの初期化:OpenAIのAPIキーを用いてクライアントを初期化します。(open aiへログイン後こちらからkeyは取得できます。)
  • 画像生成リクエスト:指定されたテキストプロンプトを使用してDall-Eに画像生成リクエストを送信します。

Dall-Eへのアクセスコード(link)

// src/services/open-ai/index.ts
import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

export const generateImageWithDallE3 = async (textPrompt: string) => {
  const response = await openai.images.generate({
    model: "dall-e-3",
    prompt: textPrompt,
    n: 1,
    size: "1024x1024",
  });
  return response.data[0].url;
};

*現時点でsample codeは古いversionのものを紹介していたので注意してください。

以上、非常に簡単にopen aiのapiを組み込むことができました

終わりに

vercelにデプロイしようと思ったのですが、open-aiのapiのプライシングは従量課金なので控えました。
もし試したい場合はcloneしていただき、ルートディレクトリ直下に下記のような.env.localを作成してください

#.env.local
#ご自身のkeyに書き換えてください
OPENAI_API_KEY=hogehogehoge

next.jsの開発元であるvercelのライブラリを使用するとstreming text responseもできるらしいので次回はそれを試したいと思います。

参照

Next.js公式ドキュメント: Next.js Documentation
OpenAI Dall-E APIガイド: OpenAI Dall-E API

コミューン株式会社

Discussion