GenAI 및 Cloud Run으로 퀴즈 생성기 빌드

1. 소개

이 실습에서는 웹 서비스를 빌드하여 상식 퀴즈를 생성하고 재미있고 작동하는 앱에 통합합니다. 이전에 사용하던 것과 다른 프로그래밍 언어(영어)를 사용하게 됩니다.

실습할 내용…

  • 일련의 기준에 따라 상식 퀴즈를 생성하는 프롬프트를 제작합니다.
  • 간단한 웹 앱을 빌드하고 개발 환경에서 예상대로 실행되는지 확인합니다.
  • 웹 앱에 점진적으로 로직을 추가하여 입력 매개변수 세트에 따라 퀴즈를 생성하는 API 서버로 전환합니다.
  • Google Cloud Run을 사용하여 퀴즈 생성 서비스를 클라우드에 얼마나 쉽게 배포할 수 있는지 알아보겠습니다.
  • 마지막으로 배포된 퀴즈 생성기 서비스를 사용하도록 실제 앱 ( quizaic.com)을 구성하고 출력에 따라 라이브 퀴즈를 플레이할 수 있습니다.

학습할 내용…

  • 대규모 언어 모델 (LLM)을 위한 템플릿 기반 프롬프트를 만드는 방법
  • Python으로 간단한 웹 서버 앱을 만드는 방법을 알아야 합니다.
  • 웹 앱에 Google의 LLM 지원을 추가하는 방법
  • 누구나 새로 만들어 볼 수 있도록 앱을 클라우드에 배포하는 방법
  • 퀴즈 생성기를 더 큰 앱에 통합하는 방법

필요한 항목…

  • Chrome 웹브라우저
  • Google 계정
  • 결제가 사용 설정된 Cloud 프로젝트

이 실습은 초보자를 포함한 모든 수준의 개발자를 대상으로 합니다. Python을 사용하겠지만, 앞으로 볼 모든 코드를 설명하므로 Python 프로그래밍에 익숙하지 않아도 내용을 이해할 수 있습니다.

2. 설정

a08aa5878e36b60c.png

이 섹션에서는 실습을 시작하는 데 필요한 모든 사항을 다룹니다.

자습형 환경 설정

  1. Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
  • 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔은 고유한 문자열을 자동으로 생성합니다. 일반적으로는 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로 PROJECT_ID로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 다른 임의 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다.
  • 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
  1. 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스 또는 프로젝트를 삭제하면 됩니다. Google Cloud 신규 사용자는 300달러(USD) 상당의 무료 체험판 프로그램에 참여할 수 있습니다.

Cloud Shell 시작

이 실습에서는 Google 클라우드에서 실행되는 가상 머신이 호스팅하는 명령어 인터프리터인 Cloud Shell 세션에서 작업합니다. 이 섹션은 사용자의 컴퓨터에서 로컬로 쉽게 실행할 수도 있지만, Cloud Shell을 사용하면 모든 사람이 일관되고 재현 가능한 환경에 액세스할 수 있습니다. 실습을 마치고 로컬 컴퓨터에서 이 섹션을 다시 시도하셔도 됩니다.

4a95152439f0159b.png

Cloud Shell 활성화

  1. Cloud Console에서 Cloud Shell 활성화853e55310c205094.png를 클릭합니다.

3c1dabeca90e44e5.png

Cloud Shell을 처음 시작하는 경우에는 무엇이 있는지 설명하는 중간 화면이 표시됩니다. 중간 화면이 표시되면 계속을 클릭합니다.

92662c6a846a5c.png

Cloud Shell을 프로비저닝하고 연결하는 데 몇 분 정도만 걸립니다.

9f0e51b578fecce5.png

가상 머신에는 필요한 개발 도구가 모두 들어 있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 Codelab에서 대부분의 작업은 브라우저를 사용하여 수행할 수 있습니다.

Cloud Shell에 연결되면 인증이 완료되었고 프로젝트가 자신의 프로젝트 ID로 설정된 것을 확인할 수 있습니다.

  1. Cloud Shell에서 다음 명령어를 실행하여 인증되었는지 확인합니다.
gcloud auth list

명령어 결과

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Cloud Shell에서 다음 명령어를 실행하여 gcloud 명령어가 프로젝트를 알고 있는지 확인합니다.
gcloud config list project

