亚马逊AWS官方博客

通过置信评分与更高准确率,在 Amazon Lex 上构建高质量对话服务

Original URL: https://aws.amazon.com/cn/blogs/machine-learning/build-more-effective-conversations-on-amazon-lex-with-confidence-scores-and-increased-accuracy/

 

在忙碌的日常生活中,我们往往会在对话中使用模棱两可或者并不完整的句子。例如,在与银行助理交谈时,客户可能会说,“余额还剩多少?”这样的请求显然比较模糊,客户并没有明确提到自己希望查询的到底是信用卡余额还是支票账户余额。这位客户也许只有银行支票账户,这时客服人员完全可以查找账户详细信息以确定对方提到的只可能是支票账户,借此带来良好的服务体验。在客户服务领域,客服人员经常需要结合当前用户的上下文数据以解释用户表述中的这些不确定性因素。聊天机器人程序也面临类似的歧视,同样需要添加客户上下文数据以确定对方的真实意图。

今天,我们在Amazon Lex上推出了自然语言理解的改进方案与置信评分机制。我们根据客户的反馈与研究进展不断改善服务能力,旨在实现更强大的大家还可以借此更好地处理种种模棱两可的场景,包括我们之前提到的查询场景。在这种情况下,如果有两项或者两项以上的intent能够以极高置信度进行匹配,则大家可以使用intent分类置信度评分确定能否以及如何使用业务逻辑来理解用户意图。如果用户只开通了信用卡服务,那么我们可以触发intent以显示信用卡余额。如果用户同时开通了信用卡与支票账户,我们则可以提出补充性问题,例如“您是指信用卡还是支票账户?”以此为基础,大家将获得更可靠的理解能力,借此管理对话流程并提升沟通效率。

本文将向大家展示如何将这些改进与置信度评分加以结合,以业务知识为基础触发最佳响应。

构建Lex机器人

本文将使用以下会话对机器人进行建模。

如果客户在银行中只开通了一个账户:

用户:余额还剩多少?

客服:请输入您的ATMPIN码以确认。 用户:5555

客服:您的支票账户余额为1234美元。

如果客户拥有多种账户,那么对话流程将变为:

用户:余额还剩多少?

客服:好的,您是指支票账户还是信用卡?

用户:信用卡。

客服:请输入您的卡片CVV编号以确认。

用户:1212

客户:您的信用卡余额为3456美元。

要实现以上功能,首先需要构建一个能够支持余额查询、资金转账及账单支付等交易的Amazon Lex机器人。

我们可以使用GetBalanceCreditCardGetBalanceChecking以及 GetBalanceSavings 等提供账户余额信息。 PayBills intent负责处理指向收款人的支付操作, TransferFunds 支持将资金在不同账户间往来转移。最后,您还可以使用 OrderChecks intent进行支票补记。当用户向Lex机器人提出的请求无法使用以上intent加以处理时,则触发其他备选intent作为响应。

部署示例Lex机器人

要创建示例机器人,我们需要完成以下操作步骤。在本文中,我们需要创建一个名为 BankingBot的Amazon Lex机器人,以及一项名为BankingBot_Handler的AWS Lambda函数。

  • 下载 Amazon Lex机器人定义 与 Lambda代码
  • 在Lambda控制台上,选择Creatge function。
  • 输入函数名称 BankingBot_Handler
  • 选择Python运行时最新版本(例如Python 3.8)。
  • 在Permissions部分, 选择 Create a new role with basic Lambda permissions
  • 选择 Create function
  • 当您的Lambda函数创建完成后,在Function code部分,选择 Actions and Upload a .zip file
  • 选择我们之前下载到的 BankingBot.zip文件。
  • 选择 Save
  • 在Amazon Lex控制台上, 选择 Actions, Import
  • 选择我们之前下载到的BankingBot.zip 文件,而后选择 Import
  • 在Amazon Lex控制台上,选择 BankingBot 机器人。
  • Fulfillment 部分,为每一项intent,包括备选intent(BankingBotFallback), 选择 AWS Lambda function而后从下拉菜单中选择 BankingBot_Handler 函数:
  • 在页面提示您向Lambda函数Add permission, 选择 OK.
  • 在所有intents更新完毕之后, 选择 Build

到这里,一个能够正常工作的Lex机器人就创建完成了。

设置置信度评分阈值

现在,我们可以为intent设置置信度评分阈值了。这项设置将根据intent的置信度评分,控制何时将Amazon Lex的Fallback intent作为默认选项。要完成这项设置,请执行以下操作:

  • 在Amazon Lex控制台上, 选择 Settings, 而后选择 General
  • 在 us-east-1us-west-2ap-southeast-2 或 eu-west-1区域中,下滚至Advanced选项,并选择Yes以选择精度改进以及置信度评分所使用的各项特征。

在默认设置下,其他区域已经直接启用了这些改进与置信度支持选项。

  • Confidence score threshold部分,输入一个0到1之间的数字。您可以选择保留默认值,即0.4。
  • 选择 Save,而后选择 Build

在机器人配置完成后,Amazon Lex会在PostText 及 PostContent响应当中显示置信度评分与备选intents:

  "alternativeIntents": [ 
      { 
         "intentName": "string",
         "nluIntentConfidence": { 
            "score": number
         },
         "slots": { 
            "string": "string" 
         }
      }
   ]

 

使用Lambda函数与置信度评分识别用户意图

