对话模型

技能为用户提供服务时通常需要通过多轮交互完成用户的请求。如当火车票技能收到用户发出的“我想买火车票”的请求时,技能不清楚用户从哪个城市出发也不清楚用户要去哪里,于是会追问用户“你从哪里出发”、“你要去哪里”等问题,获得准确槽位信息,为用户购买准确的车次。假使用户一次性的提供了购票的所有信息,如用户说“我要购买一张21日从北京到上海的G145次列车的二等座”,技能收到用户的请求后,在支付前会再次和用户确认信息“你购买了一张21日G145次列车,从北京南到上海虹桥的二等座,价格是543元,请确认”,用户确认后,技能从用户账户中扣费。

上面示例是多轮对话的两种场景。实际上,技能在与用户交互过程中还有其他的对话场景,技能需要根据这些场景设计并实现对话模型。

对话模型的场景

对话模型大致可以分为如下四种场景。

  • 必填槽位的追问
    必填槽位是技能理解用户意图必不可少的信息。当用户发出的请求中没有携带必填槽位时,技能会主动发起交互,询问必填槽位的值。如用户对打车技能发出“我要打车去北京站”的请求,请求中没有提供“出发地”即用户从哪里去北京站,此时技能就会进行“出发地”槽位的追问“你现在在哪里”。

  • 槽位确认
    当用户提供槽位信息时,技能会对一些重要的槽位值(如电话号码、证件号、金钱等槽位)进行确认,也会对一些超出正常情况的槽位值(如用户点外卖时买了50份鸡翅)进行确认,以免出现纰漏,造成用户的损失。

  • 意图确认
    意图确认是指当技能搜集完所有的槽位信息,准备开始执行用户请求前,对用户意图再次确认。意图确认通常出现在订票、购物等需要支付的技能中,在信息发布技能中也会使用。 意图确认的目的也是保护用户利益,避免因口误或其他疏忽导致请求中出现的错误。

  • 上下文语境
    上下文语境指在交互过程中上一个意图与下一个意图连接起来。如用户说“查询北京明天的天气”,技能播报了天气情况。用户听完后可能继续问“那后天呢”,这句话是在上文语境的基础上发出的,实际上的请求语句是说“查询北京后天的天气”。如果不结合上一个意图,单独分析"那后天呢",技能不能理解。上下文语境是由用户发起的多轮对话,与前面三种不同。

必填槽位的追问

当技能发现用户的请求中缺少必填槽位信息时,技能会主动发起询问。以订购火车票技能为例。

用户:我想买一张去上海的火车票(用户请求中仅提供了目的地的槽位信息,没有提供出发地的槽位信息)
技能:请问您从哪上车(技能追问“出发地”槽位)
用户:北京
技能:您哪天出发(技能追问“出发日期”槽位)
用户:21日
技能:您想乘坐几点的火车(技能追问"出发时间"槽位)
用户:15点

必填槽位追问的实现

