使用 AWS Lambda 自定义建议 - Amazon Pinpoint

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 AWS Lambda 自定义建议

在 Amazon Pinpoint 中,您可以从推荐器模型中检索个性化建议,并将其添加到您从活动和旅程发送的消息中。推荐器模型 是一种机器学习 (ML) 模型,它在数据中查找模式,并根据找到的模式生成预测和建议。它从一组给定的产品或项目中预测特定用户喜欢的内容,并以建议集的形式为用户提供该信息。

通过将推荐器模型与 Amazon Pinpoint 一起使用,您可以根据每个消息接收人的属性和行为向接收人发送个性化建议。通过使用 AWS Lambda,您还可以自定义和改进这些建议。例如,您可以将建议从单个文本值(如产品名称或 ID)动态转换为更复杂的内容(如产品名称、描述和图像)。您可以在 Amazon Pinpoint 发送消息时实时执行该操作。

此功能在以下 AWS 区域提供:美国东部(弗吉尼亚州北部)、美国西部(俄勒冈州)、亚太地区(孟买)、亚太地区(悉尼)和欧洲地区(爱尔兰)。

在消息中使用建议

要将推荐器模型与 Amazon Pinpoint 一起使用,请先创建一个 Amazon Personalize 解决方案并将该解决方案部署为 Amazon Personalize 活动。然后,在 Amazon Pinpoint 中为推荐器模型创建一个配置。在该配置中,您可以指定一些设置以确定如何从 Amazon Personalize 活动中检索和处理建议数据。这包括是否调用 AWS Lambda 函数以对检索的数据执行其他处理。

Amazon Personalize 是一项旨在帮助您创建机器学习模型的 AWS 服务,以便为使用您的应用程序的客户提供实时、个性化的建议。Amazon Personalize 将指导您完成创建和训练机器学习模型的过程,然后准备和部署该模型作为 Amazon Personalize 活动。接下来,您可以从活动中检索实时的个性化建议。要了解有关 Amazon Personalize 的更多信息,请参阅 Amazon Personalize 开发人员指南

AWS Lambda 是一项计算服务,您可用来运行代码而无需预配置或管理服务器。您可将代码打包并上载到 AWS Lambda 作为 Lambda 函数。然后在调用该函数时,AWS Lambda 会运行该函数。函数可被手动调用、自动调用以响应事件或者响应来自应用程序或服务(包括 Amazon Pinpoint)的请求。有关创建和调用 Lambda 函数的更多信息,请参阅 AWS Lambda 开发人员指南

在为推荐器模型创建 Amazon Pinpoint 配置后,您可以将模型中的建议添加到从活动和旅程发送的消息中。您可以使用包含建议属性的消息变量的消息模板以做到这一点。建议的属性 是一个旨在存储建议数据的动态端点或用户属性。在为推荐器模型创建配置时,您可以定义这些属性。

您可以在以下类型的消息模板中使用建议属性的变量:

  • 电子邮件模板,用于您从活动或旅程中发送的电子邮件。

  • 推送通知模板,用于您从活动中发送的推送通知。

  • 短信模板,用于您从活动中发送的短信文本消息。

有关将推荐器模型与 Amazon Pinpoint 一起使用的更多信息,请参阅《Amazon Pinpoint 用户指南》中的机器学习模型

如果配置 Amazon Pinpoint 以调用处理建议数据的 Lambda 函数,每次在活动或旅程的消息中发送个性化建议时,Amazon Pinpoint 都会执行以下常规任务:

  1. 评估及处理消息和消息模板的配置设置和内容。

  2. 确定消息模板已连接到推荐器模型。

  3. 评估用于连接到和使用模型的配置设置。这些设置是由模型的推荐器模型资源定义的。

  4. 检测模型配置设置定义的建议属性的一个或多个消息变量。

  5. 从模型配置设置中指定的 Amazon Personalize 活动检索建议数据。它使用 Amazon Personalize Runtime API 的 GetRecommendations 操作来执行此任务。

  6. 将相应的建议数据添加到每个消息接收人的动态建议属性 (RecommendationItems) 中。

  7. 调用 Lambda 函数,并将每个接收人的建议数据发送到该函数以进行处理。

    数据将作为 JSON 对象发送,其中包含每个接收人的端点定义。每个端点定义包含一个 RecommendationItems 字段,其中包含由 1–5 个值组成的有序数组。数组中的值数量取决于模型的配置设置。

  8. 等待 Lambda 函数处理数据并返回结果。

    结果是一个 JSON 对象,其中包含每个接收人的更新的端点定义。每个更新的端点定义包含一个新 Recommendations 对象。该对象包含 1–10 个字段,在模型配置设置中定义的每个自定义建议属性各一个字段。其中的每个字段存储端点的改进建议数据。

  9. 使用每个接收人的更新的端点定义,将每个消息变量替换为该接收人对应的值。

  10. 发送包含每个消息接收人的个性化建议的消息版本。

