对话模型
技能为用户提供服务时通常需要通过多轮交互完成用户的请求。如当火车票技能收到用户发出的“我想买火车票”的请求时,技能不清楚用户从哪个城市出发也不清楚用户要去哪里,于是会追问用户“你从哪里出发”、“你要去哪里”等问题,获得准确槽位信息,为用户购买准确的车次。假使用户一次性的提供了购票的所有信息,如用户说“我要购买一张21日从北京到上海的G145次列车的二等座”,技能收到用户的请求后,在支付前会再次和用户确认信息“你购买了一张21日G145次列车,从北京南到上海虹桥的二等座,价格是543元,请确认”,用户确认后,技能从用户账户中扣费。
上面示例是多轮对话的两种场景。实际上,技能在与用户交互过程中还有其他的对话场景,技能需要根据这些场景设计并实现对话模型。
对话模型的场景
对话模型大致可以分为如下四种场景。
-
必填槽位的追问
必填槽位是技能理解用户意图必不可少的信息。当用户发出的请求中没有携带必填槽位时,技能会主动发起交互,询问必填槽位的值。如用户对打车技能发出“我要打车去北京站”的请求,请求中没有提供“出发地”即用户从哪里去北京站,此时技能就会进行“出发地”槽位的追问“你现在在哪里”。 -
槽位确认
当用户提供槽位信息时,技能会对一些重要的槽位值(如电话号码、证件号、金钱等槽位)进行确认,也会对一些超出正常情况的槽位值(如用户点外卖时买了50份鸡翅)进行确认,以免出现纰漏,造成用户的损失。 -
意图确认
意图确认是指当技能搜集完所有的槽位信息,准备开始执行用户请求前,对用户意图再次确认。意图确认通常出现在订票、购物等需要支付的技能中,在信息发布技能中也会使用。 意图确认的目的也是保护用户利益,避免因口误或其他疏忽导致请求中出现的错误。 - 上下文语境
上下文语境指在交互过程中上一个意图与下一个意图连接起来。如用户说“查询北京明天的天气”,技能播报了天气情况。用户听完后可能继续问“那后天呢”,这句话是在上文语境的基础上发出的,实际上的请求语句是说“查询北京后天的天气”。如果不结合上一个意图,单独分析"那后天呢",技能不能理解。上下文语境是由用户发起的多轮对话,与前面三种不同。
必填槽位的追问
当技能发现用户的请求中缺少必填槽位信息时,技能会主动发起询问。以订购火车票技能为例。
用户:我想买一张去上海的火车票(用户请求中仅提供了目的地的槽位信息,没有提供出发地的槽位信息)
技能:请问您从哪上车(技能追问“出发地”槽位)
用户:北京
技能:您哪天出发(技能追问“出发日期”槽位)
用户:21日
技能:您想乘坐几点的火车(技能追问"出发时间"槽位)
用户:15点
必填槽位追问的实现
目前有两种方式实现必填槽位追问。
-
技能委托DuerOS完成必填槽位的追问。
技能可以通过配置Dialog.Delegate指令(或setDelegate指令),将对话交给DuerOS,由DuerOS完成必填槽位的追问。DuerOS会将每次槽位的信息发送给技能,由技能确认是否由DuerOS继续完成对话。使用这种方法时,技能需要在技能开放平台上面填写追问语句。以订购火车票的技能为例演示如何实现槽位追问。- 首先在代码中设置delegate指令。
function ticketIntent(){ //对话没有完成时,委托DuerOS进行槽位追问 if(!$this->request->isDialogStateCompleted()) { return $this->setDelegate(); } }
- 在技能开发平台上填写追问语句,如下图所示。
- 首先在代码中设置delegate指令。
-
技能实现必填槽位的追问。
技能通过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' => '请问您想坐几点的车', } .... }
说明:
- 槽位追问仅针对必填槽位,非必填槽位不需要进行追问。
- 在开放平台上填写追问语句时,有如下要求。
- 同一槽位最多填写5个追问语句。当设置多个追问语句时,DuerOS会随机选择1个。
- 追问语句中必须明确询问该槽位的值。
- 如果使用SSML语法,需要将追问语句全部内容添加到
<speak></speak>
标签中。 - 如果有多个槽位需要确认,槽位的追问顺序由平台上槽位的顺序决定。
- 上述两种追问方法不能同时使用。
槽位确认
在技能搜集槽位信息过程中,会对存储重要信息的槽位进行确认,如时间、卡号、金钱等重要信息的槽位。如在订购火车票的技能中,当用户输入身份证信息时,技能会对身份证的槽位进行确认,避免出现错误。
用户:我的身份证号是11022219XX0313XXXX(用户说身份证槽位信息)
技能:好的,您的身份证号码是11022219XX0313XXXX,请确认(技能确认身份证号槽位信息)
用户:确认
如何进行槽位确认
技能可以通过Dialog.ConfirmSlot(或setConfirmSlot)指令对槽位进行确认。在确认槽位过程中使用话术尽量让用户回答是或否。订购火车票的技能中确认身份证槽位信息时,代码示例如下。
function ticketIntent(){
...
$this->setConfirmSlot('ID');
return [
'outputSpeech' => '好的,您的身份证号码是11022219XX0313XXXX,请确认',
];
....
}
说明:
- 槽位确认仅对必填槽位确认,非必填槽位确认没有意义。
- 在确认槽位过程中使用话术尽量让用户回答是或否。
意图确认
当技能搜集完所有槽位信息,准确理解用户的请求,在执行用户请求前,会对意图进行确认。这种情况一般出现在需要用户支付、需要信息确认的技能中,如订票技能、订外卖技能,在用户购买前需要意图确认。在信息平台上发布信息的技能中也会有确认,在发布前要求用户确认是否进行信息发布等。
技能:您购买了一张21日从北京南到上海虹桥的火车票,车次是G115,15点发车,请您确认(技能确认意图信息)
用户:是的
技能:好的,已经为您出票。
如何进行意图确认
目前有两种方式实现意图确认。
-
技能委托DuerOS完成意图确认。
使用Dialog.Delegate将确认交给DuerOS。 在平台上面填写意图确认信息。 技能可以通过配置Dialog.Delegate指令(或setDelegate指令),将对话交给DuerOS,由DuerOS完成意图确认。使用这种方法时,技能需要在技能开放平台上面填写意图确认话术。下面以订购火车票意图为例,演示如何使用DuerOS进行意图确认。- 首先在代码中设置delegate指令。
function ticketIntent(){ //对话没有完成时,委托DuerOS进行槽位追问 if(!$this->request->isDialogStateCompleted()) { return $this->setDelegate(); } }
- 在平台上填写意图确认语句。如下图
- 首先在代码中设置delegate指令。
- 技能实现意图确认。
技能通过使用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}发车,请您确认", ]; } }
说明
- 技能在平台上填写意图确认话术时,请按如下要求填写。
- 使用"$"符号引用槽位。
- 意图确认话术中只支持纯文本,不支持SSML。
- 意图确认默认引用了确认意图和取消意图,可以丰富这两个意图的常用表达。
- 上述两种方法不能同时使用。
上下文语境
上下文语境是指技能结合上下文交互场景分析用户的意图。上下文语境是将用户的两个意图连接使用,一般继承上一个意图的槽位信息。如用户说“北京今天天气怎么样”,技能回复后,用户继续问“后天呢”,此时用户想表达的是“北京后天天气怎么样”,但是在表述过程中省略了北京及天气等相关信息。技能需要结合上一个意图进行分析,把用户缺失的“北京”等槽位信息,从上一个意图中获取,进而相应用户的请求。详细介绍及如何实现请参考上下文语境。