명령어 결과

[core]
project = <PROJECT_ID>

또는 다음 명령어로 설정할 수 있습니다.

gcloud config set project <PROJECT_ID>

명령어 결과

Updated property [core/project].

일부 API 사용 설정

이후 단계에서는 이러한 서비스가 필요한 위치와 이유를 설명하겠지만, 지금은 다음 명령어를 실행하여 프로젝트에 Cloud Build, Artifact Registry, Vertex AI, Cloud Run에 대한 액세스 권한을 부여합니다.

gcloud services enable cloudbuild.googleapis.com        \
                       artifactregistry.googleapis.com  \
                       aiplatform.googleapis.com        \
                       run.googleapis.com          

그러면 다음과 유사한 성공 메시지가 표시됩니다.

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

3. 메시지 표시 - 자연어 프로그래밍

92f630373224ead8.png

먼저 대규모 언어 모델의 프롬프트를 개발하는 방법을 알아보겠습니다. Google Cloud 콘솔로 이동 > Vertex AI > Vertex AI Studio (언어) 다음과 같은 페이지가 표시됩니다.

bfe5706041ae6454.png

Generate Text 아래에서 Text Prompt 버튼을 클릭합니다. 다음 대화상자에 다음 요구사항에 따라 상식 퀴즈를 만드는 데 효과적이라고 생각되는 프롬프트를 입력합니다.

  • 주제: 세계사
  • 질문 수: 5
  • 난이도: 중급
  • 언어: 영어

제출 버튼을 클릭하여 출력을 확인합니다.

다음 스크린샷과 같이 오른쪽 패널에서 사용할 모델을 선택하고 일부 설정을 미세 조정할 수 있습니다.

8aa89a1970ea9335.png

사용 가능한 설정은 다음과 같습니다.

  • 리전은 생성 요청을 실행해야 하는 위치입니다.
  • 모델은 사용할 대규모 언어 모델을 선택합니다. 이 Codelab에서는 'gemini-1.0-pro-001'을 계속 사용합니다.
  • 강도는 토큰 선택의 무작위성 수준을 제어합니다. 강도가 낮을수록 참 또는 정답이 예상되는 프롬프트에 적합한 반면, 강도가 높을수록 보다 다양하거나 예기치 않은 결과가 발생할 수 있습니다.
  • 토큰 한도는 프롬프트 1개의 최대 텍스트 출력량을 결정합니다. 토큰 1개는 약 4자(영문 기준)입니다. 기본값은 1024입니다.
  • Top-K는 모델이 출력용 토큰을 선택하는 방식을 변경합니다. Top-K가 1이면 선택된 토큰이 모델의 어휘에 포함된 모든 토큰 중에서 가장 확률이 높다는 의미입니다(그리디 디코딩이라고도 함). 반면에 Top-K가 3이면 강도를 사용하여 가장 확률이 높은 토큰 3개 중에서 다음 토큰이 선택된다는 의미입니다. 기본 최상위 K 값은 40입니다.
  • Top-P는 모델이 출력용 토큰을 선택하는 방식을 변경합니다. 토큰의 확률 합계가 Top-P 값과 같아질 때까지 확률이 가장 높은 순에서 낮은 순으로 토큰이 선택됩니다.
  • 최대 응답 수는 프롬프트당 생성되는 최대 모델 응답 수입니다.
  • 중지 시퀀스는 모델에서 응답이 발생할 경우 응답 생성을 중지하는 일련의 문자(공백 포함)입니다.
  • 스트리밍 응답은 응답을 생성하거나 저장할 때 인쇄해야 하는지 여부를 선택하고 완료 시 표시합니다.
  • 안전 필터 기준점은 유해할 수 있는 응답이 표시될 가능성을 조정합니다.

위에 언급된 요구사항에 따라 합당한 퀴즈를 생성하는 것으로 보이는 프롬프트가 있으면 커스텀 코드를 사용하여 이 퀴즈를 파싱할 수 있지만 LLM이 프로그램에 직접 로드할 수 있는 구조화된 형식으로 퀴즈를 생성하는 것이 더 좋지 않을까요? 이 실습의 뒷부분에서 생성기를 호출하는 데 사용할 프로그램에서는 퀴즈가 구조화된 데이터를 나타내는 데 널리 사용되는 언어 간 형식인 JSON으로 표현되어야 합니다.

