Imagen を Cloud Run にデプロイする

1. この Codelab について

最終更新日: 2024-10-11

作成者: Laurie White

画像生成

大規模言語モデル(LLM)による画像生成は楽しいものです。 もちろん、プロンプトから画像を生成するビジネス アプリケーションには、カスタマイズされた広告から魅力的なプレゼンテーションまで、さまざまな用途があります。(Google Cloud ウェブサイトには、Creative Agents を使用している企業の具体的な使用例が多数掲載されています)。それでも、「野原にいる幸せそうな緑色の犬」の画像がどのような結果になるかを確認するのは、とても面白いことです。

画像生成に興味がある理由が、仕事のためであれ、趣味のためであれ(またはその両方であれ)、画像生成プログラムの使用とウェブ アプリケーションへのデプロイの間にはいくつかの課題があります。 このラボでは、これらの課題を克服するのに役立ちます。

作成するアプリの概要

この Codelab では、テキスト プロンプトを受け取り、そのプロンプトを使用して生成された画像を含むウェブページを返すアプリを作成します。

学習内容

このラボでは、次のことを学習します。

  • Google Imagen を使用して、ノートブック環境でテキスト プロンプトから画像を作成する方法
  • Imagen コードをノートブックからウェブアプリに移行する際の難しさ
  • Imagen を使用して画像を生成する Cloud Run アプリケーションをデプロイする方法
  • Imagen の画像を HTML に含める方法

この Codelab では、Imagen とデプロイに焦点を当てます。関連のない概念やコードブロックについては詳しく触れず、コードはコピーして貼るだけの状態で提供されています。

必要なもの

この Codelab の完全なコードは、 https://github.com/Annie29/imagen-deployment で入手できます。

2. API の有効化

この Codelab で使用するプロジェクトを選択します。 完了したら作業内容を簡単に削除できるように、新しいプロジェクトを作成することをおすすめします。

Imagen を使用する前に、いくつかの API を有効にする必要があります。

  1. Google Cloud コンソールに移動します。
  2. Vertex AI ダッシュボードに移動します。
  3. [すべての推奨 API を有効にする] を選択します。

a8f336f7380a9eab.png

3. Google Imagen を調べる(省略可)

Imagen に慣れている場合は、このセクションをスキップできます。

Imagen を使用するウェブアプリを作成する前に、Imagen で何ができるかを確認しておくと便利です。幸いなことに、簡単な Imagen コードを実行するノートブックがいくつかあります。まずはそのうちの 1 つから始めましょう。

  1. https://github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/image_generation.ipynb のノートブックに移動します。
  2. [Colab で開く] を選択して、Google のノートブック サーバーでノートブックを開きます。
  3. [ファイル] -> [ドライブにコピーを保存] を選択するか、ページの上部にある [ドライブにコピー] をクリックして、このノートブックの独自のコピーを作成します。
  4. 元のコピーを閉じます(間違ったコピーで作業しないようにするため)。
  5. 右上にある [接続] ボタンをクリックして、ランタイムに接続する必要があります。2afdc8fa660a89bd.png
  6. ノートブックの各セルを操作します。
  7. セルを実行するには、セルの左側にある [] または矢印をクリックするか、[ランタイム] メニューの [選択したものを実行] オプション(またはそのショートカット)を使用します。 dfec032ef6c31296.png
  8. 現在のランタイムを再起動すると、システムがクラッシュしたというメッセージが表示されます。慌てないでください。 これは正常な動作です。
  9. ノートブック環境を認証する必要があります。
  10. コードの右側のボックスにプロジェクト ID(名前ではない)とロケーション(ロケーションを設定していない場合は us-central1)を入力すると、Colab がコードに挿入します。
  11. [画像を生成] に到達すると、Imagen で何ができるかを確認できます。プロンプトを変更してセルを再実行し、取得できる画像のバリエーションを確認してください。
  12. この時点で、Imagen がノートブックから画像を生成する方法を理解できたはずです。 このノートブックを完了して、画像パラメータの詳細を確認してください。

4. 画像を表示するウェブ アプリケーションの作成を開始する

