无论是为个性化内容构建文本还是根据用户偏好调整图像,根据描述生成视觉资产的能力都非常强大。但是,文本到图像的转换通常涉及部署端到端的机器学习解决方案,这是非常耗费资源的。如果这种能力只需要一个 API 调用就可以实现,那么开发人员的流程将变得更简单、更易于使用。
本教程将指导您如何使用 AWS CDK 部署一个无服务器图像生成应用,该应用使用 AWS Lambda 和 Amazon Bedrock 实现,后者是一项完全托管的服务,可以通过 API 访问 Amazon 和第三方模型提供商(例如 Anthropic、Cohere 等)提供的基础模型。开发人员可以通过单个 API 利用领先的基础模型,同时保持采用新模型的灵活性。
该解决方案作为一个静态网站部署在 Amazon S3 上,可以通过 Amazon CloudFront 域进行访问。用户可以输入图像描述,然后该描述将传递给 Lambda 函数(通过 Amazon API Gateway),然后 Lambda 函数将在 Amazon Bedrock 上调用 Stable Diffusion 模型生成图像。
整个解决方案都是使用 Go 构建的 – 包括 Lambda 函数(使用 aws-lambda-go 库)以及使用 AWS CDK 进行完整的解决方案部署。
该代码可在 GitHub 上获得。
先决条件
开始本教程之前,您需要具备以下条件:
克隆此 GitHub 存储库,并将目录切换到正确的目录:
git clone https://github.com/build-on-aws/amazon-bedrock-lambda-image-generation-golangcd amazon-bedrock-lambda-image-generation-golang
使用 AWS CDK 部署解决方案
要开始部署,请简单地调用 cdk deploy
。
cd cdkexport DOCKER_DEFAULT_PLATFORM=linux/amd64cdk deploy
您将看到将要创建的资源列表,并需要确认以继续(输出已缩短以保持简洁)。
Bundling asset BedrockLambdaImgeGenWebsiteStack/bedrock-imagegen-s3/Code/Stage...✨ Synthesis time: 7.84s//.... 省略此部署将根据当前的安全批准级别执行可能敏感的更改 (--require-approval broadening)。请确认您打算进行以下修改://.... 省略您是否希望部署这些更改 (y/n)? y
这将开始创建应用所需的 AWS 资源。
如果要查看在幕后将使用的 AWS CloudFormation 模板,请运行 cdk synth
并检查 cdk.out
文件夹。
您可以在终端中跟踪进度,也可以导航到 AWS 控制台: CloudFormation > Stacks > BedrockLambdaImgeGenWebsiteStack
。
所有资源都创建完成后,您可以尝试该应用程序。您将拥有:
- 图像生成 Lambda 函数和 API Gateway
- 用于主机网站 HTML 页面的 S3 存储桶
- CloudFront 分发
- 以及一些其他组件(如 IAM 角色、权限、S3 存储桶策略等)
由于创建 CloudFront 分发是一个耗时的过程,部署可能需要一些时间。部署完成后,您将收到确认消息以及 S3 存储桶名称、API Gateway URL 和 CloudFront 域名的值。
更新HTML页面并将其复制到S3存储桶
在GitHub仓库中打开index.html
文件,并定位以下文本:ENTER_API_GATEWAY_URL
。将其替换为您在上述CDK部署输出中收到的API Gateway URL。
使用AWS CLI将文件复制到S3中:
aws s3 cp index.html s3://<从CDK输出中获得的S3存储桶名称>
验证文件是否上传成功:
aws s3 ls s3://<从CDK输出中获得的S3存储桶名称>
现在您可以访问网站了!
验证解决方案
在您的Web浏览器中输入CloudFront域名以导航到网站。您应该看到带有预填的描述的网站,该描述可用作提示。
点击生成图片开始该过程。几秒钟后,您应该会看到生成的图像。
修改模型参数
稳定扩散模型允许我们根据需求来优化生成参数。
Stability.ai扩散模型支持以下控制:
- 提示强度(
cfg_scale
)控制图像与提示的相似度,较低的值会增加随机性。 - 生成步骤(
steps
)确定结果的准确度,更多的步骤会产生更精确的图像。 - 种子(
seed
)设置初始噪声水平,可以在使用相同的种子和设置时获得可重复的结果。
点击显示配置进行编辑。
cfg_steps
和steps
的最大值分别为30和150。
别忘记清理
完成后,要删除所有服务,只需使用:
cdk destroy#output prompt (选择 'y' 继续)Are you sure you want to delete: BedrockLambdaImgeGenWebsiteStack (y/n)?
您已成功设置并尝试了完整的解决方案。在结束之前,让我们快速浏览一些代码的重要部分,以更好地了解幕后发生了什么。
代码浏览
由于我们只关注重要部分,为了简洁起见省略了大量代码(如打印语句、错误处理等)。
CDK
您可以在这里查看CDK代码。
我们首先创建API Gateway和S3存储桶。
apigw := awscdkapigatewayv2alpha.NewHttpApi(stack, jsii.String("image-gen-http-api"), nil) bucket := awss3.NewBucket(stack, jsii.String("website-s3-bucket"), &awss3.BucketProps{ BlockPublicAccess: awss3.BlockPublicAccess_BLOCK_ALL(), RemovalPolicy: awscdk.RemovalPolicy_DESTROY, AutoDeleteObjects: jsii.Bool(true), })
然后我们创建CloudFront Origin Access Identity并授予S3存储桶读取权限给CloudFront Origin Access Identity主体。然后我们创建CloudFront Distribution:
- 将S3存储桶指定为源。
- 将之前创建的Origin Access Identity指定为Origin Access Identity。
oai := awscloudfront.NewOriginAccessIdentity(stack, jsii.String("OAI"), nil) bucket.GrantRead(oai.GrantPrincipal(), "*") distribution := awscloudfront.NewDistribution(stack, jsii.String("MyDistribution"), &awscloudfront.DistributionProps{ DefaultBehavior: &awscloudfront.BehaviorOptions{ Origin: awscloudfrontorigins.NewS3Origin(bucket, &awscloudfrontorigins.S3OriginProps{ OriginAccessIdentity: oai, }), }, DefaultRootObject: jsii.String("index.html"), //S3中的文件名称 })
然后,我们创建图像生成 Lambda 函数以及 IAM 权限(用于函数执行 IAM 角色),以允许其调用 Bedrock 操作。
function := awscdklambdagoalpha.NewGoFunction(stack, jsii.String("bedrock-imagegen-s3"), &awscdklambdagoalpha.GoFunctionProps{ Runtime: awslambda.Runtime_GO_1_X(), Entry: jsii.String(functionDir), Timeout: awscdk.Duration_Seconds(jsii.Number(30)), }) function.AddToRolePolicy(awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{ Actions: jsii.Strings("bedrock:*"), Effect: awsiam.Effect_ALLOW, Resources: jsii.Strings("*"), }))
最后,我们配置 Lambda 函数与 API Gateway 的集成,添加 HTTP 路由,并指定 API Gateway 终点、S3 存储桶名称和 CloudFront 域名作为 CloudFormation 输出。
functionIntg := awscdkapigatewayv2integrationsalpha.NewHttpLambdaIntegration(jsii.String("function-integration"), function, nil) apigw.AddRoutes(&awscdkapigatewayv2alpha.AddRoutesOptions{ Path: jsii.String("/"), Methods: &[]awscdkapigatewayv2alpha.HttpMethod{awscdkapigatewayv2alpha.HttpMethod_POST}, Integration: functionIntg}) awscdk.NewCfnOutput(stack, jsii.String("apigw URL"), &awscdk.CfnOutputProps{Value: apigw.Url(), Description: jsii.String("API Gateway 终点")}) awscdk.NewCfnOutput(stack, jsii.String("cloud front 域名"), &awscdk.CfnOutputProps{Value: distribution.DomainName(), Description: jsii.String("cloud front 域名")}) awscdk.NewCfnOutput(stack, jsii.String("s3 存储桶名称"), &awscdk.CfnOutputProps{Value: bucket.BucketName(), Description: jsii.String("s3 存储桶名称")})
Lambda 函数
您可以在此处参考 Lambda 函数代码。
在函数处理程序中,我们从 HTTP 请求正文中提取提示和查询参数中的配置。然后,使用 bedrockruntime.InvokeModel 函数调用模型。请注意,发送给 Amazon Bedrock 的 JSON 负载由 Request
结构的实例表示。
从 Amazon Bedrock Stability Diffusion 模型返回的输出主体是一个 JSON 负载,将其转换为包含生成的图像的 base64
字符串的 Response
结构。此字符串与 CORS
头一起作为 events.APIGatewayV2HTTPResponse 对象返回。
func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) { prompt := req.Body cfgScaleF, _ := strconv.ParseFloat(req.QueryStringParameters["cfg_scale"], 64) seed, _ := strconv.Atoi(req.QueryStringParameters["seed"]) steps, _ := strconv.Atoi(req.QueryStringParameters["steps"]) payload := Request{ TextPrompts: []TextPrompt{{Text: prompt}}, CfgScale: cfgScaleF, Steps: steps, } if seed > 0 { payload.Seed = seed } payloadBytes, err := json.Marshal(payload) output, err := brc.InvokeModel(context.Background(), &bedrockruntime.InvokeModelInput{ Body: payloadBytes, ModelId: aws.String(stableDiffusionXLModelID), ContentType: aws.String("application/json"), }) var resp Response err = json.Unmarshal(output.Body, &resp) image := resp.Artifacts[0].Base64 return events.APIGatewayV2HTTPResponse{ StatusCode: http.StatusOK, Body: image, IsBase64Encoded: false, Headers: map[string]string{ "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "POST,OPTIONS", }, }, nil}//request/response modeltype Request struct { TextPrompts []TextPrompt `json:"text_prompts"` CfgScale float64 `json:"cfg_scale"` Steps int `json:"steps"` Seed int `json:"seed"`}type TextPrompt struct { Text string `json:"text"`}type Response struct { Result string `json:"result"` Artifacts []Artifact `json:"artifacts"`}type Artifact struct { Base64 string `json:"base64"` FinishReason string `json:"finishReason"`}
结论
在本教程中,您使用了AWS CDK部署了一个基于Amazon Bedrock和AWS Lambda实现的无服务器图像生成解决方案,并通过S3上的静态网站通过CloudFront域访问。
如果您对使用AWS Go SDK和Amazon Bedrock Foundation Models(FM)的入门指南感兴趣,请查看此博客文章。
祝您建设愉快!