이 실습의 퀴즈는 객체의 배열로 표현되며, 각 객체에는 질문과 해당 질문에 대해 가능한 답변의 배열, 정답이 포함됩니다. 이 실습에서 퀴즈를 위한 JSON 인코딩은 다음과 같습니다.

[
    {
        "question": "Who was the first person to walk on the moon?",
          "responses": [
              "Neil Armstrong",
              "Buzz Aldrin",
              "Michael Collins",
              "Yuri Gagarin"
           ],
           "correct": "Neil Armstrong"
    },
    {
        "question": "What was the name of the war that took place between the British and the French in North America from 1754 to 1763??",
          "responses": [
              "The French and Indian War",
              "The Seven Years' War",
              "The War of the Austrian Succession",
              "The Great War"
           ],
           "correct": "The French and Indian War"
    },

    ...
]

이제 프롬프트를 수정하여 퀴즈를 필수 JSON 형식으로 출력할 수 있는지 확인합니다.

  1. 찾고 있는 정확한 형식을 단어로 지정하세요 (예: 위의 기울임꼴로 표시된 문장).
  2. 원하는 JSON 형식의 예시를 프롬프트에 포함합니다.

원하는 사양에 따라 퀴즈를 생성하는 프롬프트가 표시되면 페이지의 오른쪽 상단에 있는 GET CODE 버튼을 클릭하여 Vertex AI LLM에 프롬프트를 프로그래매틱 방식으로 제출하는 데 사용할 수 있는 Python 코드를 확인합니다. Python 이외의 프로그래밍 언어를 사용하는 데 관심이 있다면 https://cloud.google.com/vertex-ai/docs/samples?text=generative를 확인하세요.

4. 간단한 웹 서버 빌드

c73008bb8a72b57b.png

이제 작동하는 프롬프트가 있으므로 더 큰 앱에 통합해 보겠습니다. 물론 더 큰 앱의 소스 코드에 프롬프트를 삽입할 수도 있지만, 생성기가 다른 앱에 퀴즈 생성 서비스를 제공하는 마이크로서비스 역할을 하기를 원합니다. 이를 위해서는 간단한 웹 서버를 만들어 공개적으로 사용할 수 있도록 해야 합니다. 다음 단계에서는 이 작업을 수행합니다.

먼저 Cloud Shell 패널 상단에 있는 Open Editor 버튼을 클릭합니다. 상태 메시지가 표시됩니다.

e2a06b5304079efc.png

그러면 Visual Studio Code와 유사한 IDE 환경에서 프로젝트를 생성하고, 소스 코드를 수정하고, 프로그램을 실행하는 등의 작업을 수행할 수 있습니다.

화면이 너무 좁은 경우 여기에 강조표시된 두 영역 사이의 가로 막대를 드래그하여 콘솔과 수정/터미널 창 사이의 구분선을 확장하거나 축소할 수 있습니다.

8dea35450851af53.png

Open Editor 버튼과 Open Terminal 버튼을 각각 클릭하여 편집기와 터미널 간에 전환할 수 있습니다. 지금 두 환경 사이를 번갈아 가며 사용해 보세요.

다음으로 폴더 추가 버튼 5f4e64909bc15e30.png을 클릭하고 quiz-generator을 입력한 후 Enter 키를 눌러 이 실습 작업을 저장할 폴더를 만듭니다. 이 실습에서 만든 모든 파일과 Cloud Shell에서 수행하는 모든 작업이 이 폴더에 저장됩니다.

이제 requirements.txt 파일을 만듭니다. 이는 앱이 사용하는 라이브러리를 Python에 알려줍니다. 이 간단한 웹 앱에서는 google-cloud-aiplatform 클라이언트 라이브러리인 Flask,이라는 웹 서버 빌드에 널리 사용되는 Python 모듈과 gunicorn라는 웹 서버 프레임워크를 사용합니다. 파일 탐색창에서 quiz-generator 폴더를 마우스 오른쪽 버튼으로 클릭하고 다음과 같이 New file 메뉴 항목을 선택합니다.

