使用生成式 AI 和 Cloud Run 构建测验生成器

1. 简介

在本实验中,您将构建一个用于生成知识问答的 Web 服务,并将其集成到一个有趣且实用的应用中。您将使用一种与以往不同的编程语言:英语!

实践内容…

  • 您将创建一个提示,系统会根据一组条件生成一个知识问答测验。
  • 您将构建一个简单的 Web 应用,并验证其在开发环境中是否按预期运行。
  • 您将逐步向 Web 应用添加逻辑,将其转变为 API 服务器,以便根据一组输入参数生成知识问答。
  • 您将了解使用 Google Cloud Run 将测验生成服务部署到云端有多么容易。
  • 最后,您将配置一个真实应用 ( quizaic.com) 以使用您部署的测验生成器服务,您将能够根据输出结果播放实时测验。

学习内容…

  • 如何为大语言模型 (LLM) 创建模板化提示。
  • 如何使用 Python 创建简单的 Web 服务器应用。
  • 如何在 Web 应用中添加对 Google LLM 的支持。
  • 如何将应用部署到云端,以便任何人都可以试用您新创建的应用。
  • 如何将测验生成器集成到较大的应用中。

所需条件…

  • Chrome 网络浏览器
  • Google 账号
  • 启用了结算功能的 Cloud 项目

本实验的适用对象为各种水平的开发者,包括新手。尽管您将使用 Python,但您无需熟悉 Python 编程就能理解代码内容,因为我们将为您介绍所有代码。

2. 设置

a08aa5878e36b60c.png

本部分涵盖了开始此实验所需执行的所有操作。

自定进度的环境设置

  1. 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串。您可以随时对其进行更新。
  • 项目 ID 在所有 Google Cloud 项目中是唯一的,并且是不可变的(一经设置便无法更改)。Cloud 控制台会自动生成一个唯一字符串;通常情况下,您无需关注该字符串。在大多数 Codelab 中,您都需要引用项目 ID(通常用 PROJECT_ID 标识)。如果您不喜欢生成的 ID,可以再随机生成一个 ID。或者,您也可以尝试自己的项目 ID,看看是否可用。完成此步骤后便无法更改该 ID,并且此 ID 在项目期间会一直保留。
  • 此外,还有第三个值,即部分 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档
  1. 接下来,您需要在 Cloud 控制台中启用结算功能,以便使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有的话)。若要关闭资源以避免产生超出本教程范围的结算费用,您可以删除自己创建的资源或删除项目。Google Cloud 新用户符合参与 300 美元免费试用计划的条件。

启动 Cloud Shell

在本实验中,您将使用 Cloud Shell 会话,这是一个由在 Google 云中运行的虚拟机托管的命令解释器。您可以在自己的计算机本地轻松运行此部分,但借助 Cloud Shell,每个人都可以在一致的环境中获得可重现的体验。完成实验后,您可以在自己的计算机上重试本部分。

4a95152439f0159b

激活 Cloud Shell

  1. 在 Cloud Console 中,点击激活 Cloud Shell853e55310c205094.png

3c1dabeca90e44e5

如果这是您第一次启动 Cloud Shell,您会看到一个中间屏幕,其中描述了它是什么。如果您看到中间屏幕,请点击继续

9c92662c6a846a5c

预配和连接到 Cloud Shell 只需花几分钟时间。

9f0e51b578fecce5.png

此虚拟机已加载所需的所有开发工具。它提供了一个持久的 5 GB 主目录,并在 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. 提示 - Natural Language 编程

92f630373224ead8.png

首先,我们来学习如何为大语言模型开发提示。前往 Google Cloud 控制台 > Vertex AI > Vertex AI Studio(语言)。您应该会看到如下页面:

bfe5706041ae6454.png

Generate Text 下,点击 Text Prompt 按钮。在下一个对话框中,输入您认为可能有助于生成知识问答的提示,并满足以下要求:

  • 主题:世界史
  • 题目数量:5 题
  • 难度等级:中级
  • 语言:英语

点击“提交”按钮查看输出。

如以下屏幕截图所示,您可以在右侧面板中选择要使用的模型并微调某些设置:

8aa89a1970ea9335

