Cloud Run에 Imagen 배포

1. 이 Codelab 정보

최종 업데이트: 2024년 10월 11일

작성자: 로리 화이트

이미지 생성

대규모 언어 모델 (LLM)을 통한 이미지 생성은 재미있을 수 있습니다. 물론 프롬프트에서 이미지를 생성하는 비즈니스 애플리케이션도 많습니다. 맞춤 광고에서 매력적인 프레젠테이션에 이르기까지 다양합니다. Google Cloud 웹사이트에는 크리에이티브 에이전트를 사용하는 회사의 다양한 구체적인 사용 사례가 있습니다. 그래도 '들판에 있는 행복한 초록색 강아지' 이미지를 검색하면 어떤 결과가 나오는지 확인하는 것은 꽤 재미있을 수 있습니다.

전문적인 목적 또는 여가 목적 (또는 둘 다)으로 이미지 생성에 관심이 있는 경우 이미지 생성 프로그램을 사용하고 웹 애플리케이션에 배포하는 사이에 몇 가지 문제가 있습니다. 이 실습에서는 이러한 문제를 해결하는 데 도움이 됩니다.

빌드할 항목

이 Codelab에서는 텍스트 프롬프트를 받아 프롬프트를 사용하여 생성된 이미지가 포함된 웹페이지를 반환하는 앱을 빌드합니다.

학습할 내용

이 실습에서는 다음을 학습합니다.

  • Google Imagen을 사용하여 노트북 환경에서 텍스트 프롬프트로 이미지를 만드는 방법
  • Imagen 코드를 노트북에서 웹 앱으로 이동하는 데 어려움
  • Imagen을 사용하여 이미지를 생성하는 Cloud Run 애플리케이션을 배포하는 방법
  • HTML에 Imagen의 이미지를 포함하는 방법

이 Codelab에서는 Imagen 및 배포에 중점을 둡니다. 따라서 이와 관련 없는 개념과 코드 블록은 그냥 넘어가겠습니다. 단, 필요할 때 복사해서 붙여넣을 수 있도록 다른 설명 없이 제공만 해드리겠습니다.

필요한 항목

이 Codelab의 전체 코드는 https://github.com/Annie29/imagen-deployment에서 확인할 수 있습니다 .

2. API 사용 설정

이 Codelab에 사용할 프로젝트를 선택합니다. 완료 후 모든 작업을 더 쉽게 삭제할 수 있도록 새 프로젝트를 만드는 것이 좋습니다.

Imagen을 시작하려면 먼저 일부 API를 사용 설정해야 합니다.

  1. Google Cloud Console로 이동합니다.
  2. Vertex AI 대시보드로 이동합니다.
  3. '모든 권장 API 사용 설정'을 선택합니다.

a8f336f7380a9eab.png

3. Google Imagen 살펴보기 (선택사항)

Imagen에 익숙하다면 이 섹션을 건너뛰어도 됩니다.