613eb3de4b9b750a.png

새 파일의 이름을 입력하라는 메시지가 표시되면 requirements.txt를 입력하고 Enter 키를 누릅니다. 새 파일이 quiz-generator 프로젝트 폴더에 있는지 확인합니다.

다음 줄을 새 파일에 붙여넣어 앱이 Python flask 패키지, gunicorn 웹 서버, google-cloud-aiplatform 클라이언트 라이브러리와 각 제품의 관련 버전에 종속된다는 것을 지정합니다.

flask==3.0.0
gunicorn==21.2.0
google-cloud-aiplatform==1.47.0

Cloud 편집기가 변경사항을 자동으로 저장하므로 이 파일을 명시적으로 저장할 필요가 없습니다.

같은 방법을 사용하여 main.py이라는 또 다른 새 파일을 만듭니다. 이 파일이 앱의 유일한 기본 Python 소스 파일이 됩니다. 새 파일이 quiz-generator 폴더에 있는지 다시 확인합니다.

이 파일에 다음 코드를 삽입합니다.

from flask import Flask
import os

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
@app.route("/", methods=["GET"])
def say_hello():
    html = "<h1>Hello world!</h1>"
    return html

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

터미널로 다시 전환하고 다음 명령어를 사용하여 프로젝트 폴더로 변경합니다.

cd quiz-generator

다음 명령어를 실행하여 프로젝트 종속 항목을 설치합니다.

pip3 install -r requirements.txt

종속 항목을 설치한 후 다음과 같이 끝나는 출력이 표시됩니다.

Successfully installed flask-3.0.0

이제 터미널에서 다음 명령어를 실행하여 앱을 실행합니다.

flask --app main.py --debug run --port 8080

이 시점에서 앱은 Cloud Shell 세션 전용 가상 머신에서 실행됩니다. Cloud Shell에는 전역 인터넷 어디에서나 가상 머신에서 실행되는 웹 서버 (예: 방금 시작한 서버)에 액세스할 수 있는 프록시 메커니즘이 포함되어 있습니다.

web preview 버튼을 클릭한 후 다음과 같이 Preview on Port 8080 메뉴 항목을 클릭합니다.

7f938c0bc1b4154c.png

그러면 실행 중인 앱의 웹브라우저 탭이 열리고 다음과 같이 표시됩니다.

aaaf366f9bf74a28.png

5. 매개변수 파싱으로 생성 메서드 추가

이제 generate라는 새 메서드를 필드링하기 위한 지원을 추가하려고 합니다. 다음과 같이 import 문을 추가하여 HTTP 요청을 조작하고 기본 경로를 수정하여 이 요청을 파싱하고 매개변수를 출력하면 됩니다.

from flask import Flask
from flask import request                       #<-CHANGED
import os

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# The app.route decorator routes any GET requests sent to the /generate
# path to this function, which responds with "Generating:" followed by
# the body of the request.
@app.route("/", methods=["GET"])                #<-CHANGED
def generate():                                 #<-CHANGED
    params = request.args.to_dict()             #<-CHANGED
    html = f"<h1>Quiz Generator</h1>"           #<-CHANGED
    for param in params:                        #<-CHANGED
        html += f"<br>{param}={params[param]}"  #<-CHANGED
    return html                                 #<-CHANGED

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

이제 기존 웹브라우저 탭을 새로고침하여 결과를 확인합니다. 이번에는 URL (authuser)에 자동으로 추가된 쿼리 매개변수와 함께 '퀴즈 생성기'가 표시됩니다. 문자열 "`&param1=val1&param2=val2`를 추가하여 매개변수 두 개를 더 추가해 보세요. 를 브라우저의 주소 표시줄에 있는 URL 끝에 붙여넣고 페이지를 새로고침하면 다음과 같이 표시됩니다.

6e223ca358e4e009.png

이제 URL에서 쿼리 매개변수를 전송하고 파싱하는 방법을 살펴봤으므로 다음과 같이 퀴즈 생성기를 전송할 특정 매개변수에 대한 지원을 추가해 보겠습니다.

  • topic - 원하는 퀴즈 주제
  • num_q - 원하는 질문 수
  • diff - 원하는 난이도 (쉬움, 중급, 어려움)
  • lang - 원하는 퀴즈 언어
