配置 Azure 代理以升级和结束对话

注释

Copilot Studio 机器人重命名为 Copilot 代理(代理或 AI 代理)。 人工代理现在更名为客户服务代表(服务代表或代表)。 在我们更新产品 UI、文档和培训内容时,您可能会遇到对新旧术语的引用。

本文介绍如何在 Azure 中对 AI 代理(代理)进行编程,以将对话路由到 Dynamics 365 联络中心中的客户服务代表(服务代表或代表)。 它还描述了如何对代理进行编程以结束对话。

重要

  • 只有当代理被添加到基于推送的工作流时,代理才能接收对话。
  • 咨询模式下不支持AI代理。

先决条件

  • 您必须在 Azure 中有一个配置并与 Dynamics 365 Contact Center 集成的代理。 在集成 Azure 代理中了解详细信息
  • 应启用基于技能的路由。

将对话上报给代表

在 Dynamics 365 Contact Center 中,代理可以将当前对话上报给代表。 对话的路由取决于为工作流配置的路由规则。

当代表接受升级请求并将对话从AI客服转接时,客户和案件详情 会自动被识别。 座席通过使用 Dynamics 365 Contact Center 上下文变量来路由对话。 代理可以向 Dynamics 365 Contact Center 发送上下文变量及相关值列表,同时发送升级请求。 代理还可以设置上下文项,供技能查找模型识别新技能并将其附加到对话中的现有技能列表中。 随后,Dynamics 365 Contact Center 会更新指定值的上下文变量,并再次运行路由引擎。 系统会确保升级的对话被引导到正确的队列。 了解更多关于 “当客服升级或结束对话时,客户和案件与对话的关联”中上下文项和变量名称的更多信息。

代表接受升级请求后,代理与客户的对话记录将在代表的对话小组件上可见。 然后,代表可以继续与客户进行对话。

注释

对话摘要对客户是看不到的。

结束对话

当Azure代理确定客户的问题已被回答,或者客户不再回应时,可以选择结束对话。 客服可以向Dynamics 365联络中心发送 EndConversation 请求。

代码示例

