1. 关于此 Codelab
上次更新时间:2024 年 10 月 11 日
撰写者:Laurie White
图片生成
说实话,使用大语言模型 (LLM) 生成图片很有趣。当然,根据提示生成图片有很多商业应用,从定制广告到富有吸引力的演示文稿,不一而足。(Google Cloud 网站列出了使用广告客户经理的公司的一些具体用例。)不过,查看系统在您搜索“田野中快乐的绿色狗狗”时返回的结果还是很有趣的。
无论您是出于专业还是休闲(或两者兼有)的原因而对图片生成感兴趣,在使用图片生成程序和将其部署到 Web 应用之间都会遇到一些挑战。本实验将帮助您克服这些挑战。
构建内容
在此 Codelab 中,您将构建一个应用,该应用会接受文本提示,并返回一个网页,其中包含使用该提示生成的图片。
学习内容
在本实验中,您将学习:
- 如何在笔记本环境中使用 Google Imagen 根据文本提示创建图片
- 将 Imagen 代码从记事本迁移到 Web 应用时遇到的困难
- 如何部署使用 Imagen 生成图片的 Cloud Run 应用
- 如何在 HTML 中添加 Imagen 中的图片
此 Codelab 重点介绍 Imagen 和部署。对于不相关的概念,我们仅会略作介绍,但是会提供相应代码块供您复制和粘贴。
所需条件
- 最新版 Chrome 浏览器。
- 对 Cloud Run 有一定了解。您可以通过此处的 Codelab 了解这一点。
- 熟悉在 Cloud Shell 或 Cloud Shell Editor 中修改文件。您可以通过此 Codelab 详细了解 Cloud Shell 和 Cloud Shell Editor。
- 启用了结算功能的 Google Cloud 项目。本指南将介绍如何创建项目。许多产品都提供免费层级和免费试用。
如需获取此 Codelab 的完整代码,请访问 https://github.com/Annie29/imagen-deployment。
2. 启用 API
选择要用于此 Codelab 的项目。建议您创建一个新项目,以便在完成后更轻松地移除所有工作。
您需要先启用一些 API,然后才能开始使用 Imagen。
- 转到 Google Cloud Console。
- 前往 Vertex AI 信息中心。
- 选择“启用所有推荐的 API”
3. 探索 Google Imagen(可选)
如果您熟悉 Imagen,可以跳过此部分。
在尝试创建使用 Imagen 的 Web 应用之前,了解 Imagen 的功能非常有用。幸运的是,有许多笔记本可以运行简单的 Imagen 代码,因此我们先从其中一个笔记本开始。
- 前往 https://github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/image_generation.ipynb 中的记事本。
- 选择“在 Colab 中打开”以在 Google 的笔记本服务器中打开笔记本。
- 依次选择“文件”-“在云端硬盘中保存副本”,或点击页面顶部的“复制到云端硬盘”,以创建此记事本的副本。
- 关闭原始副本(以免在错误的副本中进行操作!)。
- 您需要点击右上角的“连接”按钮,才能连接到运行时。
- 开始处理笔记本中的每个单元。
- 如需运行单元,您可以点击单元左侧的方括号 [] 或箭头,也可以使用“运行时”菜单中的“运行所选内容”选项(或其快捷键):
- 重启当前运行时后,您会收到系统崩溃的消息。别担心。这很正常。
- 您需要对笔记本环境进行身份验证。
- 您可以在代码右侧的框中输入项目 ID(而非名称)和位置(如果您尚未设置位置,则可以使用 us-central1),让 Colab 为您将这些信息插入代码中。
- 当您看到“生成图片”时,便有机会了解 Imagen 的功能。您可以随意更改问题并重新运行该单元格,看看能获得哪些不同类型的图片。
- 至此,您应该已经大致了解了 Imagen 如何根据笔记本创建图片。您可以随时完成此 Notebook,详细了解图片参数。
4. 开始构建用于显示图片的 Web 应用
我们将使用 Python 在 Cloud Run 上使用 Flask 框架构建应用。
Python Flask 应用在文件夹中设置如下:
app-folder templates template.html (etc.) anothertemplate.html main.py requirements.txt
模板是包含 HTML 的文件,通常包含命名占位符,程序会在这些占位符中插入生成的文本。main.py
是 Web 服务器应用本身,而 requirements.txt
是 main.py
使用的所有非标准库的列表。
该应用将包含两个页面:第一个页面用于获取提示,第二个页面用于显示图片并允许用户输入其他提示。
首先创建项目框架。
创建文件结构
此 Codelab 假定您的项目位于 imageapp
文件夹中。如果您使用其他名称,请务必相应地更新命令。
选择屏幕右上角的提示图标,进入 Cloud Shell。
您可以使用 shell 窗口顶部的箭头将 shell 移至新标签页,从而获得更多工作空间:
在 Cloud Shell 的主目录中,创建 imageapp
文件夹,切换到该文件夹,然后创建 templates
文件夹。您可以通过命令行或 Cloud Shell 编辑器执行此操作。
创建模板
该应用将包含两个页面:第一个页面(我们将其称为 home.html
)用于获取提示,第二个页面(我们将其称为 display.html
)用于显示图片并允许用户输入其他提示。
使用 Cloud Shell 编辑器或您选择的 Linux 编辑器,创建两个模板。在 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
文件包含用于处理 Web 请求的代码。我们只需处理两项请求:用于获取首页的 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_image
中的 return
语句前添加一行代码,为 image_url
(指向图片的有效网址)赋值。
例如:image_url="<your url here>"
您可以通过 Cloud Shell 在本地运行该程序(使用命令 python main.py
),并使用屏幕右上角的“在端口 8080 上预览”功能预览该程序。
目前,您始终会在您提供的网址中看到图片。接下来,我们来看看如何从应用中获取该值。请务必移除用于为 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]
一次最多可以创建 4 张图片,具体取决于发送到 generate_images
的参数,因此返回的值将是 GeneratedImage
的列表,即使只返回一张图片(如本例所示)也是如此。
现在,我们需要在 WWW 页面上显示该图片。GeneratedImage
确实有一种用于 show
图片的方法,但它仅适用于笔记本环境。不过,您可以通过一种方法保存图片。我们会保存图片,并在渲染模板时发送已保存图片的网址。
这有点棘手,而且有很多方法可以实现。我们来逐步了解其中一种更简单的方法。(如果您更喜欢通过直观的方式学习,请参阅下方显示的步骤图片。)
首先,我们需要保存图片。但它将被命名为什么?使用静态名称可能会出现问题,因为许多人可以同时使用该程序。虽然我们可以为每位用户创建单独的图片名称(使用 UUID 之类的名称),但更简单的方法是使用 Python 的 tempfile
库,该库会创建一个具有唯一名称的临时文件。以下代码将创建一个临时文件,获取其名称,并将图片生成步骤的响应写入临时文件。我们暂时不会在代码中输入它,因为我们需要先获取网址。
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
您可以通过多种方式处理已保存的文件,但最简单、最安全的方法之一是使用数据网址。
借助数据网址,您可以在网址中发送实际数据,而不仅仅是数据的路径。数据网址的语法如下:
data:[image/png][;base64],<data>
如需获取图片的 base64 编码,我们需要打开由 tempfile
保存的文件,并将其读取到变量中。是的,这将是一个大型字符串,但对于现代浏览器和服务器来说应该没问题。然后,我们将使用 base64
库将其编码为字符串,以便在数据网址中发送。
用于执行第三步(创建网址)的最终代码将如下所示:
# 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}"
您可以在下图中看到所有这些步骤:
您需要在程序开头导入 tempfile 和 base64。
import tempfile
import base64
请尝试从 Cloud Shell 运行您的程序,方法是确保您位于包含 main.py
的文件夹中,然后运行以下命令:
python main.py
然后,您可以使用屏幕右上角的“在端口 8080 上预览”功能进行预览。
7. 常见错误
在某些时候,您可能会注意到,在运行程序(测试期间或部署后)时,您会收到类似以下内容的消息:
这很可能是由违反 Google 的 Responsible 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 的唯一 Responsible AI 功能。我们提供了多项功能来保护生成的人脸和儿童,以及图片的常规滤镜。您可以点击此处详细了解这些功能。
8. 将应用部署到 Web
您可以使用 Cloud Shell 中 imageapp
文件夹中的命令将应用部署到 Web 上。请务必在命令中使用您的实际项目 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 项目,请执行以下操作:
- 检索当前项目 ID:
PROJECT_ID=$(gcloud config get-value core/project)
- 确保这是您要删除的项目:
echo $PROJECT_ID
- 删除项目:
gcloud projects delete $PROJECT_ID
10. 恭喜
恭喜,您已成功构建一个 Web 应用,该应用将显示由 Imagen 创建的图片。如何在应用中使用此功能?
后续操作
查看下列 Codelab…