亚马逊Lex 是一项完全托管的人工智能 (AI) 服务,具有先进的自然语言模型,用于在应用程序中设计、构建、测试和部署对话界面。它采用先进的深度学习技术来理解用户输入,使开发人员能够创建聊天机器人、虚拟助手和其他可以用自然语言与用户交互的应用程序。
使用以下方式管理您的 Amazon Lex 机器人 AWS CloudFormation 允许您创建定义机器人及其依赖的所有 AWS 资源的模板。 AWS CloudFormation 代表您提供和配置这些资源,从而消除了将机器人部署到新环境时出现人为错误的风险。使用 CloudFormation 的好处包括:
- 持续一致 – CloudFormation 模板提供了一种更加一致和自动化的方式来部署和管理与 Amazon Lex 自动程序关联的资源。
- 版本控制 – 借助 AWS CloudFormation,您可以使用 Git 等版本控制系统来管理您的 CloudFormation 模板。这允许您维护机器人的不同版本,并在需要时回滚到以前的版本。
- 雷乌斯能力 – 您可以在多个环境(例如开发、暂存和生产)中重复使用 CloudFormation 模板。这可以节省在不同环境中定义相同机器人的时间和精力。
- 扩展 – 随着您的 Amazon Lex 机器人变得越来越复杂,通过 AWS管理控制台 变得更具挑战性。 AWS CloudFormation 允许采用更简化、更高效的方法来管理机器人的定义和资源。
- 自动化和干细胞工程
– 使用 CloudFormation 模板可以自动执行部署过程。您可以使用 AWS 服务,例如 AWS 代码管道 和 AWS 代码构建 自动构建、测试和部署您的 Amazon Lex 自动程序。
在本文中,我们将指导您完成为 Amazon Lex V2 机器人创建 CloudFormation 模板所涉及的步骤。
解决方案概述
我们选择了 预订行程 bot 作为我们本次练习的起点。我们使用 CloudFormation 模板从头开始创建一个新的机器人,包括定义意图、插槽和其他所需组件。此外,我们还探讨了版本控制、别名、集成等主题 AWS Lambda 函数、创建条件分支以及启用日志记录。
先决条件
您应该具备以下先决条件:
- An AWS账户 创建和部署 CloudFormation 模板
- 必要 AWS身份和访问管理 (我是) 权限 部署 AWS CloudFormation 和模板中使用的资源
- Amazon Lex、Lambda 函数和相关服务的基本知识
- 创建和部署 CloudFormation 模板的基础知识
创建一个IAM角色
首先,您需要创建机器人将使用的 IAM 角色。您可以通过初始化 CloudFormation 模板并将 IAM 角色添加为资源来实现此目的。您可以使用以下模板来创建角色。如果你 下载示例模板 并部署它,您应该看到 IAM 角色已创建。我们在阅读本文时提供了模板示例,并在进一步深入时合并它们。
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: CloudFormation template for book hotel bot.
Resources:
# 1. IAM role that is used by the bot at runtime
BotRuntimeRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lexv2.amazonaws.com
Action:
- "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: LexRuntimeRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "polly:SynthesizeSpeech"
- "comprehend:DetectSentiment"
Resource: "*"
配置 Amazon Lex 自动程序
接下来,您需要添加机器人定义。以下是 Amazon Lex 自动程序定义的 YAML 模板;你一一构建必要的组件:
Type: AWS::Lex::Bot
Properties:
AutoBuildBotLocales: Boolean
BotFileS3Location:
S3Location
BotLocales:
- BotLocale
BotTags:
- Tag
DataPrivacy:
DataPrivacy
Description: String
IdleSessionTTLInSeconds: Integer
Name: String
RoleArn: String
TestBotAliasSettings:
TestBotAliasSettings
TestBotAliasTags:
- Tag
要创建仅包含机器人定义而没有任何意图的机器人,您可以使用以下模板。您可以在此处指定机器人的名称、之前创建的角色的 ARN、数据隐私设置等:
BookHotelBot:
DependsOn: BotRuntimeRole # The role created in the previous step
Type: AWS::Lex::Bot
Properties:
Name: "BookHotel"
Description: "Sample Bot to book a hotel"
RoleArn: !GetAtt BotRuntimeRole.Arn
#For each Amazon Lex bot created with the Amazon Lex Model Building Service, you must specify whether your use of Amazon Lex
#is related to a website, program, or other application that is directed or targeted, in whole or in part, to children under
#age 13 and subject to the Children's Online Privacy Protection Act (COPPA) by specifying true or false in the
#childDirected field.
DataPrivacy:
ChildDirected: false
IdleSessionTTLInSeconds: 300
您还可以 下载更新后的模板。通过部署更新的模板,您可以创建角色和机器人定义。请注意,您是 更新堆栈 您在上一步中创建的。
最后一步需要定义 BotLocales
,它们构成了机器人的大部分功能。这包括,例如, Intents
和 Slot types
。以下是 YAML 模板:
CustomVocabulary:
CustomVocabulary
Description: String
Intents:
- Intent
LocaleId: String
NluConfidenceThreshold: Number
SlotTypes:
- SlotType
VoiceSettings:
VoiceSettings
在这种情况下,您构建 BookHotel
意图,这需要房间类型的自定义槽类型。您设置了 LocaleId
,则 VoiceSettings
。然后你添加 SlotTypes
及其对应的值。
下一步是定义 Intents
,从第一个意图开始, BookHotel
,其中涉及添加话语、槽和槽优先级。这些节点的详细信息在提供的模板中进行了演示。最后,添加第二个意图,即 FallbackIntent
。 请参见以下代码:
BotLocales:
- LocaleId: "en_US"
Description: "en US locale"
NluConfidenceThreshold: 0.40
VoiceSettings:
VoiceId: "Matthew"
SlotTypes:
- Name: "RoomTypeValues"
Description: "Type of room"
SlotTypeValues:
- SampleValue:
Value: queen
- SampleValue:
Value: king
- SampleValue:
Value: deluxe
ValueSelectionSetting:
ResolutionStrategy: ORIGINAL_VALUE
Intents:
- Name: "BookHotel"
Description: "Intent to book a hotel room"
SampleUtterances:
- Utterance: "Book a hotel"
- Utterance: "I want a make hotel reservations"
- Utterance: "Book a {Nights} night stay in {Location}"
IntentConfirmationSetting:
PromptSpecification:
MessageGroupsList:
- Message:
PlainTextMessage:
Value: "Okay, I have you down for a {Nights} night stay in {Location} starting {CheckInDate}. Shall I book the reservation?"
MaxRetries: 3
AllowInterrupt: false
DeclinationResponse:
MessageGroupsList:
- Message:
PlainTextMessage:
Value: "Okay, I have cancelled your reservation in progress."
AllowInterrupt: false
SlotPriorities:
- Priority: 1
SlotName: Location
- Priority: 2
SlotName: CheckInDate
- Priority: 3
SlotName: Nights
- Priority: 4
SlotName: RoomType
Slots:
- Name: "Location"
Description: "Location of the city in which the hotel is located"
SlotTypeName: "AMAZON.City"
ValueElicitationSetting:
SlotConstraint: "Required"
PromptSpecification:
MessageGroupsList:
- Message:
PlainTextMessage:
Value: "What city will you be staying in?"
MaxRetries: 2
AllowInterrupt: false
- Name: "CheckInDate"
Description: "Date of check-in"
SlotTypeName: "AMAZON.Date"
ValueElicitationSetting:
SlotConstraint: "Required"
PromptSpecification:
MessageGroupsList:
- Message:
PlainTextMessage:
Value: "What day do you want to check in?"
MaxRetries: 2
AllowInterrupt: false
- Name: "Nights"
Description: "something"
SlotTypeName: "AMAZON.Number"
ValueElicitationSetting:
SlotConstraint: "Required"
PromptSpecification:
MessageGroupsList:
- Message:
PlainTextMessage:
Value: "How many nights will you be staying?"
MaxRetries: 2
AllowInterrupt: false
- Name: "RoomType"
Description: "Enumeration of types of rooms that are offered by a hotel."
SlotTypeName: "RoomTypeValues"
ValueElicitationSetting:
SlotConstraint: "Required"
PromptSpecification:
MessageGroupsList:
- Message:
PlainTextMessage:
Value: "What type of room would you like, queen, king or deluxe?"
MaxRetries: 2
AllowInterrupt: false
- Name: "FallbackIntent"
Description: "Default intent when no other intent matches"
ParentIntentSignature: "AMAZON.FallbackIntent"
您还可以 下载 CloudFormation 模板 对于迄今为止所做的工作。您先请 更新你的堆栈 使用此模板,将部署一个功能机器人。在 Amazon Lex 控制台上,您可以确认存在机器人的草稿版本以及名为的默认别名 TestBotAlias
已经被创造了。
创建新的机器人版本和别名
Amazon Lex 支持发布 版本 机器人、意图和槽类型,以便您可以控制客户端应用程序的实现。版本是机器人定义的编号快照,您可以发布它以用于工作流程的不同部分,例如开发、测试版部署和生产。 Amazon Lex 机器人还支持 别名。别名是指向机器人特定版本的指针。使用别名,您可以更新客户端应用程序的版本。在实际场景中,机器人别名用于蓝/绿部署和管理特定于环境的配置(例如开发和生产环境)。
为了说明这一点,假设您将别名指向机器人的版本 1。当需要更新机器人时,您可以发布版本 2 并更改别名以指向新版本。由于您的应用程序使用别名而不是特定版本,因此所有客户端都无需更新即可接收新功能。
请记住,当您修改 CloudFormation 模板并启动部署时,更改将在草稿版本中实施,主要用于测试。完成测试阶段后,您可以建立新版本来完成迄今为止已合并的更改。
接下来,您根据草稿创建新的机器人版本,设置新的别名,并将该版本链接到此别名。以下是要添加到模板中的两个新资源:
BookHotelInitialVersion:
DependsOn: BookHotelBot
Type: AWS::Lex::BotVersion
Properties:
BotId: !Ref BookHotelBot
BotVersionLocaleSpecification:
- LocaleId: en_US
BotVersionLocaleDetails:
SourceBotVersion: DRAFT
Description: Hotel Bot initial version
BookHotelDemoAlias:
Type: AWS::Lex::BotAlias
Properties:
BotId: !Ref BookHotelBot
BotAliasName: "BookHotelDemoAlias"
BotVersion: !GetAtt BookHotelInitialVersion.BotVersion
您还可以 下载新版本的模板 并通过更新堆栈来部署它。您可以在 Amazon Lex 控制台上看到已创建新版本并与名为的新别名关联 BookHotelDemoAlias
.
当您创建 Amazon Lex 自动程序的新版本时,它通常会从 1 开始按顺序递增版本号。要识别特定版本,您可以参考其描述。
添加 Lambda 函数
要初始化值或验证机器人的用户输入,您可以将 Lambda 函数作为代码挂钩添加到您的机器人。同样,您也可以使用 Lambda 函数来实现,例如将数据写入数据库或调用 API 保存收集到的信息。欲了解更多信息,请参阅 使用 AWS Lambda 函数启用自定义逻辑.
让我们将 Lambda 函数的新资源添加到 CloudFormation 模板中。尽管通常不建议在 CloudFormation 模板中嵌入代码,但我们在这里这样做只是为了使演示部署不那么复杂。请看下面的代码:
HotelBotFunction:
DependsOn: BotRuntimeRole # So that the Lambda function is ready before the bot deployment
Type: AWS::Serverless::Function
Properties:
FunctionName: book_hotel_lambda
Runtime: python3.11
Timeout: 15
Handler: index.lambda_handler
InlineCode: |
import os
import json
def close(intent_request):
intent_request['sessionState']['intent']['state'] = 'Fulfilled'
message = {"contentType": "PlainText",
"content": "Your Booking is confirmed"}
session_attributes = {}
sessionState = intent_request['sessionState']
if 'sessionAttributes' in sessionState:
session_attributes = sessionState['sessionAttributes']
requestAttributes = None
if 'requestAttributes' in intent_request:
requestAttributes = intent_request['requestAttributes']
return {
'sessionState': {
'sessionAttributes': session_attributes,
'dialogAction': {
'type': 'Close'
},
'intent': intent_request['sessionState']['intent'],
'originatingRequestId': 'xxxxxxx-xxxx-xxxx-xxxx'
},
'messages': [message],
'sessionId': intent_request['sessionId'],
'requestAttributes': requestAttributes
}
def router(event):
intent_name = event['sessionState']['intent']['name']
slots = event['sessionState']['intent']['slots']
if (intent_name == 'BookHotel'):
# invoke lambda and return result
return close(event)
raise Exception(
'The intent is not supported by Lambda: ' + intent_name)
def lambda_handler(event, context):
response = router(event)
return response
要使用此 Lambda 函数来实现,请在您的意图中启用代码挂钩设置:
Intents:
- Name: "BookHotel"
Description: "Intent to book a hotel room"
FulfillmentCodeHook:
Enabled: true
SampleUtterances:
- Utterance: "Book a hotel"
- Utterance: "I want a make hotel reservations"
- Utterance: "Book a {Nights} night stay in {Location}"
由于您对机器人进行了更改,因此您可以通过添加名为的新资源来创建新版本的机器人 BookHotelVersionWithLambda
在模板中:
BookHotelVersionWithLambda:
DependsOn: BookHotelInitialVersion
Type: AWS::Lex::BotVersion
Properties:
BotId: !Ref BookHotelBot
BotVersionLocaleSpecification:
- LocaleId: en_US
BotVersionLocaleDetails:
SourceBotVersion: DRAFT
Description: Hotel Bot with a lambda function
Lambda 函数与机器人别名关联。 Amazon Lex V2 可以为每种语言的每个机器人别名使用一个 Lambda 函数。因此,您必须更新模板中的别名才能添加 Lambda 函数资源。您可以在 BotAliasLocalSettings
部分。您还需要将别名指向您创建的新版本。以下代码是修改后的别名配置:
BookHotelDemoAlias:
Type: AWS::Lex::BotAlias
Properties:
BotId: !Ref BookHotelBot
BotAliasName: "BookHotelDemoAlias"
BotVersion: !GetAtt BookHotelVersionWithLambda.BotVersion
# Remove BotAliasLocaleSettings if you aren't concerned with Lambda setup.
# If you are you can modify the LambdaArn below to get started.
BotAliasLocaleSettings:
- LocaleId: en_US
BotAliasLocaleSetting:
Enabled: true
CodeHookSpecification:
LambdaCodeHook:
CodeHookInterfaceVersion: "1.0"
LambdaArn: !GetAtt HotelBotFunction.Arn
到目前为止,您仅将 Lambda 函数与别名链接起来。但是,您需要授予权限以允许别名调用 Lambda 函数。在以下代码中,您添加 Amazon Lex 的 Lambda 调用权限并将别名 ARN 指定为源 ARN:
LexInvokeLambdaPermission:
Type: AWS::Lambda::Permission
Properties:
Action: "lambda:InvokeFunction"
FunctionName: !GetAtt HotelBotFunction.Arn
Principal: "lexv2.amazonaws.com"
SourceArn: !GetAtt BookHotelDemoAlias.Arn
您还可以 下载最新版本 模板的。使用此版本更新堆栈后,您将拥有一个与 Lambda 函数集成的 Amazon Lex 自动程序。
条件分支
现在让我们探索 Amazon Lex 机器人的条件分支功能,并考虑不允许在下周在西雅图预订超过 5 晚的情况。根据业务要求,如果用户尝试在西雅图预订超过 5 晚的住宿,则对话应以适当的消息结束。其条件分支在 CloudFormation 模板中的以下位置表示: SlotCaptureSetting
:
- Name: "Nights"
Description: “Number of nights.”
SlotTypeName: "AMAZON.Number"
ValueElicitationSetting:
SlotConstraint: "Required"
SlotCaptureSetting:
CaptureConditional:
DefaultBranch:
NextStep:
DialogAction:
Type: "ElicitSlot"
SlotToElicit: "RoomType"
ConditionalBranches:
- Name: "Branch1"
Condition:
ExpressionString: '{Nights}>5 AND {Location} = "Seattle"'
Response:
AllowInterrupt: true
MessageGroupsList:
- Message:
PlainTextMessage:
Value: “Sorry, we cannot book more than five nights in {Location} right now."
NextStep:
DialogAction:
Type: "EndConversation"
IsActive: true
PromptSpecification:
MessageGroupsList:
- Message:
PlainTextMessage:
Value: "How many nights will you be staying?"
MaxRetries: 2
AllowInterrupt: false
由于您更改了机器人定义,因此需要在模板中创建新版本并将其与别名链接。这是临时修改,因为该公司计划很快允许在西雅图进行大量预订。以下是您添加到模板的两个新资源:
BookHotelConditionalBranches:
DependsOn: BookHotelVersionWithLambda
Type: AWS::Lex::BotVersion
Properties:
BotId: !Ref BookHotelBot
BotVersionLocaleSpecification:
- LocaleId: en_US
BotVersionLocaleDetails:
SourceBotVersion: DRAFT
Description: Hotel Bot Version with conditional branches
BookHotelDemoAlias:
Type: AWS::Lex::BotAlias
Properties:
BotId: !Ref BookHotelBot
BotAliasName: "BookHotelDemoAlias"
BotVersion: !GetAtt BookHotelConditionalBranches.BotVersion
# Remove BotAliasLocaleSettings if you aren't concerned with Lambda setup.
# If you are you can modify the LambdaArn below to get started.
BotAliasLocaleSettings:
- LocaleId: en_US
BotAliasLocaleSetting:
Enabled: true
CodeHookSpecification:
LambdaCodeHook:
CodeHookInterfaceVersion: "1.0"
LambdaArn: !GetAtt HotelBotFunction.Arn
您还可以 下载更新后的模板。使用此模板版本更新堆栈后,别名将定向到包含条件分支功能的版本。要撤消此修改,您可以更新别名以恢复到以前的版本。
日志
您还可以为 Amazon Lex 自动程序启用日志。为此,您必须更新机器人的角色以授予写入权限 亚马逊CloudWatch 日志。以下是将 CloudWatch 策略添加到角色的示例:
BotRuntimeRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lexv2.amazonaws.com
Action:
- "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: LexRuntimeRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "polly:SynthesizeSpeech"
- "comprehend:DetectSentiment"
Resource: "*"
- PolicyName: CloudWatchPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: "*"
为了确保行为一致且可预测,在 CloudFormation 模板中定义资源名称和属性时应尽可能具体。这是因为在 CloudFormation 模板中使用通配符 (*) 可能会带来潜在的安全风险并导致意外后果。因此,建议避免使用通配符,而尽可能使用显式值。
接下来,您创建一个 CloudWatch 日志组资源(如以下代码所示),以将日志定向到该组:
#Log Group
LexLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /lex/hotel-bot
RetentionInDays: 5
最后,更新您的别名以启用对话日志设置:
BookHotelDemoAlias:
Type: AWS::Lex::BotAlias
Properties:
BotId: !Ref BookHotelBot
BotAliasName: "BookHotelDemoAlias"
BotVersion: !GetAtt BookHotelConditionalBranches.BotVersion
BotAliasLocaleSettings:
- LocaleId: en_US
BotAliasLocaleSetting:
Enabled: true
CodeHookSpecification:
LambdaCodeHook:
CodeHookInterfaceVersion: "1.0"
LambdaArn: !GetAtt HotelBotFunction.Arn
ConversationLogSettings:
TextLogSettings:
- Destination:
CloudWatch:
CloudWatchLogGroupArn: !GetAtt LexLogGroup.Arn
LogPrefix: bookHotel
Enabled: true
当您使用此模板更新堆栈时,您将为机器人启用对话日志。此步骤中不会创建新版本,因为您的机器人资源没有更改。你可以 下载最新版本的模板.
清理
为了防止将来产生费用,请删除您创建的 CloudFormation 堆栈。
结论
在本文中,我们讨论了为 Amazon Lex V2 自动程序创建 CloudFormation 模板的分步过程。最初,我们部署了一个基本的机器人,然后我们探索了别名和版本的潜力以及如何通过模板有效地使用它们。接下来,我们学习了如何将 Lambda 函数与 Amazon Lex V2 机器人集成,并在机器人的对话流中实现条件分支以满足业务需求。最后,我们通过创建 CloudWatch 日志组资源并使用必要的权限更新机器人角色来添加日志记录功能。
该模板允许直接部署和管理机器人,并能够根据需要恢复更改。总体而言,CloudFormation 模板对于管理和优化 Amazon Lex V2 机器人非常有用。
下一步,您可以探索 Amazon Lex 机器人示例 并应用本文中讨论的技术将它们转换为 CloudFormation 模板。这种实践练习将巩固您对通过基础设施即代码管理 Amazon Lex V2 机器人的理解。
作者简介
托马斯·林德福斯 是 Amazon Lex 团队的高级解决方案架构师。 他为语言 AI 服务发明、开发、原型设计和宣传新的技术特性和解决方案,以改善客户体验并简化采用。
里吉什·阿卡贝斯·查托斯 是 AWS 的专业服务顾问。他帮助客户实现他们想要的业务
通过利用 Amazon Connect、Amazon Lex 和 GenAI 功能,在联络中心领域取得成果。