1. 简介
在此 Codelab 中,我们将构建一个照片修复工具 GlowUp。GlowUp 使用 AI 技术修复旧照片、损坏的照片或黑白照片,生成高画质的 4K 彩色图片。您可以使用此工具让家庭照片焕发新生,甚至可以将其用于修复损坏的插图、图纸、绘画或其他形式的图片。
您将使用 Genkit Go 来实现应用逻辑,并使用 Gemini 3 Pro Image(也称为 Nano Banana Pro)作为处理照片的模型。
前提条件
- 具备 Go 编程语言的基础知识
- 对 Google Cloud 控制台有基本的了解
学习内容
- 如何在 Go 中开发 Genkit 应用
- Genkit 的基本概念,例如工作流、插件和提示
- 如何使用 Handlebars 模板撰写提示
- 如何从模型回答中获取图片数据
所需条件
本研讨会完全可以在 Google Cloud Shell 中完成,其中预安装了所有必需的依赖项(gcloud CLI、代码编辑器、Go、Gemini CLI)。
或者,如果您希望在自己的机器上操作,则需要满足以下条件:
- Go 工具链(1.24 版或更高版本)
- Node.js v20 或更高版本(适用于
genkitCLI) - 安装了
gcloudCLI 的终端 - 用于修改代码的 IDE,例如 VS Code 或类似工具
- 推荐:Gemini CLI 或 Antigravity 等编码代理
关键技术
您可以在这里找到有关我们将使用的技术的更多信息:
- Gemini Nano Banana Pro(Gemini 3 Pro Image):为我们的修复流程提供支持的模型
- Genkit Go:用于编排模型调用的工具包
2. 环境设置
选择以下选项之一:如果您想在自己的机器上运行此 Codelab,请选择自行设置环境;如果您想完全在云端运行此 Codelab,请选择启动 Cloud Shell。
自定进度的环境设置
- 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个。



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

预配和连接到环境应该只需要片刻时间。完成后,您应该会看到如下内容:

这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5 GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。您在此 Codelab 中的所有工作都可以在浏览器中完成。您无需安装任何程序。
3. 项目设置
创建项目
首先,我们需要为项目创建一个新目录并初始化 Go 模块。在终端中,运行以下命令:
mkdir -p glowup && cd glowup
go mod init glowup
安装 Genkit CLI
现在,我们需要安装 Genkit CLI。这样您就可以访问本地开发者工具,包括开发者界面。在终端窗口中,输入:
curl -sL cli.genkit.dev | bash
配置环境变量
确保您已设置正确的 Google Cloud 凭据。将 your-project-id 替换为您的实际项目 ID。使用 Gemini 3 Pro 预览版模型(Nano Banana Pro 是其中之一)时,位置必须为 global。
export GOOGLE_CLOUD_PROJECT=$(gcloud config get project)
export GOOGLE_CLOUD_LOCATION=global
在 shell 模式下运行以下命令,以启用 Vertex AI API:
gcloud services enable aiplatform.googleapis.com
如果您在本地机器(而非 CloudShell)上运行,则需要使用 gcloud 命令进行身份验证:
gcloud auth application-default login
4. 创建您的首个 Genkit 应用
Genkit 是一个开源框架,旨在帮助开发者构建、部署和监控可用于生产用途的 AI 赋能的应用。在本部分中,我们将创建一个简单的“Hello World”应用,以便您在深入了解照片修复逻辑之前熟悉该框架。
Genkit 术语
在开始使用 Genkit 之前,请务必了解以下几个关键术语:
- 插件:用于扩展 Genkit 的功能。您可以通过插件注册 AI 模型,从而为应用提供支持。
- 流程:Genkit 的主要架构组件。典型流程会获取输入、处理输入并返回输出。它不一定需要使用模型,但在大多数情况下,您会在流程中使用模型。
- 提示:以 dotprompt 格式存储的互动模板(保存为
*.prompt文件)。这些文件不仅包含模型指令,还包含模型名称、模型参数、输入和输出等配置。
与 AI 模型互动
Genkit 使用插件将您的代码连接到模型提供商。我们为所有主要模型提供商(包括 Google、Anthropic 和 OpenAI)提供了插件。您还可以使用插件连接到本地模型(例如使用 Ollama)或扩展 Genkit 的功能(例如连接到 MCP 服务器)。
如需访问 Google 模型,您应使用 googlegenai 插件。它支持两个后端:
- Google AI:非常适合原型设计。使用 API 密钥。
- Vertex AI (Google Cloud):建议用于生产环境。使用项目 ID 和位置。
在此 Codelab 中,我们将使用 Vertex AI 身份验证,并引用您在本实验开始时创建的项目。
创建问候流程
在深入了解“美化”照片修复流程之前,我们先构建一个基本流程,以便熟悉相关概念并确保设置正常运行。
flow 是一种特殊的 Genkit 函数,可封装您的 AI 逻辑,以提供以下功能:
- 类型安全的输入和输出:使用 Go 结构体定义架构,以进行静态和运行时验证
- 流式传输支持:流式传输部分响应或自定义数据
- 开发者界面集成:通过可视化轨迹测试和调试 flow
- 轻松部署:可作为 HTTP 端点部署到任何平台
打开 IDE,然后在项目目录中创建一个 main.go 文件。如果您使用的是 Cloud Shell,可以使用以下命令:
cloudshell edit main.go
然后添加以下代码:
main.go
package main
import (
"context"
"log"
"os"
"os/signal"
"syscall"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
// Initialize Genkit with the Vertex AI plugin
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.VertexAI{}),
)
// Define the greeter flow
genkit.DefineFlow(g, "greeter", func(ctx context.Context, name string) (string, error) {
text, err := genkit.GenerateText(ctx, g,
ai.WithModelName("vertexai/gemini-2.5-pro"),
ai.WithPrompt("Say a warm and creative hello to %s", name),
)
if err != nil {
return "", err
}
return text, nil
})
// Register the flow here in the next steps
log.Println("GlowUp initialized. Ready for flows.")
<-ctx.Done()
}
保存文件,然后运行 go mod tidy 以更新依赖项:
go mod tidy
上述代码使用 VertexAI 插件初始化 Genkit,定义一个名为“greeter”的流程,然后无限期等待 <-ctx.Done()。我们正在暂停执行,以便此程序不会立即终止,因为我们没有为其提供任何实际执行流程的指令。
这意味着,如果您按原样运行此程序,它本身不会执行太多操作 - 我们需要以某种方式调用该流程。虽然在实际的生产应用中,我们会将此流程封装在 Web 服务器或 CLI 应用中,但在开发期间,我们可以使用 genkit CLI 来帮助我们开发和优化流程。
开发 genkit CLI 的目的是帮助我们测试 Genkit 堆栈的模型、提示、流程和其他组件。它还完全支持轨迹,这在您想了解应用在底层是如何运作时非常方便。如需使用 genkit CLI 启动欢迎流程,请运行以下命令:
genkit start -- go run main.go
这将启动 Telemetry API 和开发者界面端点。您应该会看到与以下类似的内容:
$ genkit start -- go run main.go Telemetry API running on http://localhost:4033 Project root: /home/daniela/glowup Genkit Developer UI: http://localhost:4000
如果您在浏览器中打开 localhost:4000 以启动开发者界面,您应该会看到如下屏幕:

您可以花些时间探索开发者界面。也许可以触发一次“问候语”流程,看看它如何运作。
使用提示模板
虽然您可以像上一个示例中那样在模型调用中对提示进行硬编码,但更好的方法是创建提示模板,以集中方式存储应用的所有提示。这不仅让您在维护代码时更轻松地找到提示,还让您能够独立于流程来试验提示。
为了定义提示模板,Genkit 使用开源的 dotprompt 格式,并以 *.prompt 文件的形式保存。.prompt 文件由两部分组成:
- 前言:一个 YAML 块,用于定义模型、模型参数以及输入和输出架构
- 正文:提示本身的正文,可以使用“handlebars”语法进行模板化。例如,如果您定义了一个名为
variable-name的输入,则可以在正文中将其引用为{{variable-name}}。
项目的目录结构将如下所示:
glowup/
├── main.go
└── prompts/
└── greeter.prompt
我们来看看实际用例。首先,创建用于存储提示的文件夹:
mkdir -p prompts
然后,创建 greeter.prompt 文件:
cloudshell edit prompts/greeter.prompt
并插入以下内容:
greeter.prompt

