无服务器

联系中心票自动化与Lex和Lambda

在工作流程中使用无服务器系统可以简化和自动化业务流程。
詹姆斯Foley Trek10
詹姆斯福利 | 2019年10月2日

整合 lexbots. lambda的功能 进入你的 亚马逊连接 工作流程可以帮助解决您的呼叫中心自动化需求。在Trek10,我们在呼叫中心工作流程中使用Lex和Lambda来将口头输入转换为文本,并使用这些值来自动从呼叫者组织提交支持票证。此博客将解释TREK10如何将AWS无服务器系统集成到手动过程中以解决业务需求。

问题

在Trek10,我们有一个呼叫中心来处理入站客户端的电话。如果最终用户需要帮助并调用Trek10的支持号码,则呼叫中心代理处理呼叫,请参加一些必要的信息,例如调用者名称,来电组织和简要消息。然后调用呼叫中心代理将此信息置于一个电子邮件中,该电子邮件将紧急票证提交到Trek10的票务系统中。当他们进入系统时,这些票证没有与特定客户联系在一起。相反,Trek10代理必须解密客户端有一个问题,那个问题是什么,如果这个问题是紧急或正常的优先级。由于监控Trek10在客户环境中提供的级别,因此如今,这些天的呼叫不如这些天。通常,客户端的AWS环境中的任何问题都会在客户端通知之前出现为监视器触发器和警报TREK10代理。如果需要,客户可以通过电子邮件提交门票,但是呼叫一个数字,如旧学校,因为现在可能看起来可能是客户的选择,无论如何。

作为上述过程的经验丰富和精致,上述系统存在一些问题:

  • 无论问题,呼叫中心提交的门票都是紧急的优先级
  • 在提交票证时,无法通过客户组织和最终用户过滤票证

解决方案

像许多东西一样,亚马逊有一个解决方案:。当AWS出来时,Trek10发现呼叫中心的工作流程非常强大,随着时间的推移,发现如何将其他AWS服务集成到工作流中。认识到这是一个游戏更换者。我们能够创建一个自动化的工作流,解决了我们所有的呼叫中心票务问题。

以下是我们创建的Connect Workflow的片段,以自动化来电支持票证:

AWS无服务器服务我们在此工作流程中连接在一起,是连接,Lambda,Lex和DynamoDB以及我们的票务系统API。所有服务共同努力携带客户的呼叫,知道客户端是谁,允许客户通过语音输入票证信息,将语音输入转换为文本,存储在数据库中的呼叫者信息和语音输入,并在数据库中创建票证Trek10的票务服务。

在完全使用此工作流程之前,我们需要提出解决方案来解决我们的票务系统的限制。要将票证路由到正确的客户组织,票务系统需要客户端电子邮件地址。但是,Amazon Connect不容易存储此信息。要解决此问题,我们使用该系统创建了带有名称,电子邮件地址和客户端的电话号码的DynamoDB表。现在,当客户端呼叫时,触发Lambda函数,该函数从DynamoDB表中抓取用户信息,并且在询问呼叫者任何内容之前,Lexbot语音在姓名和组织中欢迎来电者。它肯定是一个很好的触感,即使它是一个与你交谈的机器人。

在初始尼加斯之后,lexbot要求票务优先权和来电者总结该问题。呼叫者的响应转换为文本,并且λ函数拿到那些lexbot响应并在呼叫结束后将它们输入dynamodb表中。相同的Lambda函数占据了来电者的电子邮件地址,票证优先级和问题,并使用票务系统API提交票证。票证以正确的优先级输入调用者组织下的系统。(注意:如果一个未知的来电者呼叫,则工作流程将呼叫者指向一个单独的lexbot,要求调用者的名称,组织,票证优先级和问题。然后,该过程然后将呼叫者提出的优先级与呼叫者一起提出的一般票证呼叫者提供的剩余信息。)

用于从已知的呼叫者接收信息的Lexbot列出:

上面的Lexbot具有优先级类型和问题的插槽。如果他们的问题较低或更紧急,lexbot会询问呼叫者。来电者还以几句话解释了这个问题。

当呼叫者输入完成时,Lambda函数通过将DynamoDB表中的所有信息存储在DynamoDB表中并通过API创建Trek10的票务系统中的票证来满足请求。 Lambda功能的片段如下:


在成功调用后,连接工作流确认给呼叫者创建并结束呼叫。提交票证,并且基于优先级的Trek10代理助攻。