本部分包括可用于配置 Azure 机器人以升级和结束对话的代码示例。

  1. 实现命令类,以对与升级和结束对话相关的任务进行建模。

  2. 实现一个全渠道客户端类来设置命令上下文。

    示例代码如下。

    /// <summary>
    /// Send end of conversation context to user and agent.
    /// </summary>
    public static async Task EndConversationAsync(ITurnContext turnContext, CancellationToken cancellationToken)
    {
        IActivity customerFacingActivity = Activity.CreateMessageActivity();
        customerFacingActivity.Text = "Thanks for talking with me. Have a good day. Bye.";
        BridgeBotMessage(customerFacingActivity);
    
        IActivity agentFacingActivity = Activity.CreateMessageActivity();
        agentFacingActivity.Text = "Ending the conversation as per customer request.";
        AddContext(CommandType.EndConversation, agentFacingActivity);
    
        List<IActivity> messageActivities = new List<IActivity>
        {
            customerFacingActivity,
            agentFacingActivity
        };
    
        await turnContext.SendActivitiesAsync(messageActivities.ToArray(), cancellationToken);
    }
    
    /// <summary>
    /// Send escalation context to user and agent.
    /// </summary>
    public static async Task EscalateConversationAsync(ITurnContext turnContext, IContextManager contextManager, CancellationToken cancellationToken)
    {
        IActivity customerFacingActivity = Activity.CreateMessageActivity();
        customerFacingActivity.Text = "Perfect I’ll transfer you now";
        BridgeBotMessage(customerFacingActivity);
    
        IActivity agentFacingActivity = Activity.CreateMessageActivity();
        agentFacingActivity.Text = GetEscalationSummary(turnContext, contextManager);
        AddContext(CommandType.Escalate, agentFacingActivity, contextManager.GetContext(turnContext.Activity.Conversation.Id));
    
        List<IActivity> messageActivities = new List<IActivity>
        {
            customerFacingActivity,
            agentFacingActivity
        };
    
        await turnContext.SendActivitiesAsync(messageActivities.ToArray(), cancellationToken);
    }
    
  3. 在 Bot ActivityHandler 类中调用相应的客户端方法。

  4. 根据您的要求更改 EscalateEndConversation 命令条件。

  5. 在你的机器人代码中添加代码声明 OmnichannelBotClient.BridgeBotMessage(turnContext.Activity); ,以便向Dynamics 365联系人中心发送消息。 必须为发送给客户的每个活动消息调用此方法。

    示例代码如下。

    protected async Task OnMessageActivityAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(turnContext);
        var text = turnContext.Activity.Text?.ToLower(CultureInfo.InvariantCulture);
        var responseActivity = Activity.CreateMessageActivity();
        Responses.BuildCustomerFileAttachmentResponse(turnContext, responseActivity);
    
        if (string.IsNullOrEmpty(text))
        {
            if (turnContext.Activity.Value is JsonElement jsonElement)
            {
                var activityResponseValue = turnContext.Activity.Value;
                responseActivity.Text = $"You replied with value: {Environment.NewLine}{activityResponseValue}";
            }
        }
        else if (text.StartsWith("echo:", StringComparison.OrdinalIgnoreCase))
        {
            responseActivity.Text = text.Replace("echo:", "", StringComparison.OrdinalIgnoreCase);
        }
        else if (text.Contains("ac ", StringComparison.OrdinalIgnoreCase))
        {
            Responses.BuildAdaptiveCardResponse(responseActivity, text);
        }
        else
        {
            switch (text)
            {
                case Commands.Agent:
                    await OmnichannelAgentClient.EscalateConversationAsync(turnContext, _contextManager, cancellationToken);
                    return;
                case Commands.AnimationCard:
                case Commands.AudioCard:
                case Commands.FaultySigninCard:
                case Commands.HeroCard:
                case Commands.HeroCardIMBack:
                case Commands.HtmlList:
                case Commands.Markdown:
                case Commands.ReceiptCard:
                case Commands.SigninCard:
                case Commands.ThumbnailCard:
                case Commands.VideoCard:
                    Responses.BuildStructuredCardResponse(responseActivity, text);
                    break;
                case Commands.AttachmentFromC2:
                    responseActivity.Text = $"Attachment type has been identified";
                    break;
                case Commands.Debug:
                    Responses.BuildDebugContextResponseText(_contextManager, turnContext, responseActivity);
                    break;
                case Commands.EndChat:
                    await OmnichannelAgentClient.EndConversationAsync(turnContext, cancellationToken);
                    break;
    
                case Commands.Help:
                    Responses.BuildHelpResponse(responseActivity);
                    break;
                default:
                    Responses.BuildDidNotUnderstandResponse(responseActivity, text);
                    break;
            }
        }
        await OmnichannelAgentClient.BridgeAndSendActivityAsync(turnContext, responseActivity, cancellationToken);
    }
    

    字典 contextVars 包含了你想作为升级请求一部分更新的所有上下文变量名称值对。 这是 BotHandoffTopic 上下文变量名称, CreditCard 是上下文变量值。 如果存在代表队列,规则 BotHandoffTopic 等于 CreditCar,那么升级聊天会被引导到该队列。

    上下文变量名称的类型为 String。 上下文变量值必须是 Integer 或 String 类型,并且在升级期间应作为字典<字符串、对象> 传递。 示例代码如下。

    Dictionary<string, Object> keyValues = new Dictionary<string, object>()
    {
        { "BotHandoffTopic", "CreditCard" },
        { "IDNumber", 101}
    }
    

客服还可以发送一份升级摘要,只有在客服接受升级聊天请求后才能看到。 要发送摘要,请在升级消息中设置活动文本。

集成 Azure 智能体
添加上下文变量
Azure 机器人服务
将代理连接到通道
使用 Direct Line 集成自己的自定义通道
配置 Azure 和 Copilot Studio 代理的最佳实践