aws python库
by Ralu Bolovan
由Ralu Bolovan
适用于Alexa的新AWS Python SDK入门指南 (A Beginner’s guide to the new AWS Python SDK for Alexa)
Amazon Web Services (AWS) recently added a new Python SDK to their Alexa family. It is currently in beta, but that should not stop us from getting some exposure.
亚马逊网络服务(AWS)最近在其Alexa系列中添加了新的Python SDK 。 它目前处于测试阶段,但这不应阻止我们获得一些曝光。
What we’ll build: a very simple voice app that can say 10 facts about cats.
我们将构建的:一个非常简单的语音应用程序,可以说出关于猫的 10个事实 。
Why we’ll build it: The app’s concept is simple enough for us to focus on how to work with the SDK, and how to use DynamoDB to persist the most important data for our app.
我们为什么要构建它:应用程序的概念非常简单,我们可以专注于如何使用SDK,以及如何使用DynamoDB保留应用程序中最重要的数据。
By the end of the tutorial you’ll walk away with:
在本教程结束时,您将完成:
- What each of the main Alexa request types does and how to build your own. 每个主要的Alexa请求类型做什么以及如何构建自己的请求。
- An understanding of how you can persist your app’s data in DynamoDB and avoid pitfalls. 了解如何将应用程序的数据持久保存在DynamoDB中并避免陷阱。
- See the two Python styles for Alexa in action and choose your preferred one. 查看实际使用的Alexa的两种Python样式,然后选择您喜欢的一种。
- Python tips. Python技巧。
- Alexa console tips. Alexa控制台提示。
Prerequisites:
先决条件:
1. AWS account
1. AWS账户
2. AWS developer account (if you want to test on your registered device, for example, an Echo, sign up with the same email as your Amazon account)
2. AWS开发人员帐户 (如果您想在注册的设备(例如,Echo)上进行测试,请使用与您的亚马逊帐户相同的电子邮件进行注册)
3. Python 3.6
3. Python 3.6
If you’re still with me, let’s start!
如果您仍然与我在一起,那就开始吧!
Alexa:幕后发生的事情(大图) (Alexa: what happens behind the scenes (big picture))
To illustrate the main idea behind an interaction with Alexa, let’s look at the launch of a fictitious skill called “My example”.
为了说明与Alexa进行交互的主要思想,让我们看一下一种称为“我的榜样”的虚拟技能的发布。
When the user says: “Open My example,” the “My example” bit is the skill’s Invocation name, which Alexa uses to communicate. The user’s device passes what the user said to the “My example” skill.
当用户说:“打开我的示例”时,“我的示例”位是技能的调用名称 ,Alexa用来进行交流。 用户的设备将用户所说的内容传递给“我的榜样”技能。
At this point, Alexa uses the skill’s Interaction model to understand what the user requested. The interaction model is a JSON file that maps what the user says to a request type. In this case, it will map it to the built-in AMAZON.LaunchRequest
.
此时,Alexa使用技能的交互模型来了解用户的要求。 交互模型是一个JSON文件,可将用户所说的内容映射到请求类型。 在这种情况下,它将映射到内置的AMAZON.LaunchRequest
。
Next, it calls its backend, an AWS Lambda function, which receives the identified request.
接下来,它调用其后端,即AWS Lambda函数 ,该函数接收已标识的请求。
The Lambda searches for a function that can handle the LaunchRequest and executes it.
Lambda搜索可以处理LaunchRequest的函数并执行它。
This function then returns a response that gets sent back all the way up to the user’s device. At this point, the “My example” skill will greet them and will be able to accept further user requests.
然后,此函数返回一个响应,该响应将一直发送回用户设备。 此时,“我的榜样”技能将向他们致意,并能够接受更多的用户请求。
Let’s get down to business!
让我们转到工作上!
架构概述 (Architecture overview)
Now that we’ve nailed down the main idea behind an Alexa Skill invocation, let’s explore how we will create our sample “Cat Facts” skill.
现在,我们已经确定了Alexa技能调用背后的主要思想,让我们探索如何创建示例“猫事实”技能。
The architecture is similar to the one we discussed: Alexa Skill that invokes a Lambda function to process the identified request and returns a response to be spoken back to the user.
该体系结构类似于我们讨论的体系结构:Alexa Skill,该函数调用Lambda函数来处理所标识的请求并返回要说给用户的响应。
We have two additions: DynamoDB and IAM.
我们有两个附加功能: DynamoDB和IAM。
DynamoDB (DynamoDB)
Our skill is going to keep track of the index of the last fact that our user heard from our list of ten cat facts. It uses DynamoDB to persist the index and the number of times the user has opened our skill.
我们的技能是跟踪用户从我们的十个猫事实列表中听到的最后一个事实的索引。 它使用DynamoDB来保留索引和用户打开我们的技能的次数。
我是 (IAM)
We will need it in two places:
我们将在两个地方使用它:
- First, a role for our Lambda to be able to interact with DynamoDB to persist our user data. We also need to grant it CloudWatchLogs permissions to write important details about the requests we receive. 首先,我们的Lambda能够与DynamoDB进行交互以保留我们的用户数据。 我们还需要向其授予CloudWatchLogs权限,以编写有关收到的请求的重要详细信息。
- Second, we will need a Lambda Permission to allow our Alexa skill to invoke our Lambda as its backend. 其次,我们将需要Lambda许可,以允许我们的Alexa技能调用Lambda作为其后端。
实作 (Implementation)
Alexa技能 (Alexa Skill)
Go to your Alexa developer console and click on “Create Skill”. Name the skill “Cat Facts” and choose your preferred English locale.
转到您的Alexa开发人员控制台,然后单击“创建技能”。 将技能命名为“猫事实”,然后选择您喜欢的英语语言环境。
Add the invocation name: “cat facts”.
添加调用名称:“ cat facts”。
Add the following interaction model to the console’s JSON editor:
将以下交互模型添加到控制台的JSON编辑器:
{ "interactionModel": { "languageModel": { "invocationName": "cat facts", "intents": [ { "name": "AMAZON.CancelIntent", "samples": [] }, { "name": "AMAZON.HelpIntent", "samples": [] }, { "name": "AMAZON.StopIntent", "samples": [] }, { "name": "AMAZON.StartOverIntent", "samples": [ "start", "start a new game", "restart", "restart game" ] }, { "name": "AMAZON.YesIntent", "samples": [] }, { "name": "AMAZON.NoIntent", "samples": [] }, { "name": "AMAZON.FallbackIntent", "samples": [] }, { "name": "FactNumberIntent", "slots": [ { "name": "fact_number", "type": "AMAZON.NUMBER" } ], "samples": [ "{fact_number}", "I want {fact_number}", "I want fact {fact_number}", "I want fact number {fact_number}", "Tell me {fact_number}", "Tell me fact {fact_number}", "Tell me fact number {fact_number}" ] } ], "types": [] } }}
Click the “Save Model” button.
点击“保存模型”按钮。
小费: (Tip:)
For the AWS resources, use an Alexa supported region:
对于AWS资源,请使用Alexa支持的区域 :
- Asia Pacific (Tokyo) 亚太地区(东京)
- EU (Ireland) 欧盟(爱尔兰)
- US East (N. Virginia) 美国东部(弗吉尼亚北部)
- US West (Oregon) 美国西部(俄勒冈州)
DynamoDB表 (DynamoDB table)
In the console go to DynamoDB and create a new table called “cat_facts”. Name the partition key: “id”.
在控制台中,转到DynamoDB并创建一个名为“ cat_facts”的新表。 将分区键命名为“ id”。
我是 (IAM)
We will now create the IAM policy that we will attach to our Lambda’s role.
现在,我们将创建IAM策略,并将其附加到Lambda的角色上。
Go to “Services” -> “IAM” -> “Policies” and click on “Create policy”.
转到“服务”->“ IAM”->“策略”,然后单击“创建策略”。
Then paste the following policy in the JSON editor and click on “Review policy”.
然后将以下策略粘贴到JSON编辑器中,然后单击“查看策略”。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": [ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:ListTables", "dynamodb:DeleteItem", "dynamodb:Scan", "dynamodb:ListTagsOfResource", "dynamodb:Query", "dynamodb:UpdateItem", "dynamodb:DescribeTimeToLive", "dynamodb:CreateTable", "dynamodb:DescribeTable", "dynamodb:GetItem", "dynamodb:DescribeLimits", "dynamodb:UpdateTable", "logs:CreateLogGroup", "logs:PutLogEvents", "logs:CreateLogStream" ], "Resource": "*" } ]}
Name the policy “Cat_Facts_Policy” and finish by selecting “Create policy”.
将策略命名为“ Cat_Facts_Policy”,然后选择“创建策略”以完成操作。
We then want to attach this policy to a Lambda Role. Go back to “IAM” -> “Roles” and choose “Create role”.
然后,我们希望将此策略附加到Lambda角色。 返回“ IAM”->“角色”,然后选择“创建角色”。
Then we choose “Lambda” service and click on “Next: Permissions”.
然后,我们选择“ Lambda”服务,然后单击“下一步:权限”。
We attach the “Cat_Facts_Policy” and click on “Next: Review”.
我们附上“ Cat_Facts_Policy”,然后单击“下一步:审阅”。
We finish by giving our role the name “Cat_Facts_Lambda_Role” and by clicking on “Create role”.
首先,给我们的角色命名为“ Cat_Facts_Lambda_Role”,然后单击“创建角色”。
Lambda代码 (Lambda Code)
In your terminal, create a new folder:
在您的终端中,创建一个新文件夹:
mkdir alexa_cat_facts_skill
mkdir alexa_cat_facts_skill
Within this folder create a new directory for the Lambda:
在此文件夹中,为Lambda创建一个新目录:
cd alexa_cat_facts_skill/mkdir lambda
Within the lambda folder, create a new virtual environment. The virtual env allows us to keep our skill’s libraries separate from those in any other Python project.
在lambda文件夹中,创建一个新的虚拟环境。 虚拟环境使我们能够将我们的技能库与任何其他Python项目中的库分开。
cd lambdapython3 -m venv catfactsenvsource catfactsenv/bin/activatepip install ask-sdkdeactivate
Windows Tip: To activate the virtual environment run the following: catfactsenv\Scripts\activate.bat
Windows提示 :要激活虚拟环境,请运行以下命令: catfactsenv\Scripts\activate.bat
类和装饰器Python样式 (Class and decorator Python styles)
The Python SDK offers us two ways to write our Alexa interactions: either by using classes or by using decorators.
Python SDK为我们提供了两种编写Alexa交互的方式:通过使用类或使用装饰器。
We’ll now do a comparison between the two styles while looking at the requests that we want to support as part of our app. We’ll achieve the exact same functionality.
现在,在查看要作为应用程序一部分支持的请求时,我们将对两种样式进行比较。 我们将实现完全相同的功能。
Create two new Python files, one for each style:
创建两个新的Python文件,每种样式一个:
touch catfacts_classes_lambda.pytouch catfacts_decorators_lambda.py
进口货 (Imports)
In both cases, we import the “os” module to retrieve any environment variables that we pass to our Lambda — in this case, the name of the DynamoDB table to persist our user data.
在这两种情况下,我们都导入“ os”模块以检索传递给Lambda的所有环境变量-在这种情况下,即DynamoDB表的名称,用于持久存储用户数据。
SkillBuilders are classes that make it easy for us to attach components that can handle our user’s requests and generate appropriate responses.
SkillBuilders是使我们能够轻松附加可以处理用户请求并生成适当响应的组件的类。
We import the “StandardSkillBuilder”, which offers DynamoDB support out of the box. It also integrates with the Default API client, getting basic details about the user’s device.
我们导入了“ StandardSkillBuilder ”,它提供了开箱即用的DynamoDB支持。 它还与Default API客户端集成,以获取有关用户设备的基本详细信息。
We create a new instance to which we pass the name of the DynamoDB table. We want to use the user id that Alexa gives us as our table’s partition key. We do this by specifying a built-in helper function called user_id_partition_keygen
, which extracts the user’s id from the incoming requests.
我们创建一个新实例,并将DynamoDB表的名称传递给该实例。 我们要使用Alexa给我们的用户ID作为表的分区键。 我们通过指定一个名为user_id_partition_keygen
的内置帮助器函数来完成此user_id_partition_keygen
,该函数从传入的请求中提取用户的ID。
We include the is_request_type, is_intent_name
functions to help us later determine the requests the skills has sent over.
我们包括is_request_type, is_intent_name
函数,以帮助我们稍后确定技能已发送的请求。
We import ask_sdk_dynamodb
to extract information from our Dynamo data.
我们导入ask_sdk_dynamodb
以从Dynamo数据中提取信息。
班级 (Classes)
In the case of classes, we introduce four abstract classes that we will implement for our skill to work:
在类的情况下,我们将介绍四个抽象类,以实现我们的工作技能:
AbstractRequestHandler
— this class is able to process requests from the user and return an appropriate responseAbstractRequestHandler
—此类能够处理来自用户的请求并返回适当的响应AbstractExceptionHandler
— for handling exceptionsAbstractExceptionHandler
—用于处理异常AbstractRequestInterceptor
— executes before a requestAbstractRequestInterceptor
—在请求之前执行AbstractResponseInterceptor
— executes after a requestAbstractResponseInterceptor
—在请求后执行
装饰工 (Decorators)
小费 (Tip)
We could have created our DynamoDB table within the Lambda by setting auto_create_table=True
. The problem is that this is an asynchronous function, so the first user of the app would have experienced errors while the table was initializing.
我们可以通过设置auto_create_table=True
在Lambda中创建DynamoDB表。 问题在于这是一个异步函数,因此应用程序的第一个用户在初始化表时会遇到错误。
数据 (Data)
We store the ten cat facts in a list for both versions of the code.
我们将两个代码版本的十个猫事实存储在列表中。
We’ll look at each abstract class that we need to implement once, and then focus on the code, as the syntax remains the same.
我们将查看需要实现一次的每个抽象类,然后将重点放在代码上,因为语法保持不变。
HandlerInput (HandlerInput)
Whenever we need to process a request, an exception, or intercept a request before or after we’ve processed it, what makes this possible is a HandlerInput (in the code, handler_input
) object. It contains all we need to understand the state of our skill.
每当我们需要在处理请求之前或之后处理请求,异常或拦截请求时,使HandlerInput (在代码中为handler_input
)对象成为可能。 它包含我们需要了解的所有技能状态。
The HandlerInput offers the following attributes for us to use:
HandlerInput提供以下属性供我们使用:
request_envelope
: the whole request bodyrequest_envelope
: 整个请求主体atributes_manager:
an easy way to access request, session, and persistent attributesatributes_manager:
访问请求,会话和持久属性的简便方法service_client_factory
: builds API clients that can perform functions for us like retrieving the user’s name and address, or make purchasesservice_client_factory
: 构建可以为我们执行功能的API客户端,例如检索用户的名称和地址或进行购买response_builder
: way to build the response we want to pass to our userresponse_builder
: 建立我们想要传递给用户的响应的方法context
: an optional object that is passed by the service that is running the skill code. For a Lambda backend, this is the context object that gives us information like the remaining time until AWS terminates our Lambda.context
: 运行技能代码的服务传递的可选对象。 对于Lambda后端,这是一个上下文对象,它为我们提供诸如AWS终止Lambda之前的剩余时间的信息。
LaunchRequest (LaunchRequest)
班级 (Classes)
For all request types that map to an intent, we need to implement the AbstractRequestHandler
class methods can_handle
and handle
.
对于所有映射到意图的请求类型,我们需要实现AbstractRequestHandler
类方法can_handle
和handle
。
We first determine if the class can process the incoming request. For that, we use the is_request_type
function. This takes in a request type — in our case, LaunchRequest— and returns a predicate function. We then pass the handler_input
to this predicate, which checks if the incoming request is launching the app or not.
我们首先确定该类是否可以处理传入的请求。 为此,我们使用 is_request_type
函数。 这包含一个请求类型-在我们的例子中是LaunchRequest- 并返回一个谓词函数。 然后,我们将handler_input
传递给此谓词,该谓词将检查传入的请求是否正在启动应用程序。
If this is a LaunchRequest, we can handle it. Because the launch is the gateway to our app, we want to see if this user has used our app before so we can customise their experience. We do this by using the attributes_manager
attribute of handler_input
to retrieve the persistent_attributes
from our DynamoDB cat_facts table.
如果这是LaunchRequest ,我们可以处理它。 由于启动是通向我们应用程序的门户,因此我们想查看该用户是否曾经使用过我们的应用程序,以便我们可以自定义他们的体验。 我们通过使用handler_input
的attributes_manager
属性来检索persistent_attributes
从我们的DynamoDB cat_facts表中。
Behind the scenes, it calls the partition_keygen
function that we used to create the StandardSkillBuilder
instance.
在后台,它调用了我们用来创建StandardSkillBuilder
的partition_keygen
函数 实例。
In our case, we’re interested in making the user’s identifier the partition key. Once it has retrieved the user Id using this function from the request’s envelope, it then queries the DynamoDB table’s “id” column to see if there is an entry for this user in our table. If there is, it returns a dictionary containing all the attributes names and values, otherwise an empty dictionary.
在我们的案例中,我们希望将用户的标识符用作分区键。 一旦从请求的信封中使用此函数检索了用户ID,它就会查询DynamoDB表的“ id”列,以查看表中是否有该用户的条目。 如果存在,则返回包含所有属性名称和值的字典,否则返回空字典。
If there’s no match, we record that this user has not played our game before. Also, we’re adding the index of the current fact from our cat_facts list, which is -1 because the user has not listened to any facts.
如果没有匹配项,我们记录该用户以前没有玩过我们的游戏。 另外,我们从cat_facts列表中添加当前事实的索引,该索引为-1,因为用户没有收听任何事实。
We point the contents of the persistent_attributes
to session_attributes
. We will be using the session attributes throughout the application, whenever we’re modifying a field. This will help us not only maintain the state of our app, but also avoid making unnecessary calls to our DynamoDB table.
我们指出了persistent_attributes
的内容 到session_attributes
。 每当我们修改字段时,我们将在整个应用程序中使用会话属性。 这不仅可以帮助我们维护应用程序的状态,还可以避免对DynamoDB表进行不必要的调用。
To demonstrate the functionality, we’re assuming that the user can play as long as they’ve not listened to all ten facts.
为了演示该功能,我们假设用户可以一直玩,只要他们没有听完所有十个事实。
If they have listened to all the facts, we ask them if they want to start again. If they want to restart, we start playing the facts in ascending order from the first one to the last.
如果他们听了所有事实,我们会问他们是否要重新开始。 如果他们想重新启动,我们将从第一个到最后一个升序开始播放事实。
We then use the response_builder
to create our response. We use its speak
function to make the user’s Device say the response. If they haven’t responded in eight seconds, the “ask” command will automatically reprompt them for an answer.
然后,我们使用response_builder
建立我们的回应。 我们用它的speak
功能,使用户的设备说出响应。 如果他们在八秒钟内没有响应,“询问”命令将自动提示他们回答。
装饰工 (Decorators)
The handler code is the same as for the classes version. The syntax differs in that we’re using the StandardSkillBuilder
object’s request_handler
function to decorate our function. We must pass it a parameter can_handle_func
, which has to map to a function. We use the same is_request_type
method, which gives us back the necessary function for this decorator to work.
处理程序代码与类版本相同。 语法不同,因为我们使用StandardSkillBuilder
对象的request_handler
函数来修饰函数。 我们必须给它传递一个参数can_handle_func
,该参数必须映射到一个函数。 我们使用相同的is_request_type
方法,这为我们提供了装饰器正常工作所需的功能。
Python提示: (Python tips:)
We used attr.set_default(“facts_index”, -1)
which checks if there is a facts_index
key in our “attr” dictionary and sets it to -1 if there isn’t. Otherwise the value is not modified.
我们使用attr.set_default(“facts_index”, -1)
来检查“ attr”字典中是否存在一个facts_index
键,如果没有,则将其设置为-1。 否则,该值不会被修改。
For Python 3.6 we can use “f” strings or formatted strings, which are expressions evaluated at runtime. They are faster and more readable than other ways of formatting.
对于Python 3.6,我们可以使用“ f”字符串或格式化的字符串,它们是在运行时评估的表达式。 它们比其他格式更快,更易读。
FactNumberIntent (FactNumberIntent)
This is a custom request type that we define. We want to allow our user to ask for a fact number from 1 to 10, in addition to going through the list of facts in order.
这是我们定义的自定义请求类型。 除了按顺序浏览事实列表之外,我们还希望允许用户要求一个1到10之间的事实编号。
班级 (Classes)
The interesting bit here is that this request will pass us the number of the fact the user wants via a slot. A slot is an argument given to an intent.
有趣的是,此请求将通过插槽将用户想要的事实传递给我们。 广告位是赋予意图的参数。
In our interaction model we defined in our Alexa console, we tell Alexa that we can support a user saying a number and that it should be mapped to one via the built-in Amazon.NUMBER
:
在我们在Alexa控制台中定义的交互模型中,我们告诉Alexa我们可以支持用户说出一个数字,并且应该通过内置的Amazon.NUMBER
将其映射到一个Amazon.NUMBER
。
{ "name": "FactNumberIntent", "slots": [ { "name": "fact_number", "type": "AMAZON.NUMBER" } ], "samples": [ "{fact_number}", "I want {fact_number}", "I want fact {fact_number}", "I want fact number {fact_number}", "Tell me {fact_number}", "Tell me fact {fact_number}", "Tell me fact number {fact_number}" ] }
From the Lambda side, we know that we will receive a number. We get all the slots from the intent, and then transform this value into an integer.
从Lambda方面,我们知道我们将收到一个号码。 我们从意图中获取所有插槽,然后将该值转换为整数。
We make sure that the number can be mapped to an index, and we return the fact. Otherwise, we ask the user for a different number that we support.
我们确保该数字可以映射到索引,然后返回事实。 否则,我们会要求用户提供我们支持的其他号码。
We use the is_intent_name
function to determine that we’re processing the FactNumberIntent
.
我们使用is_intent_name
函数来确定我们正在处理FactNumberIntent
。
装饰工 (Decorators)
StartOverIntent (StartOverIntent)
This is a built-in AMAZON intent used for restarting games, audio tracks, or transactions. In our case, restarting means resetting the facts_index
.
这是内置的AMAZON意图,用于重新启动游戏,音轨或事务。 在我们的情况下,重新启动意味着重置facts_index
。
班级 (Classes)
装饰工 (Decorators)
帮助目的: (HelpIntent:)
A built-in AMAZON intent to guide the user.
内置的AMAZON意图指导用户。
班级 (Classes)
装饰工 (Decorators)
停止或取消意图 (StopOrCancelIntent)
Here we’ve combined the handling of the built-in intents AMAZON.StopIntent
and AMAZON.CancelIntent
to explicitly end the user’s session by setting set_should_end_session
to “True” in the response_builder
.
这里我们结合内置的意图处理AMAZON.StopIntent
和AMAZON.CancelIntent
通过设置明确的结束用户的会话set_should_end_session
在为“True” response_builder
。
班级 (Classes)
We persist the gathered session_attributes
in DynamoDB by calling our helper function persist_user_attributes
. We also increase the number of times this user has interacted with our app.
我们通过调用帮助程序函数persist_user_attributes
将收集到的session_attributes
保留在persist_user_attributes
。 我们还增加了该用户与我们的应用互动的次数。
The save_persistent_attributes
function will save the attributes into DynamoDB. This uses the skill builder instance’s partition_keygen
function to get the userId to use as the partition key. This is done behind the scenes.
save_persistent_attributes
函数会将属性保存到DynamoDB中。 这使用技能构建器实例的partition_keygen
函数获取要用作分区键的userId。 这是在后台完成的。
装饰器 : (Decorator:)
For the can_handle_func
we’re making our own inline function, using Python’s lambda operator, where we’re passing in the handler_input
to be checked against the StopIntent
and the CancelIntent
. In this case, we must explicitly invoke the is_intent_name
function with both these inputs, which will return a boolean. Because we’re using lambda, the result will be a predicate function, which is what the can_handle_func
needs.
对于can_handle_func
我们使用Python的lambda运算符创建自己的内联函数,在该函数中,我们传入的handler_input
将根据StopIntent
和CancelIntent
进行检查。 在这种情况下,我们必须使用这两个输入显式调用is_intent_name
函数,这将返回一个布尔值。 因为我们使用的是lambda,所以结果将是谓词函数 ,这是can_handle_func
需要的。
SessionEndedRequest (SessionEndedRequest)
We use the is_request_type
function to determine if the session has been terminated. This happens when the user says “Exit” — we don’t receive a response that can be mapped to any intent, or an error occurs. This is not invoked when explicitly ending the session using set_should_end_session
, so we must ensure that we persist the attributes in both cases.
我们使用is_request_type
函数来确定会话是否已终止。 当用户说“退出”时,就会发生这种情况-我们没有收到可以映射到任何意图的响应,或者发生了错误。 使用set_should_end_session
显式结束会话时不会调用此方法,因此我们必须确保在两种情况下都保留属性。
班级 (Classes)
装饰工 (Decorators)
是的 (YesIntent)
This is a built-in intent for affirmative responses for a yes/no question. We’re keeping things very basic. We check if a new fact can be retrieved and, if not, we ask the user to restart the game. Otherwise, we tell them the fact and ask them if they want to hear another one.
这是对“是/否”问题做出肯定回答的内在意图。 我们将事情保持在最基本的状态。 我们检查是否可以检索到新的事实,如果不能,请用户重新启动游戏。 否则,我们告诉他们事实,并询问他们是否想听听另一个。
班级 (Classes)
装饰工 (Decorators)
没有意图 (NoIntent)
It’s a built-in intent for negative responses for a yes/no question. We choose to end the session and persist the session attributes in DynamoDB.
这是对是/否问题的否定回答的内置意图。 我们选择结束会话并将会话属性保留在DynamoDB中。
班级 (Classes)
装饰工 (Decorators)
后备意图 (FallbackIntent)
Another built-in AMAZON intent that is supported at the time of writing in English locales.
在使用英语语言环境编写时,还支持另一个内置的AMAZON意图。
It provides a fallback mechanism when the user says something that does not match any of our skill’s intents.
当用户说出与我们的技术意图不符的内容时,它提供了一个后备机制。
班级 (Classes)
装饰工 (Decorators)
AllException (AllException)
To keep things simple, we want to use this handler to handle every possible exception.
为了简单起见,我们希望使用此处理程序来处理所有可能的异常。
班级 (Classes)
We need to implement the can_handle
method to which we pass the handler_input
and the exception
. We want this function to handle any exceptions, but for more specialized cases we could look at exception classes and have specific ways to handle them.
我们需要实现can_handle
方法,并将handler_input
和exception
传递给该方法。 我们希望该函数处理任何异常,但是对于更特殊的情况,我们可以查看异常类并具有处理它们的特定方法。
In the handle
function we pass the handler_input
and the exception
and we return a simple message.
在handle
函数中,我们传递handler_input
和 exception
,我们返回一条简单消息。
装饰器 (Decorator)
For the decorator version, we need to pass to can_handle_func
a function that takes as input the handler_input
and the exception
and returns a boolean. The function that gets decorated receives both of these parameters.
对于装饰器版本,我们需要向can_handle_func
传递一个函数,该函数将handler_input
和exception
作为输入,并返回一个布尔值。 被修饰的函数将接收这两个参数。
GlobalRequestInterceptor (GlobalRequestInterceptor)
We use the global request interceptor to execute code before every request’s handler gets invoked. In our case, we want to record the request we received. We also want to log the user’s id and their device id.
我们使用全局请求拦截器在调用每个请求的处理程序之前执行代码。 在我们的情况下,我们要记录收到的请求。 我们还想记录用户的ID和他们的设备ID。
班级 (Classes)
装饰工 (Decorators)
For decorators, the global request interceptor is invoked directly as a function. It needs the skill builder instance to register the interceptor on our behalf.
对于装饰器,全局请求拦截器直接作为函数调用。 它需要技能构建者实例来代表我们注册拦截器。
辅助功能 (Helper functions)
The get_device_id
and get_user_id
are two helper functions to showcase how to extract the deviceId and the userId from the request using the ask_dynamo_db
package.
get_device_id
和get_user_id
是两个帮助函数,用于展示如何使用ask_dynamo_db
从请求中提取deviceId和userId 。 包。
We can use ask_sdk_dynamodb.partition_keygen.device_id_partition_keygen
and the ask_sdk_dynamodb.partition_keygen.user_id_partition_keygen
as the partition key getters for our table. When we created our skill builder instance, we used the second function.
我们可以使用ask_sdk_dynamodb.partition_keygen.device_id_partition_keygen
和ask_sdk_dynamodb.partition_keygen.user_id_partition_keygen
作为表的分区键获取器。 创建技能构建器实例时,我们使用了第二个功能。
GlobalResponseInterceptor (GlobalResponseInterceptor)
Similar to the global request interceptor, the global response interceptor is used to execute code after any request’s handler gets invoked. Here we will just log the response we pass back to the user.
与全局请求拦截器相似,全局响应拦截器用于在调用任何请求的处理程序之后执行代码。 在这里,我们只记录返回给用户的响应。
班级 (Classes)
装饰工 (Decorators)
注册并致电我们的处理程序: (Registering and calling our handlers:)
The request and response interceptors are executed in the same order as they are registered.
请求和响应拦截器的执行顺序与注册时的顺序相同 。
班级 (Classes)
We must explicitly register each request handler, each exception handler, and the global request and global response interceptors.
我们必须显式注册每个请求处理程序,每个异常处理程序以及全局请求和全局响应拦截器。
We then create a lambda_handler
that can be used by our Lambda as the gateway to invoking all the supported handlers.
然后,我们创建一个lambda_handler
我们的Lambda可以将其用作调用所有支持的处理程序的网关。
装饰工 (Decorators)
We don’t need to register the handlers explicitly as that’s done directly by the decorators. But we must pay attention to the order we’ve written the handlers as that is the order in which they’ll be executed.
我们不需要显式注册处理程序,因为这是由装饰器直接完成的。 但是我们必须注意我们编写处理程序的顺序,因为这是它们执行的顺序。
We’re officially done with the syntax part and understanding what goes into our code.
我们正式完成了语法部分,并了解了代码中的内容。
打包我们的Python代码 (Packaging our Python code)
Because we’re using non-standard Python libraries like the AWS Python SDK, we need to package them up alongside our Lambda code.
因为我们使用的是非标准Python库(例如AWS Python SDK),所以我们需要将它们与Lambda代码一起打包。
The way we achieve this is by creating a bash script that will do the work for us. In the “alexa_cat_facts_skill” directory create a new bash file: “create_lambda_package.sh”
我们实现此目标的方法是创建一个bash脚本来为我们完成工作。 在“ alexa_cat_facts_skill”目录中,创建一个新的bash文件:“ create_lambda_package.sh”
cd ..touch create_lambda_package.sh
Add the following to the new bash file. This will zip the Python libraries as well as the two versions of our code into a package called “lambda_package.zip”.
将以下内容添加到新的bash文件中。 这会将Python库以及我们的代码的两个版本压缩到一个名为“ lambda_package.zip”的软件包中。
#!/bin/bash
BASEDIR=$(pwd)rm -rf $BASEDIR/lambda_package.zipcd $BASEDIR/lambda/catfactsenv/lib/python3.6/site-packages/zip -r9 $BASEDIR/lambda_package.zip *cd $BASEDIR/lambda/catfactsenv/lib64/python3.6/site-packages/zip -r9 $BASEDIR/lambda_package.zip *cd $BASEDIR/lambda
zip -r9 $BASEDIR/lambda_package.zip catfacts_classes_lambda.py catfacts_decorators_lambda.py
Run the bash script: bash -x create_lambda_package.sh
运行bash脚本: bash -x create_lambda_package.sh
Windows提示 (Windows Tip)
The Python libraries will be found instead under catfactsenv\Lib\site-packages
.
可以在catfactsenv\Lib\site-packages
下找到Python库。
设置Lambda (Setting up the Lambda)
Start by going to the “AWS console” -> “Services” -> “Lambda”
首先转到“ AWS控制台”->“服务”->“ Lambda”
We will author from scratch. Name the Lambda: “cat_facts_lambda”. Select the runtime to be “Python 3.6” and for the role choose the “Cat_Facts_Lambda_Role” we created above. Click on “Create function”.
我们将从头开始创作。 将Lambda命名为:“ cat_facts_lambda”。 选择运行时为“ Python 3.6”,并为角色选择我们在上面创建的“ Cat_Facts_Lambda_Role”。 点击“创建功能”。
Add the environment variable “skill_persistence_table” with the value cat_facts
.
添加环境变量 值为cat_facts
“ skill_persistence_table” 。
Increase the “Timeout”.
增加“超时”。
Import the code by uploading the “lambda_package.zip” file. Add the Lambda’s handler to be: “catfacts_decorators_lambda.handler”.
通过上传“ lambda_package.zip”文件导入代码。 将Lambda的处理程序添加为:“ catfacts_decorators_lambda.handler”。
Save the function.
保存功能。
添加Alexa触发器 (Add the Alexa trigger)
From the function’s “Designer” menu, choose “Alexa Skills Kit”. Then click on the button with the same name to fix the configuration.
从功能的“设计器”菜单中,选择“ Alexa技能套件”。 然后单击具有相同名称的按钮以修复配置。
Go to the Alexa developer console, to “Endpoint” and you will see the skill’s id. Copy it to your clipboard.
转到Alexa开发人员控制台 ,单击“端点”,您将看到技能的ID 。 将其复制到剪贴板。
Paste the Skill ID into the Lambda console and then click “Add”.
将技能ID粘贴到Lambda控制台中,然后单击“添加”。
Save the function.
保存功能。
Then copy the Lambda’s ARN from the top right corner of the page.
然后从页面右上角复制Lambda的ARN 。
Alexa控制台设置完成 (Alexa console setup finish)
Select “AWS Lambda ARN” from “Endpoint”, and paste the Lambda’s ARN into the “Default Region” Field.
从“端点”中选择“ AWS Lambda ARN”,然后将Lambda的ARN粘贴到“默认区域”字段中。
Then go to “Build” -> “JSON Editor” -> “Save Model”. Once the model is saved, click on “Build Model” so all our changes take effect.
然后转到“构建”->“ JSON编辑器”->“保存模型”。 保存模型后,单击“构建模型”,以便所有更改生效。
We’re officially done with our setup! Congratulations on making it this far!
我们的设置已正式完成! 恭喜!
测试中 (Testing)
Let’s interact with our skill directly from the Alexa console. Go to “Test” and enable testing for the skill to run the Alexa simulator.
让我们直接从Alexa控制台与我们的技能进行互动。 转到“测试”并启用测试 运行Alexa模拟器的技巧。
Alexa控制台提示 (Alexa console tip)
When testing the FactNumberIntent, write the numbers as characters, for example “two” instead of “2”. Otherwise, the intent will be mapped to the FallbackIntent.
测试FactNumberIntent时,将数字写为字符,例如“两个”而不是“ 2”。 否则,该意图将被映射到FallbackIntent。
让我们测试装饰器版本 (Let’s test the Decorators version)
Let’s run a simple scenario to see how our skill performs. We’re especially interested in testing the fact number intent and its boundaries. Feel free to either speak the commands by clicking and holding the mic icon or by writing them.
让我们运行一个简单的场景,看看我们的技能如何表现。 我们对测试事实数字意图及其边界特别感兴趣。 通过单击并按住麦克风图标或编写它们,可以随意说出命令。
See the results in DynamoDB by going into your AWS console to “Services”-> “DynamoDB” -> “Tables” -> “cat_facts”. You will see a similar item, with your user id as the partition key.
通过进入AWS控制台转到“服务”->“ DynamoDB”->“表”->“ cat_facts”,在DynamoDB中查看结果。 您将看到一个类似的项目,其中您的用户ID为分区键。
让我们测试Classes版本 (Let’s test the Classes version)
To switch to the classes version of our code, go to “Services” -> “Lambda” -> “cat_facts_lambda”. The simple change is to rename the Handler from “catfacts_decorators_lambda.handler” to “catfacts_classes_lambda.handler”. “Save” the function and the switch happens automatically.
要切换到我们的代码的类版本,请转到“服务”->“ Lambda”->“ cat_facts_lambda”。 简单的更改是将处理程序从“ cat facts_deco rators_lambda.handler”重命名为“ cat facts_c lasses_lambda.handler”。 “保存”功能,切换自动进行。
Let’s do another run with our Alexa skill, where we want to test the start over behaviour. Even though we changed the code, the behaviour is the same.
让我们用我们的Alexa技能再进行一次测试,在这里我们要测试行为的开始。 即使我们更改了代码,其行为也相同。
Let’s go back to our DynamoDB table and refresh our page. Our Lambda has successfully recorded the last heard fact’s index and that the user has interacted with the skill twice.
让我们回到DynamoDB表并刷新页面。 我们的Lambda已成功记录了最近一次听到的事实的索引,并且用户已两次与该技能进行了交互。
Congratulations! You’ve successfully created your first Alexa Skill using the Python SDK. You now know how to persist relevant attributes in DynamoDB, how to create your skill’s infrastructure, what the major intents do, how to create your own, and how to make Lambda answer to any intents.
恭喜你 ! 您已经使用Python SDK成功创建了第一个Alexa技能。 您现在知道了如何在DynamoDB中保留相关属性,如何创建技能的基础结构,主要意图做什么,如何创建自己的意图以及如何使Lambda回答任何意图。
有待改进 (Room for improvement)
We specifically did not focus on infrastructure such as code, git, multiple languages, CI/CD, testing, and APIs for our cat facts. That would have made the tutorial much more complex and would have taken away from the main focus. In a real-life environment, these make our lives a lot easier.
我们特别不关注基础架构,例如代码,git,多种语言,CI / CD,测试和适用于我们事实的API。 那样会使本教程变得更加复杂,并且会偏离主要重点。 在现实环境中,这些使我们的生活更加轻松。
Even though adding such improvements would increase our productivity, knowing how to start and how to go about it can be overwhelming. Combining new technology trends like AI, Serverless and DevOps, requires fulfilling many roles at the same time, which can seem insurmountable.
即使添加此类改进将提高我们的生产率,但是知道如何开始和如何进行它可能会让人难以理解。 结合AI , Serverless和DevOps等新技术趋势,需要同时履行许多职责,这似乎是无法克服的。
获得更多帮助 (Get more help)
But what if there was a way to overcome this obstacle and be empowered to build your own applications using these concepts? I have created a course that demystifies this process. You can find it here, with a free trial by going here.
但是,如果有一种方法可以克服这一障碍,并能够使用这些概念来构建自己的应用程序,该怎么办? 我创建了一门使这个过程神秘化的课程。 您可以在这里找到它,并可以通过这里免费试用。
Thank you for taking the time to read this article. May it be a stepping stone in your journey to creating something great!
感谢您抽出宝贵的时间阅读本文。 愿它成为您创造伟大事物的踏脚石!
aws python库