AWS智能客服

amazon connect

全渠道云联系中心服务

创建amazon connect的实例

创建过程可以参考–https://docs.aws.amazon.com/zh_cn/connect/latest/adminguide/amazon-connect-instances.html

amazon connect实例详情

image-20221021093726887

这里是设置联系流,可以在这里给联系流绑定上bot和lambda,只有在这里绑定了,在创建联系流时才能使用bot和lambda

image-20221021093750611

机器人lex

智能回复,本质上就是计算文本相似度,匹配分支,给予用户不同的反馈。

创建lex v2的实例

创建比较简单,可以参考–https://docs.aws.amazon.com/zh_cn/connect/latest/adminguide/tutorial1-create-helpdesk.html,这个文档描述的是v1版本的机器人,目前最新的是v2,其实也差不多。

注意–在联系流中使用v2版本的机器人,联系流的语言属性必须是机器具有的语言,目前中文联系流存在问题。

配置意图

机器人可以有多个意图,这里意图可以理解为接收用户的指令然后去执行。

流程

创建意图—添加语句—添加插槽—确认提示和拒绝响应—执行(配置lambda)—正在关闭响应

相关概念

语句:指令关键词,当用户输入与这些关键词匹配时,就会执行相应的意图,一个意图可以创建多个语句。

插槽:执行指令,可能需要用户提供一些信息,比如设备编码等,需要用户提供的信息就称为插槽

配置lambda

请求json、响应json格式参考链接–https://docs.aws.amazon.com/zh_cn/lexv2/latest/dg/lambda.html

绑定lambda

image-20221021093758161

意图设置

image-20221021093802622

在这个界面可以设置属性值,可以用来配置在lambda中的路由,该属性在json中的对应位置是"requestAttributes"中,messageVersion不会变,路由取该值判断。路由到方法后通过取interpretations(可能包含多个意图) 判断是那个意图,interpretations中的intent是满足用户输入的意图列表。意图按信心分数排序。

image-20221021093841979

lambda路由方案

使用机器人名称做类名,前缀写死,方法名为最匹配的意图名

优点:结构清晰,使用简便

缺点:当一个机器人的意图过多,会导致一个类中方法过多(可以按功能划分机器人,避免机器人中意图过多)。

lambda返回参数

dialogAction

必填项。dialogAction 字段指示 Amazon Lex 进行下一步操作,并说明在 Amazon Lex 将响应返回给客户端后用户应执行的操作。