Cloud Run で Flask フレームワークを使用して Python でアプリを作成します。

Python Flask アプリは、次のようにフォルダに設定されます。

app-folder
    templates
        template.html
        (etc.)
        anothertemplate.html
    main.py
    requirements.txt

テンプレート は HTML を含むファイルです。通常、プログラムが生成されたテキストを挿入する名前付きプレースホルダが含まれています。main.py はウェブサーバー アプリ自体で、requirements.txtmain.py が使用する標準以外のライブラリのリストです。

アプリケーションには 2 つのページがあります。1 つはプロンプトを取得するページ、もう 1 つは画像を表示してユーザーが別のプロンプトを入力できるようにするページです。

まず、プロジェクト フレームワークを作成します。

ファイル構造を作成する

この Codelab では、プロジェクトが imageapp フォルダにあることを前提としています。 別の名前を使用する場合は、必要に応じてコマンドを更新してください。

画面の右上にあるプロンプト アイコンを選択して、Cloud Shell を開きます。

28135f700c5b12b0.png

シェル ウィンドウの上部にある矢印を使用してシェルを新しいタブに移動すると、作業スペースを広げることができます。

310422ac131813e1.png

Cloud Shell のホーム ディレクトリから imageapp フォルダを作成し、そのフォルダに移動して templates フォルダを作成します。 これは、コマンドラインまたは Cloud Shell エディタから行うことができます。

テンプレートを作成する

アプリケーションには 2 つのページがあります。1 つはプロンプトを取得するページ(home.html)、もう 1 つは画像を表示してユーザーが別のプロンプトを入力できるようにするページ(display.html)です。

Cloud Shell エディタまたは任意の Linux エディタを使用して、2 つのテンプレートを作成します。 imageapp/templates フォルダから、ユーザーに最初に表示されるページ home.html を作成します。 変数 prompt を使用して、ユーザーが入力した説明を返します。

templates/home.html

<!DOCTYPE html>
<html>
   <head>
       <title>Let's draw a picture</title>
   </head>
   <body>
       <h1>Let's draw a picture</h1>
       <form  action="/" method="post" >
           <input type="text" id="prompt" name="prompt">
           <input type="submit" value="Send">
       </form>
   </body>
</html>

次に、画像を表示する display.html を作成します。 画像の場所は image_url になります。

templates/display.html

<!DOCTYPE html>
<html>
   <head>
       <title>Let's draw a picture</title>
   </head>
   <body>
       <h1>Let's draw a picture</h1>

       <div>
           <form  action="/" method="post" >
               <input type="text" id="prompt" name="prompt">
               <input type="submit" value="Send">
           </form>

           <p></p>
       </div>

       <div id="picture">
           <img id="pict" name="pict" alt="The created image" src="{{image_uri}}" style="width:100%;">
       </div>

   </body>
</html>

5. コードを開始する

プログラムに必要なすべてのライブラリが使用可能であることを確認するには、requirements.txt ファイルを作成する必要があります。 今のところは、requirements.txt ファイルに flask を含めるだけでかまいません。

main.py ファイルには、ウェブ リクエストを処理するコードが含まれています。処理する必要があるリクエストは 2 つだけです。ホームページの GET リクエストと、生成する画像の説明を含むフォームを送信する POST リクエストです。

Cloud Shell エディタまたは任意の Linux エディタを使用して、main.py ファイルを imageapp フォルダに作成します。まずは以下のスケルトンから始めましょう。

main.py

import flask

app = flask.Flask(__name__)

@app.route("/", methods=["GET"])
def home_page():
    return flask.render_template("home.html")

@app.route("/", methods=["POST"])
def display_image():
    # Code to get the prompt (called prompt) from the submitted form
    # Code to generate the image
    # Code to create a URL for the image (called image_url)

    return flask.render_template("display.html", prompt=prompt, image_url=image_url)

# Initialize the web server app when the code locally (Cloud Run handles it in that environment)
if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=8080)

実際、これはアプリのほぼ全体です。display_image には Python コードで記述する必要があるコメントが 3 つあります。