要以这种方式自定义和改进建议,请先创建一个 Lambda 函数以处理 Amazon Pinpoint 发送的端点定义,然后返回更新的端点定义。接下来,分配一个 Lambda 函数策略并授权 Amazon Pinpoint 调用该函数。然后,在 Amazon Pinpoint 中配置推荐器模型。在配置模型时,指定要调用的函数并定义要使用的建议属性。

创建 Lambda 函数

要了解如何创建 Lambda 函数,请参阅《AWS Lambda 开发人员指南》中的入门。在设计和开发函数时,请牢记以下要求和准则。

输入事件数据

在 Amazon Pinpoint 为推荐器模型调用 Lambda 函数时,它发送一个负载,其中包含发送消息的活动或旅程的配置和其他设置。负载包含一个 Endpoints 对象,该对象是将端点 ID 与消息接收人的端点定义关联的映射。

端点定义使用由 Amazon Pinpoint API 的端点资源定义的结构。不过,它们还包含一个名为 RecommendationItems 的动态建议属性字段。RecommendationItems 字段包含从 Amazon Personalize 活动返回的一个或多个端点建议项目。该字段的值是由 1–5 个建议的项目(作为字符串)组成的有序数组。数组中的项目数取决于您配置 Amazon Pinpoint 以便为每个端点或用户检索的建议项目数。

例如:

"Endpoints": { "endpointIDexample-1":{ "ChannelType":"EMAIL", "Address":"sofiam@example.com", "EndpointStatus":"ACTIVE", "OptOut":"NONE", "EffectiveDate":"2020-02-26T18:56:24.875Z", "Attributes":{ "AddressType":[ "primary" ] }, "User":{ "UserId":"SofiaMartínez", "UserAttributes":{ "LastName":[ "Martínez" ], "FirstName":[ "Sofia" ], "Neighborhood":[ "East Bay" ] } }, "RecommendationItems":[ "1815", "2009", "1527" ], "CreationDate":"2020-02-26T18:56:24.875Z" }, "endpointIDexample-2":{ "ChannelType":"EMAIL", "Address":"alejandror@example.com", "EndpointStatus":"ACTIVE", "OptOut":"NONE", "EffectiveDate":"2020-02-26T18:56:24.897Z", "Attributes":{ "AddressType":[ "primary" ] }, "User":{ "UserId":"AlejandroRosalez", "UserAttributes":{ "LastName ":[ "Rosalez" ], "FirstName":[ "Alejandro" ], "Neighborhood":[ "West Bay" ] } }, "RecommendationItems":[ "1210", "6542", "4582" ], "CreationDate":"2020-02-26T18:56:24.897Z" } }

在前面的示例中,相关的 Amazon Pinpoint 设置为:

  • 配置推荐器模型,以便为每个端点或用户检索三个建议的项目。(RecommendationsPerMessage 属性的值设置为 3。) 在使用该设置时,Amazon Pinpoint 为每个端点或用户检索并仅添加第一、第二和第三个建议的项目。

  • 配置项目以使用自定义用户属性,这些属性存储每个用户的名字、姓氏以及他们居住的社区。(UserAttributes 对象包含这些属性的值。)

  • 配置项目以使用自定义端点属性 (AddressType),该属性指示端点是否为用户从项目中接收消息的首选地址(渠道)。(Attributes 对象包含该属性的值。)

在 Amazon Pinpoint 调用 Lambda 函数并将该负载作为事件数据发送时,AWS Lambda 将该数据传递给 Lambda 函数以进行处理。

每个负载最多可以包含 50 个端点的数据。如果分段包含超过 50 个端点,则 Amazon Pinpoint 反复调用该函数(每次最多处理 50 个端点),直到该函数处理了所有数据。

响应数据和要求

在设计和开发 Lambda 函数时,请牢记机器学习模型的限额。如果函数不满足这些限额定义的条件,则 Amazon Pinpoint 无法处理和发送消息。

还要牢记以下要求:

  • 函数必须使用输入事件数据提供的相同格式返回更新的端点定义。

  • 每个更新的端点定义可以包含端点或用户的 1–10 个自定义建议属性。这些属性的名称必须与在 Amazon Pinpoint 中配置推荐器模型时指定的属性名称匹配。

  • 必须在单个 Recommendations 对象中为每个端点或用户返回所有自定义建议属性。该要求有助于确保不会发生命名冲突。您可以将 Recommendations 对象添加到端点定义中的任何位置。

  • 每个自定义建议属性的值必须是一个字符串(单个值)或字符串数组(多个值)。如果值是字符串数组,我们建议您保持 Amazon Personalize 返回的建议项目的顺序,如 RecommendationItems 字段中所示。否则,您的内容可能无法反映模型为端点或用户提供的预测。

  • 函数不应修改事件数据中的其他元素,包括端点或用户的其他属性值。它应该只添加和返回自定义推荐属性的值。Amazon Pinpoint 不接受对函数响应中任何其他值的更新。

  • 函数必须托管在与调用函数的 Amazon Pinpoint 项目相同的 AWS 区域中。如果函数和项目不在同一个区域中,则 Amazon Pinpoint 无法将事件数据发送到函数。