您可以使用以下设置:

  • 区域是生成请求应运行的位置。
  • “模型”用于选择您要使用的大型语言模型。在此 Codelab 中,请使用“gemini-1.0-pro-001”。
  • 温度可以控制词元选择的随机性。较低的温度适合希望获得真实或正确回复的提示,而较高的温度可能会引发更加多样化或意想不到的结果。
  • 词元限制决定了一条提示的最大文本输出量。词元约为 4 个字符。默认值为 1024。
  • Top-k 可更改模型选择输出词元的方式。如果 Top-k 设为 1,表示所选词元是模型词汇表的所有词元中概率最高的词元(也称为贪心解码)。如果 Top-k 设为 3,则表示系统将从 3 个概率最高的词元(通过温度确定)中选择下一个词元。Top-k 的默认值为 40。
  • Top-p 可更改模型选择输出词元的方式。系统会按照概率从最高到最低的顺序选择词元,直到所选词元的概率总和等于 Top-p 的值。
  • “Max responses”是指模型针对每个提示生成的回答数量上限。
  • 停止序列是一连串字符(包括空格),如果模型遇到停止序列,则会停止生成回答。
  • “流式回答”用于选择是应在生成回答时即刻输出,还是应将回答保存起来,并在回答生成完毕时显示。
  • 安全过滤器阈值可调整您看到可能有害的回答的可能性。

当您获得一个似乎可以根据上述要求生成合理的测验题目的提示后,我们可以使用自定义代码解析此测验,但如果 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. 构建简单的 Web 服务器

c73008bb8a72b57b.png

现在,您已经有了可用的题目,我们希望将其集成到更大的应用中。当然,我们可以将您的题目嵌入到更大的应用的源代码中,但我们希望您的生成器能够作为微服务运行,为其他应用提供知识问答生成服务。为此,我们需要创建一个简单的 Web 服务器并将其设为公开可用。我们将在后续步骤中进行此操作。

首先,点击 Cloud Shell 面板顶部的 Open Editor 按钮。如下所示:

e2a06b5304079efc.png

然后,您会进入一个类似于 Visual Studio Code 的 IDE 环境,您可以在其中创建项目、修改源代码、运行程序等。

如果屏幕太狭窄,您可以拖动控制台和编辑/终端窗口之间的水平栏,以扩大或缩小这两个区域之间的分界线,如下图突出显示:

8dea35450851af53

您可以分别点击 Open EditorOpen Terminal 按钮,在编辑器和终端之间来回切换。现在,请尝试在这两种环境之间来回切换。

接下来,点击“添加文件夹”按钮 5f4e64909bc15e30.png,输入 quiz-generator,然后按 Enter 键,创建一个用于存储本实验作业的文件夹。您在本实验中创建的所有文件,以及在 Cloud Shell 中执行的所有工作,都将在此文件夹中进行。

现在,创建一个 requirements.txt 文件。这会告知 Python 您的应用依赖于哪些库。对于这个简单的 Web 应用,您将使用一个名为 Flask,google-cloud-aiplatform 客户端库(用于构建 Web 服务器的热门 Python 模块)和一个名为 gunicorn 的 Web 服务器框架。在文件导航窗格中,右键点击 quiz-generator 文件夹,然后选择 New file 菜单项,如下所示:

613eb3de4b9b750a

当系统提示您输入新文件的名称时,输入 requirements.txt 并按 Enter 键。确保新文件最终位于 quiz-generator 项目文件夹中。

将以下代码行粘贴到新文件中,以指定您的应用依赖于 Python flask 软件包、gunicorn Web 服务器和 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 服务器(例如您刚刚启动的服务器)。

依次点击 web preview 按钮和 Preview on Port 8080 菜单项,如下所示:

7f938c0bc1b4154c.png

系统随即会打开一个 Web 浏览器标签页,其中会显示正在运行的应用,该标签页应如下所示:

aaaf366f9bf74a28.png

5. 添加了带有参数解析的生成方法

现在,我们需要添加对字段化名为 generate 的新方法的支持。为此,请添加一个用于操控 HTTP 请求的 import 语句,并修改主路由以解析此请求并输出参数,如下所示:

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)

现在,重新加载现有的网络浏览器标签页以查看结果。这一次,您应该会看到“测验生成器”,以及一个自动添加到网址的查询参数 (authuser)。请尝试添加两个额外的参数,即在浏览器地址栏中的网址末尾附加字符串“`&param1=val1&param2=val2`”,然后重新加载网页,您应该会看到如下内容:

6e223ca358e4e009.png

现在,我们已经了解了如何在网址上发送和解析查询参数,接下来我们将添加对要发送测验生成器的特定参数的支持,如下所示:

  • 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

请尝试更改网址,以设置各种参数的值。例如,您可以尝试在地址栏中的网址末尾使用后缀“?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

请尝试修改网址以更改这四个参数。

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

尝试更改网址,以请求其他知识问答主题、题目数量和难度级别。

至此,您的微服务就完成了,恭喜!在下一步中,您将学习如何在云端部署服务,以便任何人都可以随时随地访问该服务。

8. 欢迎进入云端!

67c99bf45a7b7805