欠落している部分を埋めていきましょう。Flask を使用すると、プロンプトを簡単に取得できます。 以下のように、コメントの後に 1 行追加します。

# Code to get the prompt (called prompt) from the submitted form
prompt = flask.request.form["prompt"]

ここでアプリをテストする場合は、display_imagereturn ステートメントの前に 1 行追加して、image_url に値(画像を指す有効な URL)を指定します。

例: image_url="<your url here>"

Cloud Shell から(python main.py コマンドを使用して)プログラムをローカルで実行し、画面の右上にある [ポート 8080 でプレビュー] を使用してプレビューできます。

a80b4abd28cb7eed.png

現在のプログラムでは、指定した URL に常に画像が表示されます。 次に、アプリからその値を取得する方法について説明します。image_url に静的な値を指定する行を削除してください。

6. イメージを作成する

Google Cloud には、Vertex AI の 生成 AI 用の Python API があります。これを使用するには、プログラムの上部にある他のインポートとともにインポートする行を追加する必要があります。

from vertexai.vision_models import ImageGenerationModel

また、requirements.txt ファイルに vertexai を含めます。

ImageGenerationModel の ドキュメントには、その使用方法が記載されています。モデルを作成し、プロンプトを指定して画像を生成します。 2 つ目の手順として、main.py にコードを追加して画像を作成し、response に保存します。

# Code to generate the image
model = ImageGenerationModel.from_pretrained("imagegeneration@006")
response = model.generate_images(prompt=prompt)[0]

generate_images に送信されるパラメータに応じて、一度に最大 4 つの画像を作成できます。そのため、返される値は GeneratedImage のリストになります。この場合のように、返される画像が 1 つだけの場合でも同様です。

次に、画像を WWW ページに表示する必要があります。 GeneratedImage には画像を show するメソッドがありますが、ノートブック環境でのみ機能します。 ただし、画像を保存するメソッドはあります。 画像を保存し、テンプレートをレンダリングするときに保存した画像の URL を送信します。

これは少し難しいですが、さまざまな方法があります。 簡単な方法をステップごとに見ていきましょう (視覚的に学習したい場合は、以下の手順の図をご覧ください)。

まず、画像を保存する必要があります。 どのような名前を付けますか? プログラムは多くのユーザーが同時に使用できるため、静的な名前を使用すると問題が発生する可能性があります。 各ユーザーに個別の画像名(UUID など)を作成することもできますが、より簡単な方法として、Python の tempfile ライブラリを使用します。このライブラリは、一意の名前を持つ一時ファイルを作成します。次のコードは、一時ファイルを作成し、その名前を取得して、画像生成ステップのレスポンスを一時ファイルに書き込みます。 URL を取得する必要があるため、まだコードには入力しません。

with tempfile.NamedTemporaryFile("wb") as f:
    filename = f.name
    response.save(filename, include_generation_parameters=False)
    # process the saved file here, before it goes away

保存したファイルを処理する方法はいくつかありますが、最も簡単で安全な方法の 1 つは データ URL を使用することです。

データ URL を使用すると、パスだけでなく実際のデータを URL で送信できます。 データ URL の構文は次のとおりです。

data:[image/png][;base64],<data>

画像の Base64 エンコードを取得するには、tempfile で保存したファイルを開いて変数に読み込む必要があります。はい、これは長い文字列になりますが、最新のブラウザとサーバーでは問題ありません。次に、 base64 ライブラリを使用して、データ URL で送信できる文字列にエンコードします。

3 番目のステップ(URL の作成)を行う最終的なコードは次のようになります。

# Code to create a URL for the image (called image_url)
with tempfile.NamedTemporaryFile("wb") as f:
    filename = f.name
    response.save(filename, include_generation_parameters=False)
    # process the saved file here, before it goes away
    with open(filename, "rb") as image_file:
        binary_image = image_file.read()
        base64_image = base64.b64encode(binary_image).decode("utf-8")
        image_url = f"data:image/png;base64,{base64_image}"

これらの手順はすべて、次の図で確認できます。

268876579dc02376.png

プログラムの先頭で tempfile と base64 をインポートする必要があります。