from flask import Flask
from flask import request
import os

# Default quiz settings  #<-CHANGED
TOPIC = "History"        #<-CHANGED
NUM_Q = "5"              #<-CHANGED
DIFF = "intermediate"    #<-CHANGED
LANG = "English"         #<-CHANGED

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# This function takes a dictionary, a name, and a default value.
# If the name exists as a key in the dictionary, the corresponding
# value is returned. Otherwise, the default value is returned.
def check(args, name, default):  #<-CHANGED
    if name in args:             #<-CHANGED
        return args[name]        #<-CHANGED
    return default               #<-CHANGED

# The app.route decorator routes any GET requests sent to the /generate
# path to this function, which responds with "Generating:" followed by
# the body of the request.
@app.route("/", methods=["GET"])
# This function generates a quiz using Vertex AI.
def generate():
    args = request.args.to_dict()        #<-CHANGED
    topic = check(args, "topic", TOPIC)  #<-CHANGED
    num_q = check(args, "num_q", NUM_Q)  #<-CHANGED
    diff = check(args, "diff", DIFF)     #<-CHANGED
    lang = check(args, "lang", LANG)     #<-CHANGED
    html = f"""
        <h1>Quiz Generator</h1><br>
        {topic=}<br>
        {num_q=}<br>
        {diff=}<br>
        {lang=}"""                       #<-CHANGED
    return html

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

이제 기존 웹브라우저 탭을 새로고침하여 결과를 확인합니다. 다음과 같은 웹페이지가 표시됩니다.

15eed60f6a805212.png

URL을 변경하여 다양한 매개변수에 대한 값을 설정해 보세요. 예를 들어 접미사 '?authuser=0&topic=Literature&num_q=10&diff=easy&lang=French'을(를) 사용해 보세요. 를 입력합니다.

f629dba5fa207cef.png

6. 프롬프트 추가 및 서식 지정

다음으로, 퀴즈 생성기를 전송할 특정 매개변수에 관한 지원을 추가합니다. 이러한 매개변수는 다음과 같습니다.

  • topic - 원하는 퀴즈 주제
  • num_q - 원하는 질문 수
  • diff - 원하는 난이도 (쉬움, 중급, 어려움)
  • lang - 원하는 퀴즈 언어

이전 단계에서 Vertex Generative AI Studio로 개발한 프롬프트를 복사하되 주제, 질문 수, 난이도의 하드 코딩 값을 다음 문자열로 변경합니다.

  • {topic}
  • {num_q}
  • {diff}
  • {lang}
from flask import Flask
from flask import request
import os

# Default quiz settings
TOPIC = "History"
NUM_Q = 5
DIFF = "intermediate"
LANG = "English"

PROMPT = """
Generate a quiz according to the following specifications:

- topic: {topic}
- num_q: {num_q}
- diff:  {diff}
- lang:  {lang}

Output should be (only) an unquoted json array of objects with keys:
"Question", "responses", and "correct".

"""  #<-CHANGED

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# This function takes a dictionary, a name, and a default value.
# If the name exists as a key in the dictionary, the corresponding
# value is returned. Otherwise, the default value is returned.
def check(args, name, default):
    if name in args:
        return args[name]
    return default

# The app.route decorator routes any GET requests sent to the /generate
# path to this function, which responds with "Generating:" followed by
# the body of the request.
@app.route("/", methods=["GET"])
# This function generates a quiz using Vertex AI.
def generate():
    args = request.args.to_dict()
    topic = check(args, "topic", TOPIC)
    num_q = check(args, "num_q", NUM_Q)
    diff = check(args, "diff", DIFF)
    lang = check(args, "lang", LANG)
    prompt = PROMPT.format(topic=topic, num_q=num_q, diff=diff, lang=lang)  #<-CHANGED 
    html = f"<h1>Prompt:</h1><br><pre>{prompt}</pre>"                       #<-CHANGED
    return html

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

이제 기존 웹브라우저 탭을 새로고침하여 결과를 확인합니다. 다음과 같은 웹페이지가 표시됩니다.

3c2b9dfcfba86b7a.png

URL을 수정하여 매개변수 4개를 변경해 보세요.

7. Vertex AI 클라이언트 라이브러리 추가