type 字段指示下一步操作。它还确定 Lambda 函数需要作为 dialogAction 值的一部分提供的其他字段。

  • Close — 通知 Amazon Lex 不要期望用户进行响应。例如,“您的披萨已下单”不需要响应。

    fulfillmentState 字段为必填项。Amazon Lex 使用此值在对客户端应用程序的 PostContentPostText 响应中设置 dialogState 字段。messageresponseCard 字段是可选的。如果您不指定消息,则 Amazon Lex 将使用为此目的配置的再见消息或跟进消息。

    "dialogAction": {
        "type": "Close",
        "fulfillmentState": "Fulfilled or Failed",
        "message": {
          "contentType": "PlainText or SSML or CustomPayload",
          "content": "Message to convey to the user. For example, Thanks, your pizza has been ordered."
        },
       "responseCard": {
          "version": integer-value,
          "contentType": "application/vnd.amazonaws.card.generic",
          "genericAttachments": [
              {
                 "title":"card-title",
                 "subTitle":"card-sub-title",
                 "imageUrl":"URL of the image to be shown",
                 "attachmentLinkUrl":"URL of the attachment to be associated with the card",
                 "buttons":[ 
                     {
                        "text":"button-text",
                        "value":"Value sent to server on button click"
                     }
                  ]
               } 
           ] 
         }
      }
    
  • ConfirmIntent — 通知 Amazon Lex,用户应提供“是”或“否”答案以确认或拒绝当前目的。

    必须包含 intentNameslots 字段。对于指定目的的每个填充槽,slots 字段都必须包含一个条目。未填充槽的 slots 字段无需包含条目。如果目的的 confirmationPrompt 字段为空,则您必须包括 message 字段。Lambda 函数返回的 message 字段的内容优先于目的中指定的 confirmationPromptresponseCard 字段为可选项。

    "dialogAction": {
        "type": "ConfirmIntent",
        "message": {
          "contentType": "PlainText or SSML or CustomPayload",
          "content": "Message to convey to the user. For example, Are you sure you want a large pizza?"
        },
       "intentName": "intent-name",
       "slots": {
          "slot-name": "value",
          "slot-name": "value",
          "slot-name": "value"  
       },
       "responseCard": {
          "version": integer-value,
          "contentType": "application/vnd.amazonaws.card.generic",
          "genericAttachments": [
              {
                 "title":"card-title",
                 "subTitle":"card-sub-title",
                 "imageUrl":"URL of the image to be shown",
                 "attachmentLinkUrl":"URL of the attachment to be associated with the card",
                 "buttons":[ 
                     {
                        "text":"button-text",
                        "value":"Value sent to server on button click"
                     }
                  ]
               } 
           ] 
         }
      }
                             
    
  • Delegate — 指示 Amazon Lex 根据自动程序配置选择下一步操作。如果响应不包含任何会话属性,Amazon Lex 将保留现有属性。如果您希望槽值为空,则无需在请求中包含槽字段。如果您的实现函数返回 Delegate 对话操作而没有删除任何槽,您将收到 DependencyFailedException 异常。

    kendraQueryRequestPayloadkendraQueryFilterString 字段是可选的,并且仅当目的派生自 AMAZON.KendraSearchIntent 内置目的时才使用。有关更多信息,请参阅 AMAZON.KendraSearchIntent

      "dialogAction": {
       "type": "Delegate",
       "slots": {
          "slot-name": "value",
          "slot-name": "value",
          "slot-name": "value"  
       },
       "kendraQueryRequestPayload": "Amazon Kendra query",
       "kendraQueryFilterString": "Amazon Kendra attribute filters"
      }
    
  • ElicitIntent — 通知 Amazon Lex,用户应使用包含目的的表达进行响应。例如,“我想要大份披萨”表示 OrderPizzaIntent。 另一方面,表达“大份”不足以供 Amazon Lex 推断用户的目的。

    messageresponseCard 字段是可选的。如果您不提供消息,则 Amazon Lex 会使用自动程序的某个说明提示。如果没有定义澄清提示,Amazon Lex 将返回“400 错误请求”异常。

    {
      "dialogAction": {
        "type": "ElicitIntent",
        "message": {
          "contentType": "PlainText or SSML or CustomPayload",
          "content": "Message to convey to the user. For example, What can I help you with?"
        },
        "responseCard": {
          "version": integer-value,
          "contentType": "application/vnd.amazonaws.card.generic",
          "genericAttachments": [
              {
                 "title":"card-title",
                 "subTitle":"card-sub-title",
                 "imageUrl":"URL of the image to be shown",
                 "attachmentLinkUrl":"URL of the attachment to be associated with the card",
                 "buttons":[ 
                     {
                        "text":"button-text",
                        "value":"Value sent to server on button click"
                     }
                  ]
               } 
           ] 
        }
     }                       
                            
    
  • ElicitSlot — 通知 Amazon Lex,用户应该在响应中提供槽值。intentNameslotToElicit 字段是必填字段。slots``messageresponseCard 字段是可选的。如果您不指定消息,则 Amazon Lex 将使用为槽配置的某个槽引出提示。

      "dialogAction": {
        "type": "ElicitSlot",
        "message": {
          "contentType": "PlainText or SSML or CustomPayload",
          "content": "Message to convey to the user. For example, What size pizza would you like?"
        },
       "intentName": "intent-name",
       "slots": {
          "slot-name": "value",
          "slot-name": "value",
          "slot-name": "value"  
       },
       "slotToElicit" : "slot-name",
       "responseCard": {
          "version": integer-value,
          "contentType": "application/vnd.amazonaws.card.generic",
          "genericAttachments": [
              {
                 "title":"card-title",
                 "subTitle":"card-sub-title",
                 "imageUrl":"URL of the image to be shown",
                 "attachmentLinkUrl":"URL of the attachment to be associated with the card",
                 "buttons":[ 
                     {
                        "text":"button-text",
                        "value":"Value sent to server on button click"
                     }
                  ]
               } 
           ] 
         }
      }
    

卡片消息

lex响应的格式,lambda响应必须按照此格式填充好必填的值,否则机器人会报错

image-20221021093858440

使用卡片消息需要设置消息体类型为CustomPayload,然后在content字段设置value值,value内容参考–https://docs.aws.amazon.com/zh_cn/connect/latest/adminguide/interactive-messages.html

使用机器人属性

属性 描述 JSONPath 引用
对话状态 从 Amazon Lex 自动程序返回的最后的对话状态。如果一个目的返回到联系流,则该值为“已完成”。 $.Lex.DialogState
目的名称 Amazon Lex 返回的用户目的。 $.Lex.IntentName
Slots 在交互期间从用户输入中检测到的目的槽(键值对)Amazon Lex 的映射。 $.Lex.Slots.slotName
会话属性 表示会话特定上下文信息的键值对的映射。 $.Lex.SessionAttributes.key

联系流

conect的核心,决定了与客户的交互流程。

创建联系流

入站联系流:用户发起的联系,支持文字、语音通话

出站联系流:由服务方发起的联系,支持语音通话、邮件、短信

联系流块

使用lambda块

参考文档–https://docs.aws.amazon.com/zh_cn/connect/latest/adminguide/connect-lambda-functions.html

lambda块返回参数使用.Externel.[key]来直接获取值,示例:.Externel.[key]来直接获取值,示例:.External.name。

也可以将返回参数设置为联系人属性,使用设置联系人块,这样可以将作用域升级为整个会话的周期,需要使用参数时从联系人属性取值,使用$.Attributes.[key],示例 $.Attributes.name

image-20221021095235578

使用联系人属性判断块

这里有坑,对于数字类型才能使用等于、小于等比较方式,对于文字只能使用开头为、结尾为、包含。

image-20221021095302222

连接人工客服

需要配置客户等待队列,可以将用户需求划分不同的队列,这样可以将用户分流到相应领域的客服。

image-20221021095316313

客服路由

创建客服

image-20221021095337779

创建账号

设置客服登录cpp的账号和密码

image-20221021095359130

设置客服角色

安全配置文件==角色,选择安全配置文件即可,一般的客服选择agent。安全配置文件可以自定义,配置不同的权限。

通话后续时间:聊天结束后,留给客服创建任务、记录的时间

image-20221021095414952

设置客服路由

决定客服和什么客户对接,路由文件需要自定义。在路由文件中添加队列,再将路由文件配置给客服,从而是客服能处理相应队列的客户需求。

image-20221021095431077

构造聊天容器

将下面代码粘贴到您希望显示此聊天构件的每个网页

添加域名

地址–https://granwin.my.connect.aws/customize-chat-widget

image-20221021095452203

这里通过编辑可以添加多个域名,此外还需要在amazon connect 的实例里设置批准的源添加上域名。

地址–https://us-west-2.console.aws.amazon.com/connect/v2/app/settings/approved-origins

image-20221021095506104

密钥使用

生成token(jwt)

主要的参数WidgetId(聊天容器id)、密钥(jwt的sign)

参数地址–https://granwin.my.connect.aws/customize-chat-widget(其中的granwin,可以替换为自己的实例名称)

image-20221021095530721

  • 算法:HS256

  • 声明:

    • subWidgetId

      ReplacewidgetId用你自己的 WidgetId。要查找你的 WidgetID,请参阅示例聊天小部件脚本.

    • IAT:* 按时发行。

    • EXP:* 到期(最多 10 分钟)。

下面的代码片段显示了如何在java 中生成 JWT 的示例:

    public static final long EXPIRE = 1000 * 60 * 10; // tocken过期时间
    public static final String SECRET = "mSGE6SbYwVyFg3Kx+T1fNjLpeQemb7iVZirOi/7QhEc="; // tocken秘钥,可以任意设置
    private static final String WIDGET_ID = "5a17b4ac-b368-46bf-b130-b47d441c7601";
     /**
     * 传入参数,获取jwt字符串
     */
    public static String getJwtToken(JSONObject jsonObject){
       Map<String, Object> map = new HashMap<>();
        map.put("typ", "JWT");
        map.put("alg", "HS256");
        String JwtToken = JWT.create()
                .withHeader(map)
                .withSubject(WIDGET_ID)
                .withIssuedAt(new Date())
                .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRE))

                /*
                 * 在这里可以一直添加参数
                 */