如果不满足任何上述要求,则 Amazon Pinpoint 无法处理消息并将其发送到一个或多个端点。这可能会导致活动或旅程活动失败。

最后,我们建议您为函数保留 256 个并发执行。

总体而言,Lambda 函数应处理 Amazon Pinpoint 发送的事件数据,并返回修改的端点定义。它可以遍历 Endpoints 对象中的每个端点,并为每个端点创建和设置要使用的自定义建议属性值以做到这一点。以下示例处理程序(使用 Python 编写并继续前面的输入事件数据示例)说明了这一点:

import json import string def lambda_handler(event, context): print("Received event: " + json.dumps(event)) print("Received context: " + str(context)) segment_endpoints = event["Endpoints"] new_segment = dict() for endpoint_id in segment_endpoints.keys(): endpoint = segment_endpoints[endpoint_id] if supported_endpoint(endpoint): new_segment[endpoint_id] = add_recommendation(endpoint) print("Returning endpoints: " + json.dumps(new_segment)) return new_segment def supported_endpoint(endpoint): return True def add_recommendation(endpoint): endpoint["Recommendations"] = dict() customTitleList = list() customGenreList = list() for i,item in enumerate(endpoint["RecommendationItems"]): item = int(item) if item == 1210: customTitleList.insert(i, "Hanna") customGenreList.insert(i, "Action") elif item == 1527: customTitleList.insert(i, "Catastrophe") customGenreList.insert(i, "Comedy") elif item == 1815: customTitleList.insert(i, "Fleabag") customGenreList.insert(i, "Comedy") elif item == 2009: customTitleList.insert(i, "Late Night") customGenreList.insert(i, "Drama") elif item == 4582: customTitleList.insert(i, "Agatha Christie\'s The ABC Murders") customGenreList.insert(i, "Crime") elif item == 6542: customTitleList.insert(i, "Hunters") customGenreList.insert(i, "Drama") endpoint["Recommendations"]["Title"] = customTitleList endpoint["Recommendations"]["Genre"] = customGenreList return endpoint

在前面的示例中,AWS Lambda 将事件数据作为 event 参数传递给处理程序。处理程序遍历 Endpoints 对象中的每个端点,并设置名为 Recommendations.TitleRecommendations.Genre 的自定义建议属性的值。return 语句将每个更新的端点定义返回到 Amazon Pinpoint。

继续前面的输入事件数据示例,更新的端点定义为:

"Endpoints":{ "endpointIDexample-1":{ "ChannelType":"EMAIL", "Address":"sofiam@example.com", "EndpointStatus":"ACTIVE", "OptOut":"NONE", "EffectiveDate":"2020-02-26T18:56:24.875Z", "Attributes":{ "AddressType":[ "primary" ] }, "User":{ "UserId":"SofiaMartínez", "UserAttributes":{ "LastName":[ "Martínez" ], "FirstName":[ "Sofia" ], "Neighborhood":[ "East Bay" ] } }, "RecommendationItems":[ "1815", "2009", "1527" ], "CreationDate":"2020-02-26T18:56:24.875Z", "Recommendations":{ "Title":[ "Fleabag", "Late Night", "Catastrophe" ], "Genre":[ "Comedy", "Comedy", "Comedy" ] } }, "endpointIDexample-2":{ "ChannelType":"EMAIL", "Address":"alejandror@example.com", "EndpointStatus":"ACTIVE", "OptOut":"NONE", "EffectiveDate":"2020-02-26T18:56:24.897Z", "Attributes":{ "AddressType":[ "primary" ] }, "User":{ "UserId":"AlejandroRosalez", "UserAttributes":{ "LastName ":[ "Rosalez" ], "FirstName":[ "Alejandro" ], "Neighborhood":[ "West Bay" ] } }, "RecommendationItems":[ "1210", "6542", "4582" ], "CreationDate":"2020-02-26T18:56:24.897Z", "Recommendations":{ "Title":[ "Hanna", "Hunters", "Agatha Christie\'s The ABC Murders" ], "Genre":[ "Action", "Drama", "Crime" ] } } }

在前面的示例中,函数修改了它收到的 Endpoints 对象并返回了结果。现在,每个端点的 Endpoint 对象包含一个新 Recommendations 对象,其中包含 TitleGenre 字段。其中的每个字段存储由三个值(作为字符串)组成的有序数组,其中的每个值为 RecommendationItems 字段中的相应建议项目提供改进的内容。