Imagen을 사용하는 웹 앱을 만들기 전에 Imagen의 기능을 확인하는 것이 좋습니다. 다행히 간단한 Imagen 코드를 실행하는 여러 노트북이 있으므로 그중 하나로 시작해 보겠습니다.

  1. https://github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/image_generation.ipynb의 노트북으로 이동합니다 .
  2. 'Colab에서 열기'를 선택하여 Google의 노트북 서버에서 노트북을 엽니다.
  3. '파일 -> Drive에 사본 저장'을 선택하거나 페이지 상단의 'Drive에 복사'를 클릭하여 이 노트북의 사본을 만듭니다.
  4. 잘못된 사본에서 작업하지 않도록 원본 사본을 닫습니다.
  5. 오른쪽 상단의 연결 버튼을 클릭하여 런타임에 연결해야 합니다. 2afdc8fa660a89bd.png
  6. 노트북의 각 셀을 살펴봅니다.
  7. 셀을 실행하려면 셀 왼쪽에 있는 [] 또는 화살표를 클릭하거나 런타임 메뉴의 Run Selection 옵션 (또는 단축키 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에서 사용하는 모든 비표준 라이브러리의 목록입니다.

애플리케이션에는 두 페이지가 있습니다. 첫 번째 페이지는 프롬프트를 가져오고 두 번째 페이지는 이미지를 표시하고 사용자가 다른 프롬프트를 입력할 수 있도록 허용합니다.

먼저 프로젝트 프레임워크를 만듭니다.

파일 구조 만들기

이 Codelab에서는 프로젝트가 imageapp 폴더에 있다고 가정합니다. 다른 이름을 사용하는 경우 적절하게 명령어를 업데이트해야 합니다.

화면 오른쪽 상단에 있는 프롬프트 아이콘을 선택하여 Cloud Shell을 엽니다.

28135f700c5b12b0.png

셸 창 상단의 화살표를 사용하여 셸을 새 탭으로 이동하면 더 많은 작업 공간을 확보할 수 있습니다.

310422ac131813e1.png

Cloud Shell의 홈 디렉터리에서 imageapp 폴더를 만들고 이 폴더로 이동한 후 templates 폴더를 만듭니다. 명령줄 또는 Cloud Shell 편집기에서 이 작업을 수행할 수 있습니다.

템플릿 만들기

애플리케이션에는 두 페이지가 있습니다. 첫 번째 페이지 (home.html라고 함)는 메시지를 가져오고 두 번째 페이지 (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 파일에는 웹 요청을 제공하는 코드가 포함되어 있습니다. 처리해야 하는 요청은 두 가지뿐입니다. 홈페이지의 GET 요청과 생성하려는 이미지를 설명하는 양식을 제출하는 POST 요청입니다.

Cloud Shell 편집기 또는 원하는 Linux 편집기를 사용하여 imageapp 폴더에 main.py 파일을 만듭니다. 아래의 스켈레톤으로 시작합니다.

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 코드로 보완해야 하는 주석이 세 개 있습니다.

누락된 부분을 채워 보겠습니다. Flask를 사용하면 프롬프트를 쉽게 검색할 수 있습니다. 아래와 같이 주석 뒤에 줄을 추가합니다.

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

지금 앱을 테스트하려면 display_imagereturn 문자열 앞에 줄을 추가하여 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의 문서에서 사용 방법을 확인하세요. 모델을 만든 다음 프롬프트를 통해 모델에서 이미지를 생성합니다. 두 번째 단계의 코드를 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 목록이 됩니다.

이제 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

저장된 파일을 처리하는 방법에는 여러 가지가 있지만 가장 간단하고 안전한 방법은 데이터 URL을 사용하는 것입니다.

데이터 URL을 사용하면 데이터의 경로뿐만 아니라 실제 데이터를 URL로 전송할 수 있습니다. 데이터 URL의 문법은 다음과 같습니다.

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

이미지의 base64 인코딩을 가져오려면 tempfile로 저장된 파일을 열고 변수로 읽어야 합니다. 예. 큰 문자열이 되지만 최신 브라우저와 서버에서는 문제가 없습니다. 그런 다음 base64 라이브러리를 사용하여 데이터 URL로 전송할 수 있는 문자열로 인코딩합니다.

세 번째 단계 (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

main.py가 있는 폴더에 있는지 확인하고 다음 명령어를 실행하여 Cloud Shell에서 프로그램을 실행해 봅니다.

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>

그런 다음 display_image에서 generate_images 코드를 호출할 때 발생할 수 있는 예외를 포착하는 코드를 main.py에 추가합니다. 예외가 있으면 코드가 메시지와 함께 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 기능이 아닙니다. 사람 및 아동 생성, 이미지의 일반적인 필터를 보호하는 여러 기능이 있습니다. 여기에서 자세한 내용을 확인하세요.

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 프로젝트를 삭제할 수 있습니다. 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을 확인하세요.

추가 자료