이제 Vertex AI Python 클라이언트 라이브러리를 사용하여 퀴즈를 생성할 준비가 되었습니다. 이렇게 하면 3단계에서 실행한 대화형 프롬프팅이 자동화되고 생성기 서비스에서 Google의 LLM 기능에 프로그래매틱 방식으로 액세스할 수 있게 됩니다. 다음과 같이 main.py 파일을 업데이트합니다.

"YOUR_PROJECT"를 실제 프로젝트 ID로 바꿉니다.

from flask import Flask
from flask import request
from flask import Response                                          #<-CHANGED
import os

import vertexai    
from vertexai.generative_models import GenerativeModel  #<-CHANGED

# Default quiz settings
TOPIC = "History"
NUM_Q = 5
DIFF = "intermediate"
LANG = "English"
MODEL = "gemini-1.0-pro"  #<-CHANGED

PROMPT = """
Generate a quiz according to the following specifications:

- topic: {topic}
- num_q: {num_q}
- diff:  {diff}
- lang:  {lang}

Output should be (only) an unquoted json array of objects with keys "question", "responses", and "correct".

"""

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# Initialize Vertex AI access.
vertexai.init(project="YOUR_PROJECT", location="us-central1")  #<-CHANGED
parameters = {                                                 #<-CHANGED
    "candidate_count": 1,                                      #<-CHANGED
    "max_output_tokens": 1024,                                 #<-CHANGED
    "temperature": 0.5,                                        #<-CHANGED
    "top_p": 0.8,                                              #<-CHANGED
    "top_k": 40,                                               #<-CHANGED
}                                                              #<-CHANGED
model = GenerativeModel(MODEL)             #<-CHANGED

# This function takes a dictionary, a name, and a default value.
# If the name exists as a key in the dictionary, the corresponding
# value is returned. Otherwise, the default value is returned.
def check(args, name, default):
    if name in args:
        return args[name]
    return default

# The app.route decorator routes any GET requests sent to the /generate
# path to this function, which responds with "Generating:" followed by
# the body of the request.
@app.route("/", methods=["GET"])
# This function generates a quiz using Vertex AI.
def generate():
    args = request.args.to_dict()
    topic = check(args, "topic", TOPIC)
    num_q = check(args, "num_q", NUM_Q)
    diff = check(args, "diff", DIFF)
    lang = check(args, "lang", LANG)
    prompt = PROMPT.format(topic=topic, num_q=num_q, diff=diff, lang=lang)
    response = model.generate_content(prompt, generation_config=parameters)  #<-CHANGED
    print(f"Response from Model: {response.text}")           #<-CHANGED
    html = f"{response.text}"                                #<-CHANGED
    return Response(html, mimetype="application/json")       #<-CHANGED

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

이제 기존 웹브라우저 탭을 새로고침하여 결과를 확인합니다. 이제 실제로 LLM 요청을 하게 되므로 몇 초 정도 걸릴 수 있습니다. 다음과 같은 웹페이지가 표시됩니다.

f43d3ba5102857b8.png

URL을 변경하여 다른 퀴즈 주제, 질문 수, 난이도를 요청해 보세요.

이렇게 마이크로서비스가 완성되었습니다. 축하합니다! 다음 단계에서는 누구나 어디서든 서비스에 액세스할 수 있도록 클라우드에 서비스를 배포하는 방법을 알아봅니다.

8. 클라우드로

67c99bf45a7b7805.png

이제 자체 퀴즈 생성기를 빌드했으므로 이 멋진 기능을 전 세계 사용자와 공유하고 싶을 수 있으므로 이제 클라우드에 배포해 보겠습니다. 하지만 단순히 공유하는 것 이상의 일을 하고 싶습니다. 다음 사항을 확인하세요.

  • 안정적으로 실행 - 앱을 실행하는 컴퓨터가 다운되는 경우 자동 내결함성을 제공합니다.
  • 자동으로 확장 - 앱이 방대한 양의 트래픽을 처리할 수 있고 사용하지 않을 경우 공간을 자동으로 줄입니다.
  • 사용하지 않는 리소스에 대해 비용을 청구하지 않으므로, 트래픽에 응답하는 동안 사용한 리소스에 대해서만 비용이 청구되므로 비용이 최소화됩니다.
  • 맞춤 도메인 이름을 통해 액세스 가능 - 원클릭 솔루션에 액세스하여 서비스에 맞춤 도메인 이름을 할당할 수 있습니다.
  • 뛰어난 응답 시간을 제공합니다. 콜드 스타트는 응답 속도가 합리적이지만 최소 인스턴스 구성을 지정하여 이를 세부적으로 조정할 수 있습니다.
  • 표준 SSL/TLS 웹 보안을 사용하여 엔드 투 엔드 암호화를 지원합니다. 서비스를 배포할 때 표준 웹 암호화와 이에 상응하는 필수 인증서가 무료로 자동 제공됩니다.