随着AWS服务的综合力量,我们已经减轻了所有原始问题。您可以开始看到AWS的力量以及不同的AWS系统如何共同努力解决业务流程需求。如果您正在寻找自己的亚马逊连接呼叫中心,如果您想将自动化或其他服务集成到您已经创建的Amazon Connect Workflow,或使用任何AWS系统获取专家建议,请在Trek10与我们联系,我们将是很高兴探索我们如何提供帮助的可能性。


import logging
import boto3
import json
from boto3.dynamodb.conditions import Key
from zdesk import Zendesk


logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# Get the service resource.
dynamodb = boto3.resource('dynamodb')

# Instantiate a table resource object
db_table = dynamodb.Table('dynamotableA')
br_table = dynamodb.Table('dynamotableB')

""" --- Main handler --- """

def lambda_handler(event, context):
    logger.debug(json.dumps(event))
    logger.debug('event.bot.name={}'.format(event['bot']['name']))
    logger.debug('dispatch userId={}, intentName={}'.format(event['userId'], event['currentIntent']['name']))
    logger.debug('entire.event={}'.format(event))


    # Validate intent name
    intent_name = event['currentIntent']['name']
    if intent_name != 'lexbotintent':
        raise Exception('Intent with name ' + intent_name + ' not supported!')

    # Validate invocation source
    source = event['invocationSource']
    if source == 'DialogCodeHook':
        raise Exception('This Lambda function only support fulfillment')

    # Get bot slot values
    issue = event['currentIntent']['slots']["issue"]
    prioritytype = event['currentIntent']['slots']["prioritytype"]

    ## Get customer number from DynamoDB table
    response = br_table.query(
        TableName='dynamotableB',
        IndexName='constant-timestamp-index',
        Select='ALL_ATTRIBUTES',
        Limit=1,
        ConsistentRead=False,
        ScanIndexForward=False,
        KeyConditionExpression=Key("constant").eq("a")
    )
    phoneNumber = response['Items'][0]['phoneNumber']
    
    update_response = db_table.update_item(
        Key={
            "phoneNumber": phoneNumber,
        },
        UpdateExpression='SET issue = :issue, prioritytype = :prioritytype',
        ExpressionAttributeValues={
            ":prioritytype": prioritytype,
            ":issue": issue
        }
    )
    
    get_customer_info = db_table.get_item(
        TableName='dynamotableA',
        Key={
            "phoneNumber": phoneNumber,
        },
    )['Item']
    
    #create ticket in zendeks with dynamodb and lexbot values
    SSM_CLIENT = boto3.client('ssm')
    zd_secret = SSM_CLIENT.get_parameter(
        Name='ssm_secret_key_name',
        WithDecryption=True
    )['Parameter']['Value']
    zendesk = Zendesk('companyzendeskurl', 'zendesk_user_email', zd_secret, True)
    new_ticket = {
    'ticket': {
        'requester': {
            #'name': get_customer_info['firstName'],
            'email': get_customer_info['email'],
        },
        'subject': 'Ticket Subject Here',
        'description': get_customer_info['issue'],
        'tags': ['key1', 'value1'],
        'priority': get_customer_info['prioritytype']
        }
    }
    zd = zendesk.ticket_create(data=new_ticket)
    logger.debug(zd)
    
 # Define the return response to the Lex bot in the required Lex response format. The
    # The Lex response format is documented here: http://docs.aws.amazon.com/lex/latest/dg/lambda-input-response-format.html#using-lambda-response-format
    intent_fulfillment_response = { 'sessionAttributes': event["sessionAttributes"],
       'dialogAction': {
            'type': 'Close',
            'fulfillmentState': 'Fulfilled',
            'message':
            {'contentType': 'SSML',
            # Message to return to the Lex bot 
             'content': 'Thank you. A ticket was sucessfully created. A Trek10 agent will be online and respond shortly. Have a great day.'}
        }
    }

    return intent_fulfillment_response

在成功调用后,连接工作流确认给呼叫者创建并结束呼叫。提交票证,并且基于优先级的Trek10代理助攻。

随着AWS服务的综合力量,我们已经减轻了所有原始问题。您可以开始看到AWS的力量以及不同的AWS系统如何共同努力解决业务流程需求。如果您正在寻找自己的亚马逊连接呼叫中心,如果您想将自动化或其他服务集成到您已经创建的Amazon Connect Workflow,或使用任何AWS系统获取专家建议,请在Trek10与我们联系,我们将是很高兴探索我们如何提供帮助的可能性。

作者
詹姆斯Foley Trek10
詹姆斯福利