//                .claim("attributes", jsonObject.toJSONString())

                .sign(Algorithm.HMAC256(SECRET));
        return JwtToken;
    }
                

使用token

您必须在嵌入的代码段中实施回调函数,官方示例如以下示例所示。

amazon_connect('authenticate', function(callback) {
  window.fetch('/token').then(res => {
    res.json().then(data => {
      callback(data.data);
    });
  });
});   

实际含义

amazon_connect('authenticate',token); (添加到上文的聊天构建脚本中)  

显示用户名称

要传递客户显示名称,请在片段中实现回调函数。Amazon Connect 会自动检索显示名称。

  1. 完成中的步骤将聊天用户界面添加到你的网站,如果您尚未执行此操作,请。

  2. 扩充现有的小部件片段以添加customerDisplayName回拨。它看起来可能类似于以下示例:

    amazon_connect(‘customerDisplayName’, function(callback) {
      const displayName = ‘Jane Doe’;
      callback(displayName);
    });
    

    重要的是名字被传给callback(name).

open search使用

创建open search实例

参考文档:https://docs.aws.amazon.com/zh_cn/opensearch-service/latest/developerguide/createupdatedomains.html

注意事项:

  1. 选择open search,因为后台使用的是open search的sdk

    img

2.访问控制选择创建主用户,记下用户名和密码,java代码和open search交互需要用到。