此提示展示了模板语言的一些功能。首先,我们在前言中指定模型 vertexai/gemini-2.5-flash。如需指定模型,您需要使用相应插件文档中定义的命名惯例。
通过配置部分,我们可以配置模型参数。我们将温度设为 1.9,以便模型更具创意。温度范围为 0(输出更一致)到 2(输出更具创意)。此参数和其他模型参数通常会发布在模型的工作表中。例如,以下是 gemini-2.5-flash 的模型卡片。
在输入部分,我们可以指定提示的实参。在本例中,我们将名称定义为字符串。在前言之后,我们有提示正文。第一个代码块定义了系统提示,第二个代码块是用户提示。所有这些要素结合在一起,可实现一些非常强大的提示技巧。您可以点击dotprompt 此处查看完整文档。
现在,我们来调整 greeter 流程,以使用刚刚创建的提示:
main.go
package main
import (
"context"
"os"
"os/signal"
"syscall"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
// Initialize Genkit with the Vertex AI plugin
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.VertexAI{}),
genkit.WithDefaultModel("vertexai/gemini-2.5-flash"),
)
// Define the greeter flow
genkit.DefineFlow(g, "greeter", func(ctx context.Context, name *string) (string, error) {
prompt := genkit.LookupPrompt(g, "greeter")
input := map[string]any{
"name": name,
}
resp, err := prompt.Execute(ctx, ai.WithInput(input))
if err != nil {
return "", err
}
return resp.Text(), nil
})
<-ctx.Done()
}
尝试从命令行运行流,分别使用名称和不使用名称,以查看差异。运行时不带名称:
genkit flow:run greeter
输出示例:
$ genkit flow:run greeter Telemetry API running on http://localhost:4035 Running '/flow/greeter' (stream=false)... Result: "Hello there, absolutely delightful human!\n\nThe very moment your message arrived, the day instantly sparkled a little brighter. It's not just nice, it's genuinely **wonderful** to meet you!\n\nMay your entire day be filled with unexpected pockets of joy, effortless triumphs, and all the happiness you truly deserve! We're thrilled to have you here!"
以及带有名称:
genkit flow:run greeter '{"name":"Daniela"}'
输出示例:
$ genkit flow:run greeter '{"name":"Daniela"}'
Telemetry API running on http://localhost:4035
Running '/flow/greeter' (stream=false)...
Result:
"Well hello there, Daniela! What a truly beautiful name, and what an absolute pleasure it is to meet you!\n\nRight from this moment, I just know your day is going to be brimming with positive energy and wonderful surprises. May it be filled with brilliant ideas, joyful moments, and the delightful realization that you're an amazing person doing incredible things. So glad you're here!"
您可以看到,该模板按预期运行。我们已准备好将此项目提升到新的水平!
5. 使用 Nano Banana Pro 修复图片
恢复提示
现在,您已经熟悉了 Genkit 的基本组件,接下来可以创建照片修复提示了。
在提示目录中创建一个名为 glowup.prompt 的文件,并将以下内容粘贴到其中:
glowup.prompt

恢复提示与我们的“问候”提示遵循相同的模式,但有以下几个显著区别:
- 图片大小:
imageConfig的imageSize属性是 Nano Banana Pro 的模型专用形参。这样一来,我们就可以将输出大小指定为 1K、2K 或 4K。 - 媒体输入:我们使用
{{ media }}模板将照片注入到用户提示中。借助此技术,我们可以向模型发送多模态提示(文本 + 图片)。
您可以在开发者界面中测试此提示。您可以随意调整它,看看它对输出有何影响。
映像恢复流程
恢复提示已准备就绪,现在我们来构建 CLI 应用。将 main.go 的内容替换为以下代码:
main.go
package main
import (
"context"
"encoding/base64"
"errors"
"flag"
"fmt"
"log"
"mime"
"os"
"os/signal"
"strings"
"syscall"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
url := flag.String("url", "", "url of the image to restore")
contentType := flag.String("contentType", "image/jpeg", "content type of the image (default: image/jpeg)")
flag.Parse()
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
// Initialize Genkit with the Vertex AI plugin
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.VertexAI{}),
)
// Input schema for the glowUp flow
type Input struct {
URL string `json:"url,omitempty"`
ContentType string `json:"contentType,omitempty"`
}
glowup := genkit.DefineFlow(g, "glowUp", func(ctx context.Context, input Input) (string, error) {
// 1. Retrieve prompt
prompt := genkit.LookupPrompt(g, "glowup")
if prompt == nil {
return "", errors.New("prompt 'glowup' not found")
}
resp, err := prompt.Execute(ctx, ai.WithInput(input))
if err != nil {
return "", fmt.Errorf("generation failed: %w", err)
}
return resp.Media(), nil
})
// triggers the flow and returns the encoded response from the model
out, err := glowup.Run(ctx, Input{URL: *url, ContentType: *contentType})
if err != nil {
log.Fatalln(err)
}
// decodes image data and returns the appropriate file extension
data, ext, err := decode(out)
if err != nil {
log.Fatalln(err)
}
// writes restored file to disk
filename := "restored" + ext
if err := os.WriteFile(filename, data, 0644); err != nil {
log.Fatalln(err)
}
}
// decode returns the decoded data and the file extension appropriate for the mime type
func decode(text string) ([]byte, string, error) {
if !strings.HasPrefix(text, "data:") {
return nil, "", errors.New("unsupported enconding format")
}
text = strings.TrimPrefix(text, "data:")
parts := strings.Split(text, ";base64,")
mimeType := parts[0]
decoded, err := base64.StdEncoding.DecodeString(parts[1])
if err != nil {
return nil, "", err
}
ext, err := mime.ExtensionsByType(mimeType)
if err != nil {
return nil, "", err
}
return decoded, ext[0], nil
}
此代码在结构上与 greeter 数据流非常相似,但这次它经过调整,可以作为独立的 CLI 应用运行。它不会永远阻塞,而是会运行 glowUp 流、解码输出并将生成的二进制数据保存到磁盘。
我们需要对输出进行解码,因为模型会以以下格式返回图片数据:
data:<mime type>;base64,<base64 encoded image>
您可以在 decode 函数中看到,我们使用字符串操作来拆分 MIME 类型和编码的图片部分。然后,我们使用 mime.ExtensionByType 和 base64.DecodeString 函数提取保存文件所需的信息。
测试恢复流程
现在,终于可以运行此流程并使用真实图片了!如果您手边没有任何需要修复的旧照片,可以尝试使用从美国国会图书馆网站上检索到的这张公共领域图片:

以下是照片的直接链接,可将其传递给流程:https://tile.loc.gov/storage-services/service/pnp/fsa/8c01000/8c01700/8c01765v.jpg
export IMAGE_URL="https://tile.loc.gov/storage-services/service/pnp/fsa/8c01000/8c01700/8c01765v.jpg"
go run main.go --url $IMAGE_URL
以下是恢复并着色后的输出:

成功!
6. 将 glowUp 部署为 Web 服务
如果您想在 Web 服务中公开 flow,而不是通过命令行应用,Genkit 提供了一种便捷的方式,可使用 genkit.Handler 适配器将 flow 转换为端点。以下代码使用 genkit.Handler 将 glowUp 流注册为 glowUp 端点。
您可以像往常一样使用标准库中的 http 软件包通过常规 HTTP 服务器公开它们,但 Genkit 还提供了一个 server 插件,可帮助处理一些常见的服务器样板代码,例如妥善处理关闭信号。
将 main.go 的内容替换为以下代码,以创建您的 Web 服务器。
package main
import (
"context"
"errors"
"fmt"
"log"
"net/http"
"os"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
"github.com/firebase/genkit/go/plugins/server"
)
func main() {
ctx := context.Background()
PORT := os.Getenv("PORT")
if PORT == "" {
PORT = "8080"
}
listenAddr := ":" + PORT
// Initialize Genkit with the Vertex AI plugin
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.VertexAI{}),
)
// Input schema for the glowUp flow
type Input struct {
URL string `json:"url,omitempty"`
ContentType string `json:"contentType,omitempty"`
}
genkit.DefineFlow(g, "glowUp", func(ctx context.Context, input Input) (string, error) {
prompt := genkit.LookupPrompt(g, "glowup")
if prompt == nil {
return "", errors.New("prompt 'glowup' not found")
}
resp, err := prompt.Execute(ctx, ai.WithInput(input))
if err != nil {
return "", fmt.Errorf("generation failed: %w", err)
}
return resp.Media(), nil
})
log.Printf("GlowUp Flow Server started. Listening on %s", listenAddr)
mux := http.NewServeMux()
for _, flow := range genkit.ListFlows(g) {
mux.HandleFunc("POST /"+flow.Name(), genkit.Handler(flow))
}
if err := server.Start(ctx, listenAddr, mux); err != nil {
// Check if the error is due to context cancellation
if ctx.Err() != nil {
log.Println("GlowUp server shutting down gracefully...")
return
}
log.Fatal(err)
}
}
您可以选择在本地或云端运行此服务。如需在本地运行,您只需直接运行该文件,因为该程序现在已完成,因此我们无需通过 Genkit CLI 启动它。例如:
go run main.go
由于这是一个阻塞操作,因此您需要启动第二个终端来对其进行测试。最快的方法是使用 curl 命令:
curl -sS -X POST http://localhost:8080/glowUp \
-H "Content-Type: application/json" \
-d '{"data":{"url": $IMAGE_URL, "contentType":"image/jpeg"}}' \
> result.json
由于这是服务器响应,我们需要对 base64 编码的图片进行解码:
cat result.json | jq -r '.result' | awk -F ',' '{print $2}' | base64 -d > restored.png
将 Web 服务部署到 Cloud Run
虽然此服务器“可在我的机器上运行”,但在理想情况下,我们会将其部署到所有用户都可以访问的其他位置。部署此类服务最便捷的方式之一是使用 Cloud Run 的“从源代码部署”功能。借助此功能,您甚至无需自行构建容器,一切都会自动完成。
如需使用从源代码部署功能将此服务部署到 Cloud Run,请执行以下命令(将项目 ID 替换为您自己的项目 ID):
gcloud run deploy glowup --source . --region us-central1 --no-allow-unauthenticated --set-env-vars GOOGLE_GENAI_USE_VERTEXAI=True,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT
部署过程可能需要几分钟才能完成。完成后,您可以通过 curl 发送另一个请求来测试端点:
GLOWUP_URL=$(gcloud run services describe glowup --region us-central1 --format='value(status.url)')
curl -X POST "$GLOWUP_URL/glowUp" \
-H "Authorization: Bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \
-d "{\"data\":{\"url\":\"$IMAGE_URL\", \"contentType\":\"image/jpeg\"} }" \
> result.json
同样,我们需要对 base64 编码的图片进行解码:
cat result.json | jq -r '.result' | awk -F ',' '{print $2}' | base64 -d > restored_cloudrun.png
现在,我们有了一个可正常运行的照片修复网络服务器!
可选:为客户端应用进行“氛围编程 (vibe coding)”
编写手动代码很有趣,但如果您之前从未做过某种类型的项目,可能会遇到挑战。幸运的是,如今我们有了编码智能体,可以帮助我们加快这一流程。
在此步骤中,我们将要求 Gemini CLI(或您喜爱的编码智能体)为我们完成工作,而不是自己编写代码。使用以下提示:
GlowUp is a photo restoration service that takes a restoration request as input and returns a restored picture as output. Your task is to create a client application that uses this server to process image urls and save a restored file locally.
TODO:
- Write a CLI application that receives three arguments: an url (required), content type (optional, defaults to image/jpeg) and addr (server address, optional, defaults to localhost:8080)
- The CLI should send a POST request to the /glowUp endpoint in the server with the body '{"data":{"url": <url>, "contentType": <contentType>} }'
- The server response should be parsed by stripping the "data:" prefix. The remainder will have the format <mimeType>;base64,<encoded imageData>
- Extract the mime type and convert to a file extension using the mime package
- Extract the image data and decode it using the base64 package
Save a file named "restored" + the detected file extension
Acceptance Criteria:
- The client builds successfully
- Use the client to restore the image https://tile.loc.gov/storage-services/service/pnp/fsa/8c01000/8c01700/8c01765v.jpg
- Check that restored.png exists after processing the image above
由于同一模块中不能有两个“main”函数,因此代理可能需要稍微重新整理一下文件。观看它工作,并在必要时向它提供服务器代码或代码段,引导它实现正确的植入。
实验结束后进行清理
7. 总结
恭喜!您已使用 Genkit 和 Nano Banana Pro 成功构建了一款高保真照片修复应用,
在此 Codelab 中,您学习了如何执行以下操作:
- 配置环境以开发 Genkit Go 应用
- 使用
dotprompt创建多模态提示 - 使用提示模板创建 Genkit 流
- 使用 Nano Banana Pro 处理图片
- 将 Genkit flow 封装为命令行应用和 Web 服务
- 将 Genkit 应用部署到 Cloud Run
测试完成后,请记得清理环境。
后续步骤
您可以探索此平台中的其他 Codelab,也可以自行改进 glowUp,继续您的学习之旅。
如果您需要一些改进方面的建议,可以尝试以下操作:
- 启用 glowUp CLI 以恢复本地文件
- 为 GlowUp Web 服务创建前端
- 自动检测数据的 MIME 类型
- 执行其他类型的图片处理(从照片到绘画、从绘画到照片、从草图到最终艺术作品等)
- 创建或改进客户端(或许可以构建智能手机应用?)
无限可能尽在您的手中!如果您觉得独自完成这项任务有点困难,可以随时借助 Gemini CLI 或 Antigravity 等编码智能体的帮助。如果您想使用 Genkit 做更多事情,将编码代理与 Genkit MCP 服务器搭配使用可让您的工作轻松许多。
最后,如果您想访问此代码库的完整代码,请点击此处。
祝大家编码顺利!