7

过去,我设置了两个用 Java 编写的独立 AWS lambda。一种用于 Alexa,一种用于 Api.ai。他们只是将“Hello world”返回给每个助手 api。因此,尽管它们很简单,但它们可以工作。随着我开始为每个代码编写越来越多的代码,我开始看到我的 java 代码有多么相似,我只是通过拥有两个单独的 lambda 来重复自己。

快进到今天。

我现在正在做的是拥有一个可以处理来自 Alexa 和 Api.ai 的输入的单个 AWS lambda,遇到了一些麻烦。目前,我的想法是,当 lambda 运行时,会有一个简单的 if 语句,如下所示:

以下不是真正的代码,只是我认为我可以做的

if (figureOutIfInputType.equals("alexa")){
runAlexaCode();
} else if (figureOutIfInputType.equals("api.ai")){
runApiAiCode();
}

现在问题是我需要以某种方式判断该函数是由 alexa 还是 api.ai 调用的。

这是我现在的实际java:

public class App implements RequestHandler<Object, String> {

  @Override
  public String handleRequest(Object input, Context context) {
    System.out.println("myLog: " + input.toString());

      return "Hello from AWS";
  }

然后我从 Alexa 和 Api.ai 运行 lambda,看看在 java 中会生成什么对象输入。

API.ai

{id=asdf-6801-4a9b-a7cd-asdffdsa, timestamp=2017-07-
28T02:21:15.337Z, lang=en, result={source=agent, resolvedQuery=hi how 
are you, action=, actionIncomplete=false, parameters={}, contexts=[], 
metadata={intentId=asdf-3a2a-49b6-8a45-97e97243b1d7, 
webhookUsed=true, webhookForSlotFillingUsed=false, 
webhookResponseTime=182, intentName=myIntent}, fulfillment=
{messages=[{type=0, speech=I have failed}]}, score=1}, status=
{code=200, errorType=success}, sessionId=asdf-a7ac-43c8-8ae8-
bc1bf5ecaad0}

亚历克斯

{version=1.0, session={new=true, sessionId=amzn1.echo-api.session.asdf-
7e03-4c35-9d98-d416eefc5b23, application=    
{applicationId=amzn1.ask.skill.asdf-a02e-4938-a747-109ea09539aa}, user=        
{userId=amzn1.ask.account.asdf}}, context={AudioPlayer=
{playerActivity=IDLE}, System={application=
{applicationId=amzn1.ask.skill.07c854eb-a02e-4938-a747-109ea09539aa}, 
user={userId=amzn1.ask.account.asdf}, device=
{deviceId=amzn1.ask.device.asdf, supportedInterfaces={AudioPlayer={}}}, 
apiEndpoint=https://api.amazonalexa.com}}, request={type=IntentRequest, 
requestId=amzn1.echo-api.request.asdf-5de5-4930-8f04-9acf2130e6b8, 
timestamp=2017-07-28T05:07:30Z, locale=en-US, intent=
{name=HelloWorldIntent, confirmationStatus=NONE}}}

所以现在我有我的 Alexa 和 Api.ai 输出,它们是不同的。所以这很好。我将能够分辨出哪个是哪个。但我被困住了。我不确定是否应该尝试创建一个 AlexaInput 对象和一个 ApiAIinput 对象。

我做这一切都错了吗?试图让一个 lambda 满足来自多个服务(Alexa 和 ApiAI)的“助手”请求,我错了吗?

任何帮助,将不胜感激。当然,其他人必须在 AWS 中编写他们的助手功能,并希望将他们的代码重用于两个“助手”平台。

4

3 回答 3

3

我有同样的问题和同样的想法,但随着我越来越深入地实施,我意识到它不太实用,原因有一个:

虽然我的很多逻辑都需要相同 - 结果的格式不同。有时,甚至结果的细节或格式也会有所不同。

我所做的就是回到 W​​eb 编程中熟悉的一些概念,将其分为两部分:

  1. 一个后端系统,负责获取参数并应用业务逻辑来产生结果。这些结果将是相当低级的,不是整个短语,而是更多的一组键/值对,指示要给出什么样的结果以及该结果需要什么值。

  2. 一个前端系统,负责处理特定于 Alexa/Assistant 的事情。所以它会接受请求,提取参数和状态,用这个信息调用后端系统,得到一个结果,其中包括要发送什么样的回复和需要的值,然后格式化确切的短语(以及任何其他支持信息,例如卡片或其他)并将其放入格式正确的响应中。

对于每种代理类型,前端组件将是不同的 lambda 函数,主要是为了使逻辑更清晰。后端组件可以是库函数或另一个 lambda 函数,只要对任务最有意义,但独立于前端实现。

我想也可以通过拥有一个实现后端逻辑的抽象父类,并让前端逻辑成为它的子类来实现这一点。我不会这样做,因为它没有在两者之间提供清晰的界面边界,但并非不合理。

于 2017-07-29T05:31:49.093 回答
1

您可以通过不同的方式实现结果(代码重用)。

aws-lambda-java-events首先,使用该库为每种类型的事件(Alexa、API 网关等)创建一个方法。这里的一些信息:http: //docs.aws.amazon.com/lambda/latest/dg/java-programming-model-handler-types.html

每个入口点方法都应处理触发它的事件的语义(API 网关),并调用通用代码以提供代码重用。

其次,将您的 JAR/ZIP 上传到 S3 存储桶。

第三,对于您要处理的每个事件 - 创建一个 Lambda 函数,在 S3 存储桶中引用相同的 ZIP/JAR 并指定相关的入口点。

这样,您将获得代码重用,而不必在 AWS 上处理多个代码副本,尽管代价是定义了多个 Lambda。

有一个很棒的工具可以支持这种工作方式,称为无服务器框架,我强烈建议您查看: https ://serverless.com/framework/docs/providers/aws/

于 2017-08-01T15:56:16.687 回答
0

我一直在使用单个 Lambda 来处理 Alexa ASK 和 Microsoft Luis.ai 响应。我使用的是 Python 而不是 Java,但想法是一样的,我相信使用 AlexaInput 和 ApiAIinput 对象,都应该扩展相同的接口。

我首先使用上下文信息来识别请求的来源并将其解析为适当的对象(我使用一个简单的嵌套字典)。然后将其传递给我的主要处理函数,最后,根据上下文再次将输出传递给格式化程序。格式化程序将知道您需要返回什么。唯一需要注意的是处理会话信息;在我的情况下,无论如何我都会序列化到我自己的 DynamoDB 表。

于 2017-07-31T17:38:47.680 回答