앱을 Google Cloud Run에 배포하면 위의 모든 기능과 그 밖의 이점을 누릴 수 있습니다. Cloud Run과 앱을 공유하기 위한 기본 구성 요소는 컨테이너입니다.

컨테이너를 사용하면 모든 종속 항목이 번들로 포함된 애플리케이션을 실행할 수 있는 모듈식 박스를 만들 수 있습니다. 컨테이너는 거의 모든 가상 서버 또는 실제 서버에서 사용할 수 있으므로, 이를 통해 온프레미스에서 클라우드로 원하는 곳에 애플리케이션을 배포하고 애플리케이션을 한 서비스 제공업체에서 다른 서비스 제공업체로 이동할 수도 있습니다.

Google Cloud Run에서의 컨테이너 및 컨테이너 작동 방식에 대해 자세히 알아보려면 Cloud Run을 사용한 간단한 3단계로 개발부터 프로덕션까지 Codelab을 확인하세요.

Cloud Run에 앱 배포

Cloud Run은 리전별 서비스입니다. 즉, Cloud Run 서비스를 실행하는 인프라가 특정 리전에 위치해 있으며, 해당 리전 내의 모든 영역에서 중복으로 사용할 수 있도록 Google에서 관리합니다. 이 실습에서는 편의상 하드코딩된 영역 us-central1를 사용합니다.

빌드팩이라는 것을 사용하여 컨테이너를 자동으로 생성하겠습니다. Cloud 편집기에서 Procfile이라는 새 파일을 만들고 다음 텍스트 한 줄을 삽입합니다.

web: gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

이는 자동 생성된 컨테이너에서 앱을 실행하는 방법을 빌드팩 시스템에 알려줍니다. 그런 다음 Cloud Shell 터미널에서 동일한 quiz-generator 디렉터리에 있는 다음 명령어를 실행합니다.

gcloud run deploy quiz-generator  \
    --source .                    \
    --region us-central1          \
    --allow-unauthenticated

이는 현재 디렉터리에서 찾은 소스 파일을 기반으로 빌드팩을 사용하여 컨테이너 이미지를 만들도록 gcloud 명령어에 지시합니다 (--source .dot는 현재 디렉터리의 약어임). 서비스가 암시적으로 컨테이너 이미지를 처리하므로 이 gcloud 명령어에 이미지를 지정할 필요가 없습니다.

그런 다음 배포가 완료될 때까지 잠시 기다립니다. 성공하면 gcloud 명령어가 새 서비스의 URL을 표시합니다.

Building using Buildpacks and deploying container to Cloud Run service [quiz-generator] in project [YOUR_PROJECT] region [YOUR_REGION]
OK Building and deploying new service... Done.                                                                          
  OK Creating Container Repository...                                                                                   
  OK Uploading sources...                                                                                               
  OK Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/0cf1383f-35db-412d
  -a973-557d5e2cd4a4?project=780573810218].                                                                             
  OK Creating Revision...                                                                                               
  OK Routing traffic...                                                                                                 
  OK Setting IAM Policy...                                                                                              
Done.                                                                                                                   
Service [quiz-generator] revision [quiz-generator-00001-xnr] has been deployed and is serving 100 percent of traffic.
Service URL: https://quiz-generator-co24gukjmq-uc.a.run.app

다음 명령어를 사용하여 서비스 URL을 검색할 수도 있습니다.

gcloud run services describe quiz-generator  \
  --region us-central1                       \
  --format "value(status.url)"

다음과 같이 표시됩니다.

https://quiz-generator-co24gukjmq-uc.a.run.app