当用户发出比较模糊的请求时,例如“账户余额还剩多少?”,Lambda函数会解析Amazon Lex返回的intent列表。如果返回了多项intent,则函数会检查排名最高的intent是否具有与AMBIGUITY_RANGE值的定义具有相似的评分。举例来说,如果某项intent的置信度得分为0.95,而另一项intent的评分为0.65,则前者的正确率显然更高。但如果一项intent的评分为0.75,而另一项评分为0.72,我们就需要结合应用程序中的业务知识对二者加以区分。在我们的用例中,如果客户拥有多个账户,则该函数将设置一项补充性的问题,例如“您是指信用卡还是支票账户?”但如果客户只拥有一个账户(例如支票账户),则直接向其返回该账户的余额数字。

在使用置信度评分时,Amazon Lex会在每条响应中返回概率最高的intent,以及最多四项备用intent及其对应置信度评分。如果所有intent的置信度评分均小于您预先定义的阈值,则Amazon Lex会使用AMAZON.FallbackIntent intent、 AMAZON.KendraSearchIntent intent或者二者兼有。您可以直接使用默认阈值,也可以根据需求另行设定。

以下代码所示,为我们在本文的示例机器人中下载的Lambda代码。此函数同样适用于各类其他Amazon Lex机器人。

此Lambda函数的分派器函数会将请求转发至处理程序函数,但GetBalanceCreditCard, GetBalanceChecking以及 GetBalanceSavings intents则会被其转发至determine_intent

其中还有负责检查Lex报告中各top事件及其他备选intents的 determine_intent函数。如果某一备选intent适用于当前用户查询(以其账户为基础),且置信度评分处于top事件的AMBIGUITY_RANGE范围之内,则该intent将被添加至可能事件列表当中。

possible_intents = []
# start with the top intent (if it is valid for the user)
top_intent = intent_request["currentIntent"]
if top_intent["name"] in valid_intents:
    possible_intents.append(top_intent)

# add any alternative intents that are within the AMBIGUITY_RANGE
# if they are valid for the user
if intent_request.get("alternativeIntents", None):
    top_intent_score = top_intent["nluIntentConfidenceScore"]
    for alternative_intent in intent_request["alternativeIntents"]:
        alternative_intent_score = alternative_intent["nluIntentConfidenceScore"]
        if top_intent_score is None:
            top_intent_score = alternative_intent_score                            
        if alternative_intent["name"] in valid_intents:
            if abs(top_intent_score - alternative_intent_score) <= AMBIGUITY_RANGE:
                possible_intents.append(alternative_intent)

 

如果用户只有一项可能的intent,则(在找出所有缺失的slots之后)直接实现。

num_intents = len(possible_intents)
if num_intents == 1:
    # elicit any missing slots or fulfill the intent
    slots = possible_intents[0]["slots"]
    for slot_name, slot_value in slots.items():
        if slot_value is None:
            return elicit_slot(intent_request['sessionAttributes'],
                          possible_intents[0]["name"], slots, slot_name)
    # dispatch to the appropriate fulfillment method 
    return HANDLERS[possible_intents[0]['name']]['fulfillment'](intent_request)

如果存在多项可能的intents,则进一步请求用户做出说明。

elif num_intents > 1:
    counter = 0
    response = ""
    while counter < num_intents:
        if counter == 0:
            response += "Sure. Is this for your " + 
               INTENT_TO_ACCOUNT_MAPPING[possible_intents[counter]["name"]]
        elif counter < num_intents - 1:
            response += ", " + 
               INTENT_TO_ACCOUNT_MAPPING[possible_intents[counter]["name"]]
        else:
            response += ", or " + 
               INTENT_TO_ACCOUNT_MAPPING[possible_intents[counter]["name"]] + "?"
        counter += 1
    return elicit_intent(form_message(response))

如果没有适用于用户的intent,则触发后备intent。

else:
    return fallback_handler(intent_request)

要进行方案测试,大家可以调整check_available_accounts函数的返回值,以更改代码中的测试用户配置:

# This could be a DynamoDB table or other data store
USER_LIST = {
    "user_with_1": [AccountType.CHECKING],
    "user_with_2": [AccountType.CHECKING, AccountType.CREDIT_CARD],
    "user_with_3": [AccountType.CHECKING, AccountType.SAVINGS, AccountType.CREDIT_CARD]
}

def check_available_accounts(user_id: str):
    # change user ID to test different scenarios
    return USER_LIST.get("user_with_2")

我们可以在Amazon Lex控制台或Lambda函数的CloudWatch Logs日志文件中查看Lex的置信度评分。

置信度评分也可用于测试各机器人的不同版本。例如,如果您添加了新的intent、话语或者slot值,则可以测试机器人并检查新的置信度评分,确认相关变更是否达到了预期效果。

总结

虽然人们在与机器人交互时,使用的词语往往不那么精确,但我们仍然需要努力提供自然顺畅的用户体验。Amazon Lex此次推出的一系列自然语言理解改进与置信度评分,将帮助大家结合更多上下文信息设计出智能度更高的对话过程。您可以将,也可以在机器人开发过程中通过测试确定准确的置信度得分阈值,借此确定针对特定intent的样本话语更改是否能够实现预期效果。这些改进将帮助您设计出更加高效的对话流程。关于将这些技术整合至您聊天机器人内的更多详细信息,请参阅 Amazon Lex说明文档

 

本篇作者

Trevor Morse

Amazon AI团队软件开发工程师。他专注于构建并扩展Lex的NLU功能。在业余时间,他喜欢运动以及陪伴家人与朋友。

Brian Yost

Brian Yost 是 AWS Professional Services 的高级顾问。在闲暇时间,他喜欢山地骑行、自酿啤酒和技术研究。

Harshal Pimpalkhute

作为 Amazon Lex团队的产品经理,Harshal Pimpalkhute 投入大量时间尝试使机器(友好地)与人类互动。