import tempfile
import base64

Cloud Shell からプログラムを実行します。main.py を含むフォルダに移動し、次のコマンドを実行します。

python main.py

画面の右上にある [ポート 8080 でプレビュー] を使用してプレビューできます。

a80b4abd28cb7eed.png

7. 一般的なエラー

プログラムの実行中(テスト中またはデプロイ後)に、次のようなメッセージが表示されることがあります。

2366c3bba6273517.png

これは、Google の責任ある AI への取り組みに違反するプロンプトが原因である可能性が最も高いです。「カラフルなボールで遊ぶ子猫」のような簡単なプロンプトでも、この問題が発生する可能性があります (ただし、「カラフルなおもちゃで遊ぶ子猫」の画像は取得できます)。

このエラーに対処するため、画像を生成しようとしたときに発生する例外をキャッチするコードを追加します。例外が発生した場合は、メッセージを表示して home.html テンプレートを再度レンダリングします。

まず、エラーが発生した場合に表示される最初のフォームの後に、home.html テンプレートに div を追加します。

<!DOCTYPE html>
<html>
   <head>
       <title>Let's draw a picture</title>
   </head>
   <body>
       <h1>Let's draw a picture</h1>
       <form  action="/" method="post" >
           <input type="text" id="prompt" name="prompt">
           <input type="submit" value="Send">
       </form>
       {% if mistake %}
       <div id="warning">
       The prompt contains sensitive words that violate
       <a href=\"https://ai.google/responsibility/responsible-ai-practices\">
           Google's Responsible AI practices</a>.
       Try rephrasing the prompt."</div>

       {% endif %}

   </body>
</html>

次に、main.py にコードを追加して、display_image で generate_images コードを呼び出すときに発生する可能性のある例外をキャッチします。 例外が発生した場合、コードはメッセージとともに home.html テンプレートをレンダリングします。

# Code to generate the image
   model = ImageGenerationModel.from_pretrained("imagegeneration@006")
   try:
       response = model.generate_images(prompt=prompt)[0]   
   except:
       #  This is probably due to a questionable prompt
       return flask.render_template("home.html", warning=True)

これは、Imagen の責任ある AI 機能の 1 つにすぎません。 人物や子供の生成を保護する機能や、画像に対する一般的なフィルタがいくつかあります。 詳細については、こちらをご覧ください

8. アプリをウェブにデプロイする

Cloud Shell の imageapp フォルダから コマンドを使用して、アプリをウェブにデプロイできます。 コマンドでは実際のプロジェクト ID を使用してください。

gcloud run deploy imageapp \
  --source . \
  --region us-central1 \
  --allow-unauthenticated \
  --project your-project-id

次のようなレスポンスが表示され、アプリケーションの場所が示されます。

Service [imageapp] revision [imageapp-00001-t48] has been deployed and is serving 100 percent of traffic.
Service URL: https://imageapp-708208532564.us-central1.run.app```

9. クリーンアップ

サービスが使用されていない場合、Cloud Run の料金は発生しませんが、コンテナ イメージを Artifact Registry に保存すると課金される場合があります。リポジトリを削除するか、クラウド プロジェクトを削除してこのような料金が発生しないようにできます。Cloud プロジェクトを削除すると、そのプロジェクト内で使用されているすべてのリソースに対する課金が停止します。

コンテナ イメージ リポジトリを削除するには:

gcloud artifacts repositories delete cloud-run-source-deploy \
  --location $REGION

Cloud Run サービスを削除するには:

gcloud run services delete imageapp \
  --platform managed \
  --region $REGION

Google Cloud プロジェクトを削除するには:

  1. 現在のプロジェクト ID を取得します。
PROJECT_ID=$(gcloud config get-value core/project)
  1. これが削除するプロジェクトであることを確認します。
echo $PROJECT_ID
  1. プロジェクトを削除します。
gcloud projects delete $PROJECT_ID

10. 完了

Imagen で作成された画像を表示するウェブ アプリケーションが正常に作成されました。これをアプリケーションでどのように使用できますか?

次のステップ

以下の Codelab をご覧ください。

参考資料