이 링크는 TLS 보안이 적용된 Cloud Run 서비스 전용 URL입니다. 이 링크는 서비스를 사용 중지하지 않는 한 영구적이며 인터넷 어디에서나 사용할 수 있습니다. 앞에서 언급했듯이 일시적인 가상 머신에 종속된 Cloud Shell의 프록시 메커니즘은 사용하지 않습니다.

강조표시된 Service URL를 클릭하여 실행 중인 앱의 웹브라우저 탭을 엽니다. 결과가 개발 환경에서 확인한 것과 동일한지 확인합니다. 또한 URL 끝에 매개변수를 제공하여 생성된 퀴즈를 조정할 수 있는지 확인합니다.

축하합니다. 이제 앱이 Google의 클라우드에서 실행됩니다. TLS (HTTPS) 암호화 및 자동 확장 기능을 통해 놀라울 정도로 뛰어난 트래픽 수준으로 자동 확장되는 앱이 공개되므로 신경 쓰지 않아도 됩니다.

9. 총정리

9927db1725bcd5d6.png

이 마지막 단계에서는 퀴즈 생성기를 퀴즈 앱의 일부로 실행할 준비가 되었습니다. quizaic URL을 방문하여 Google 계정에 로그인한 다음 Create Quiz 탭으로 이동합니다. 생성기 유형 Custom를 선택하고 Cloud Run URL을 URL 필드에 붙여넣고 다른 필수 필드를 작성한 후 양식을 제출합니다.

328ee05579ea05f9.png

잠시 후 해당 버튼을 통해 수정, 재생, 클론, 삭제할 수 있는 AI 생성 썸네일 이미지가 포함된 새 퀴즈 (아래 이미지의 '내 새 퀴즈' 참고)가 생성됩니다. 이 새로운 퀴즈는 템플릿 형식 프롬프트를 기반으로 방금 배포한 웹 서비스를 사용하여 생성되었습니다.

1719169140978b63.png

10. 삭제

c1592d590c563428.png

Cloud Run에서는 서비스를 사용하지 않을 때 비용이 청구되지 않지만 빌드된 컨테이너 이미지를 저장하는 데 요금이 부과될 수 있습니다.

GCP 프로젝트를 삭제하여 요금이 청구되지 않도록 하거나, 해당 프로젝트 내에서 사용된 모든 리소스에 대한 청구가 중지되도록 하거나, 다음 명령어를 사용하여 컨테이너 이미지를 삭제할 수 있습니다.

gcloud config set artifacts/repository cloud-run-source-deploy
gcloud config set artifacts/location us-central1
gcloud artifacts docker images list

# Note image tag for resulting list

gcloud artifacts docker images delete <IMAGE-TAG>

Cloud Run 서비스를 삭제하려면 다음 명령어를 사용합니다.

gcloud run services delete quiz-generator --region us-central1 --quiet

11. 해냈어요!

910162be58c0f6d6.png

수고하셨습니다. LLM 프롬프트를 작성하고 이 프롬프트를 사용하여 Cloud Run 마이크로서비스를 배포했습니다. 이제 자연어로 프로그래밍하고 창작물을 전 세계에 공유할 수 있습니다.

한 가지 중요한 질문을 하겠습니다.

앱이 개발자 환경에서 작동하도록 한 후 Cloud Run에서 제공하는 모든 프로덕션 등급 속성을 포함하여 클라우드에 배포하기 위해 몇 줄의 코드를 수정해야 했나요?

물론 답은 0입니다.

살펴볼 다른 Codelab...

참조 문서…

12. 액션 유도하기

이 Codelab이 만족스러웠고 Google Cloud를 실습하는 시간이 더 길다면 지금 바로 Google Cloud Innovators에 가입해 보세요.

498cab7d87ec12d3.png

Google Cloud Innovators는 무료이며 다음 서비스가 제공됩니다.

  • Google 직원으로부터 직접 최신 소식을 배울 수 있는 실시간 토론, AMA, 로드맵 세션
  • 최신 Google Cloud 소식을 이메일로 받아보세요.
  • 디지털 배지 및 화상 회의 배경
  • 실습 및 Skills Boost 학습 500크레딧 제공

등록하려면 여기를 클릭하세요.