目前有两种方式实现必填槽位追问。

  1. 技能委托DuerOS完成必填槽位的追问。
    技能可以通过配置Dialog.Delegate指令(或setDelegate指令),将对话交给DuerOS,由DuerOS完成必填槽位的追问。DuerOS会将每次槽位的信息发送给技能,由技能确认是否由DuerOS继续完成对话。使用这种方法时,技能需要在技能开放平台上面填写追问语句。以订购火车票的技能为例演示如何实现槽位追问。

    1. 首先在代码中设置delegate指令。
      function ticketIntent(){
         //对话没有完成时,委托DuerOS进行槽位追问
         if(!$this->request->isDialogStateCompleted()) {
             return $this->setDelegate();
         }
      }
    2. 在技能开发平台上填写追问语句,如下图所示。
      images
  2. 技能实现必填槽位的追问。
    技能通过Dialog.ElicitSlot指令ask指令进行必填槽位追问。以订购火车票的技能为例演示技能如何实现槽位追问。

    function ticketIntent(){
        $origin = $this->getSlot('origin');
        $destination = $this->getSlot('destination');
        $date = $this->getSlot('date');
        $time = $this->getSlot('time');
    
        if(!$origin){
            $this->nlu->ask('origin');
            $card = new TextCard('请问您要从哪里出发呢?');
            $this->waitAnswer();
            return [
                'card' => $card,
                'outputspeech' => '请问您要从哪里出发呢?',
        }else if(!$destination){
            $this->nlu->ask('destination');
            $card = new TextCard('请问您要到哪里?');
            $this->waitAnswer();
            return [
                'card' => $card,
                'outputspeech' => '请问您要到哪里?',
        }else if (!$date)
            $this->nlu->ask('date');
            $card = new TextCard('请问您哪天出发');
            $this->waitAnswer();
            return [
                'card' => $card,
                'outputspeech' => '请问您哪天出发',
        }else if (!$time) 
            $this->nlu->ask('fromCity');
            $card = new TextCard('请问您想坐几点的车');
            $this->waitAnswer();
            return [
                'card' => $card,
                'outputspeech' => '请问您想坐几点的车',
        }
    ....
    }

说明:

  1. 槽位追问仅针对必填槽位,非必填槽位不需要进行追问。
  2. 在开放平台上填写追问语句时,有如下要求。
    • 同一槽位最多填写5个追问语句。当设置多个追问语句时,DuerOS会随机选择1个。
    • 追问语句中必须明确询问该槽位的值。
    • 如果使用SSML语法,需要将追问语句全部内容添加到<speak></speak>标签中。
    • 如果有多个槽位需要确认,槽位的追问顺序由平台上槽位的顺序决定。
  3. 上述两种追问方法不能同时使用。

槽位确认

在技能搜集槽位信息过程中,会对存储重要信息的槽位进行确认,如时间、卡号、金钱等重要信息的槽位。如在订购火车票的技能中,当用户输入身份证信息时,技能会对身份证的槽位进行确认,避免出现错误。

用户:我的身份证号是11022219XX0313XXXX(用户说身份证槽位信息)
技能:好的,您的身份证号码是11022219XX0313XXXX,请确认(技能确认身份证号槽位信息)
用户:确认

如何进行槽位确认

技能可以通过Dialog.ConfirmSlot(或setConfirmSlot)指令对槽位进行确认。在确认槽位过程中使用话术尽量让用户回答是或否。订购火车票的技能中确认身份证槽位信息时,代码示例如下。

function ticketIntent(){
    ...
    $this->setConfirmSlot('ID');
    return [
        'outputSpeech' => '好的,您的身份证号码是11022219XX0313XXXX,请确认',
    ];
    ....
}

说明:

  1. 槽位确认仅对必填槽位确认,非必填槽位确认没有意义。
  2. 在确认槽位过程中使用话术尽量让用户回答是或否。

意图确认

当技能搜集完所有槽位信息,准确理解用户的请求,在执行用户请求前,会对意图进行确认。这种情况一般出现在需要用户支付、需要信息确认的技能中,如订票技能、订外卖技能,在用户购买前需要意图确认。在信息平台上发布信息的技能中也会有确认,在发布前要求用户确认是否进行信息发布等。

技能:您购买了一张21日从北京南到上海虹桥的火车票,车次是G115,15点发车,请您确认(技能确认意图信息)
用户:是的
技能:好的,已经为您出票。

如何进行意图确认

目前有两种方式实现意图确认。

  1. 技能委托DuerOS完成意图确认。
    使用Dialog.Delegate将确认交给DuerOS。 在平台上面填写意图确认信息。 技能可以通过配置Dialog.Delegate指令(或setDelegate指令),将对话交给DuerOS,由DuerOS完成意图确认。使用这种方法时,技能需要在技能开放平台上面填写意图确认话术。下面以订购火车票意图为例,演示如何使用DuerOS进行意图确认。

    1. 首先在代码中设置delegate指令。
      function ticketIntent(){
         //对话没有完成时,委托DuerOS进行槽位追问
         if(!$this->request->isDialogStateCompleted()) {
             return $this->setDelegate();
         }
      }
    2. 在平台上填写意图确认语句。如下图
      images
  2. 技能实现意图确认。
    技能通过使用Dialog.ConfirmIntent指令(或setConfirmIntent指令)进行意图确认,代码示例如下。
    function ticketIntent(){
        $origin = $this->getSlot('origin');
        $destination = $this->getSlot('destination');
        $date = $this->getSlot('date');
        $time = $this->getSlot('time');
        $train-number = $this->getSlot('train-number'); 、
        if($money && $phone) {
            $this->setConfirmIntent();
            return [
                'outputSpeech' => "您购买了一张${date}从${origin}到${destination}的火车票,车次是${train-number},${time}发车,请您确认",
            ];
        }
    }

说明

  1. 技能在平台上填写意图确认话术时,请按如下要求填写。
    • 使用"$"符号引用槽位。
    • 意图确认话术中只支持纯文本,不支持SSML。
    • 意图确认默认引用了确认意图和取消意图,可以丰富这两个意图的常用表达。
  2. 上述两种方法不能同时使用。

上下文语境

上下文语境是指技能结合上下文交互场景分析用户的意图。上下文语境是将用户的两个意图连接使用,一般继承上一个意图的槽位信息。如用户说“北京今天天气怎么样”,技能回复后,用户继续问“后天呢”,此时用户想表达的是“北京后天天气怎么样”,但是在表述过程中省略了北京及天气等相关信息。技能需要结合上一个意图进行分析,把用户缺失的“北京”等槽位信息,从上一个意图中获取,进而相应用户的请求。详细介绍及如何实现请参考上下文语境

相关主题

对话的模糊回答
上下文语境