3.冷存储,在数据量较大时可以开启

以java代码示例

  1. 导入依赖

    <dependency>
        <groupId>org.opensearch.client</groupId>
        <artifactId>opensearch-rest-client</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.13</version>
    </dependency>
    <dependency>
        <groupId>org.opensearch.client</groupId>
        <artifactId>opensearch-java</artifactId>
        <version>1.0.0</version>
    </dependency>
    
  2. 导入open search配置

    open-search:
      url: search-granwin-es-s2i6fyqu46o2uabv4y3rwcsqym.us-west-2.es.amazonaws.com  #不要加https://
      port: 443
      username: granwin #创建时的主账户
      password: Granwin888. #创建时的主账户密码
    

    img3.curd

    https://file-1307860395.cos.ap-guangzhou.myqcloud.com/open search示例代码.pdf

补充信息

假如lambda的使用java等语言,使用lambda块调用lambda时会超时,因为web应用启动需要30来秒,而lambda块最多允许8秒,目前选用方案是使用Amazon EventBridge(事件总线),避免lambda热启动。

参考文档

  1. aws connect: https://docs.aws.amazon.com/zh_cn/connect/latest/adminguide/add-chat-to-website.html
  2. aws lex: https://docs.aws.amazon.com/zh_cn/lexv2/latest/dg/getting-started.html
  3. lex ui master:https://github.com/aws-samples/aws-lex-web-ui