分配 Lambda 函数策略

您必须先授权 Amazon Pinpoint 调用 Lambda 函数,然后才能使用该函数处理建议数据。要授予调用权限,请为该函数分配 Lambda 函数策略。Lambda 函数策略 是一个基于资源的权限策略,它指定哪些实体可以使用函数以及这些实体可以执行哪些操作。有关更多信息,请参阅《AWS Lambda 开发人员指南》中的将基于资源的策略用于 AWS Lambda

以下示例策略允许 Amazon Pinpoint 服务主体将 lambda:InvokeFunction 操作用于特定 Amazon Pinpoint 项目 (projectId) 中的特定 Amazon Pinpoint 活动 (campaignId):

{ "Sid": "sid", "Effect": "Allow", "Principal": { "Service": "pinpoint.us-east-1.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "{arn:aws:lambda:us-east-1:accountId:function:function-name}", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:mobiletargeting:us-east-1:accountId:recommenders/*" } } }

该函数策略需要使用一个包含 AWS:SourceArn 键的 Condition 块。该键指定允许哪个资源调用函数。在前面的示例中,该策略允许一个特定活动调用函数。

您还可以编写一个策略,以允许 Amazon Pinpoint 服务主体将 lambda:InvokeFunction 操作用于特定 Amazon Pinpoint 项目 (projectId) 中的所有活动和旅程。以下示例策略说明了这一点:

{ "Sid": "sid", "Effect": "Allow", "Principal": { "Service": "pinpoint.us-east-1.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "{arn:aws:lambda:us-east-1:accountId:function:function-name}", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:mobiletargeting:us-east-1:accountId:recommenders/*" } } }

与第一个示例不同,该示例的 Condition 块中的 AWS:SourceArn 键允许一个特定项目调用函数。该权限适用于项目中的所有活动和旅程。

要编写更通用的策略,您可以使用多字符匹配通配符 (*)。例如,您可以使用以下 Condition 块以允许任何 Amazon Pinpoint 项目调用函数:

"Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:mobiletargeting:us-east-1:accountId:recommenders/*" } }

如果要将 Lambda 函数与您的 Amazon Pinpoint 账户的所有项目一起使用,我们建议您按前面的方式配置策略的 Condition 块。不过,作为最佳实践,您创建的策略只应包含对特定资源执行特定操作所需的权限。

授权 Amazon Pinpoint 调用该函数

在将 Lambda 函数策略分配给函数后,您可以添加权限以允许 Amazon Pinpoint 为特定项目、活动或旅程调用该函数。您可以使用 AWS Command Line Interface (AWS CLI) 和 Lambda add-permission 命令以执行该操作。以下示例说明了如何为特定项目 (projectId) 执行该操作:

$ aws lambda add-permission \ --function-name function-name \ --statement-id sid \ --action lambda:InvokeFunction \ --principal pinpoint.us-east-1.amazonaws.com \ --source-arn arn:aws:mobiletargeting:us-east-1:accountId:recommenders/*

前面的示例针对 Unix、Linux 和 macOS 进行了格式设置。对于 Microsoft Windows,请将反斜杠 (\) 行继续符替换为插入符号 (^)。

如果命令成功运行,则您将看到类似于以下内容的输出:

{ "Statement": "{\"Sid\":\"sid\", \"Effect\":\"Allow\", \"Principal\":{\"Service\":\"pinpoint.us-east-1.amazonaws.com\"}, \"Action\":\"lambda:InvokeFunction\", \"Resource\":\"arn:aws:lambda:us-east-1:111122223333:function:function-name\", \"Condition\": {\"ArnLike\": {\"AWS:SourceArn\": \"arn:aws:mobiletargeting:us-east-1:111122223333:recommenders/*\"}}}" }

Statement 值是已添加到 Lambda 函数策略的语句的 JSON 字符串版本。

配置推荐器模型

要配置 Amazon Pinpoint 以便为推荐器模型调用 Lambda 函数,请为模型指定以下 Lambda 特定的配置设置:

  • RecommendationTransformerUri – 该属性指定 Lambda 函数的名称或 Amazon 资源名称 (ARN)。

  • Attributes – 该对象是一个映射,它定义了函数添加到每个端点定义的自定义建议属性。可以将其中的每个属性作为消息模板中的消息变量。

当您为模型创建配置或更新模型的配置时,可以使用 Amazon Pinpoint API 的推荐器模型资源https://docs.aws.amazon.com/pinpoint/latest/apireference/recommenders-recommender-id.html来指定这些设置。您也可以使用 Amazon Pinpoint 控制台定义这些设置。

有关将推荐器模型与 Amazon Pinpoint 一起使用的更多信息,请参阅《Amazon Pinpoint 用户指南》中的机器学习模型