现在,您已经构建了自己的知识问答生成器,接下来便可将其部署到云端,与世界各地的用户分享这项出色的工具。但你确实想做的不仅仅是分享。您希望确保:

  • 运行可靠 - 在运行您应用的计算机崩溃时,您具备自动容错能力
  • 自动扩缩 - 您的应用将能够跟上大量流量,并在闲置时自动缩减其占用空间
  • 可最大限度地降低费用,因为它不会针对未使用的资源向您收费 - 您只需为响应流量期间消耗的资源付费
  • 可通过自定义网域名访问 - 您可以使用一键式解决方案为服务分配自定义网域名
  • 响应时间极短,冷启动的响应速度比较快,但您可以通过指定实例数下限配置进行微调
  • 支持使用标准 SSL/TLS 网站安全功能实现端到端加密 - 在您部署服务时,系统会自动免费为您提供标准网站加密功能和相应的必需证书

将应用部署到 Google Cloud Run 后,您可以获享上述所有优势及其他优势。与 Cloud Run 共享应用的基本构建块是一个容器。

容器让我们能够创建一个模块化盒子,在其中运行捆绑在一起所有依赖项的应用。由于容器可在几乎任何虚拟或真实服务器上使用,因此我们可以将您的应用部署到您喜欢的任何位置(从本地到云端),甚至可以将您的应用从一个服务提供商迁移到另一个服务提供商。

如需详细了解容器及其在 Google Cloud Run 中的运作方式,请参阅 使用 Cloud Run 在三个简单步骤中从开发环境迁移到生产环境 Codelab。

将应用部署到 Cloud Run

Cloud Run 是一项区域级服务,这意味着运行 Cloud Run 服务的基础架构位于特定区域并由 Google 托管,以便在该区域内的所有可用区以冗余方式提供。为简单起见,在本实验中,我们将使用硬编码区域 us-central1

我们将使用一种名为 buildpack 的工具自动生成容器。在 Cloud Editor 中创建一个名为 Procfile 的新文件,并插入下面一行文本:

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

这会告知 Buildpack 系统如何在自动生成的容器中运行您的应用。接下来,在 Cloud Shell 终端中(从同一 quiz-generator 目录)运行以下命令:

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

这会告知 gcloud 命令,您希望它根据在当前目录中找到的源文件使用 buildpack 创建容器映像(--source . 中的 dot 是当前目录的缩写)。由于该服务隐式处理容器映像,因此您无需在此 gcloud 命令中指定映像。

等待部署完成。 成功完成后,gcloud 命令会显示新服务的网址:

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

您还可以使用以下命令检索服务网址:

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

此时,屏幕上应显示如下内容:

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

此链接是您的 Cloud Run 服务专用的 TLS 安全网址。此链接是永久有效的(只要您不停用服务),并且可以在互联网上的任何位置使用。它不使用前面提到的 Cloud Shell 代理机制,该机制依赖于临时虚拟机。

点击突出显示的 Service URL,以打开一个网页浏览器标签页,在其中查看正在运行的应用。验证结果是否与您在开发环境中看到的相同。此外,请验证您是否可以在网址末尾提供参数来调整生成的知识问答。

恭喜!您的应用现在正在 Google Cloud 中运行。您的应用会以公开方式提供,并采用 TLS (HTTPS) 加密,并且会自动扩容以应对惊人的流量。

9. 整合各部分

9927db1725bcd5d6.png

在这一最后一步中,我们将在 quizaic 应用中运行您的知识问答生成器。访问 quizaic 网址,登录您的 Google 账号,然后前往 Create Quiz 标签页。选择生成器类型 Custom,将您的 Cloud Run 网址粘贴到网址字段中,填写其他必填字段,然后提交表单。

328ee05579ea05f9.png

几秒钟后,您应该会看到一个新的知识问答(请参阅下图中的“我的新知识问答”),其中包含 AI 生成的缩略图。您可以通过相应的按钮对其进行修改、玩游戏、克隆或删除。这份新的知识问答是根据您刚刚部署的 Web 服务和模板问题创建的!

1719169140978b63

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 提供的所有生产级属性?

答案当然是零。:)

其他值得一看的 Codelab…

参考文档…

12. 号召性用语

如果您喜欢此 Codelab,并且可能希望花更多时间亲自使用 Google Cloud,不妨立即加入 Google Cloud Innovators

498cab7d87ec12d3.png

Google Cloud Innovators 计划免费,提供以下福利:

  • 通过实时讨论、AMA 和路线图会议,直接向 Google 员工学习最新动态
  • 通过电子邮件接收最新的 Google Cloud 资讯
  • 数字徽章和视频会议背景
  • 价值 500 积分的 Skills Boost 实验和学习积分

点击此处报名!