介绍

本文为《意图技能回答服务》的上下文实现示例。

意图技能主要完成用户输入语句的解析。然而,对话状态转移、对话关键信息的储存,这些上下文信息需要单独维护。本文主要介绍使用薄言研发的ContextFlow上下文框架,来配合意图技能完成整个上下文对话。

薄言ContextFlow框架用XML脚本文件定义对话状态和关键信息。框架系统需要运行在服务器上,并在轻语平台中填写该服务地址,实现二者对接。详见下文。

对话过程

示例场景为“机票预定”。想要预定一张机票,需要3个关键因素(必备条件):日期、出发地和目的地。缺少其中之一,对话系统会询问用户进行补全。补全3个信息之后,将会查询机票。 上轮对话中的关键信息,保存在会话Session中,用于下文提取或者修改相关信息。示例对话过程如下。机票预定对话过程

系统设计步骤

  1. 画流程图,规划上下文流程;
  2. 根据流程,编写XML文件;
  3. 编写意图与词典,用于理解用户意图、提取槽位;
  4. 测试;
  5. 发布服务。

流程图

参考示例对话过程,根据其中的关键信息,抽象出各个对话状态和跳转逻辑,绘制出完整的流程图,便于编写XML脚本。流程图

编写XML脚本

根据流程图,编写XML脚本文件,用于控制对话流程状态。

薄言ContextFlow的XML脚本简要介绍:

  • 每个entry中可包含多个trans;
  • 每个trans中可包含condition、intent和下一个state;
  • condition包含type、args;
  • 每个state中包含name、action、stimulate和trans;
  • action包含type、args。

例如:

<?xml version="1.0" encoding="UTF-8"?>
<xml>
<!-- 入口状态 -->
<entry>
<trans>
<!-- 槽位是否齐全?-->
<condition>
<type>NOT_CONTAIN_PROP_KEY</type>
<args>目的地 出发地</args>
</condition>
<intent>booking_entry</intent>
<state>缺少目的地和出发地</state>
</trans>
</entry>
<!-- 询问信息,补全槽位 -->
<state>
<name>缺少目的地和出发地</name>
<args>出发地 日期 目的地 时间 数字 舱位 ID</args>
<action>
<type>ANSWER</type>
</action>
<stimulate>请问您的出发地和目的地是哪里呢?(例子格式为“出发地:北京,目的地:上海”)</stimulate>
<trans>
<intent>booking_leav_arr_city</intent>
<state>查询</state>
</trans>
</state>
<!-- 查询状态 -->
<state>
<name>查询</name>
<action>
<type>ANSWER</type>
<args>出发地 日期 目的地 时间 数字 舱位 ID 折扣 票价</args>
</action>
<stimulate>请稍候,正在帮您查询……机票(需连接外部数据,由用户选择航班号)。请问您是否有其他服务要求?</stimulate>
<trans>
<intent>booking_ID</intent>
<state>出票</state>
</trans>
</state>
<!-- 出票 -->
<state>
<name>出票</name>
<action>
<type>ANSWER</type>
<args>ID</args>
</action>
<stimulate>正在为您出票,请稍候。</stimulate>
</state>
</xml>

备注:

  • type若为ANSWER,args需写出所有在此阶段获需要更新的槽位名称;
  • 查询步骤中,stimulate已写死,可在Java程序中调用槽位、保存参数并进行修改查询;
  • 实际操作重,这与下一步意图与词典的编写迭代完成。比如在写entry状态时,可先编写意图里的模版,发现可能会有缺少槽位的情况(例:订一张明天的机票。此处缺少目的地和出发地两个必要槽位)。此时可在XML文件中添加condition,补全缺失槽位,并加入对应的state信息。

意图及词典

在轻语平台上创建意图模板与词典

意图

用于识别用户输入。

词典

用于匹配同近义词。

测试

测试分为本地测试与服务端测试。

本地测试方便开发者调试。因无法接受解析结果,需要自行调用接口(PARSING_URL)进行解析,运行结果只可在后台看到。

服务端测试可以直接利用意图技能,将运行结果连接到前端网页中。但需要部署到远程服务器。

本地测试

(1) 设置PARSING_URL

在ContextFlow程序中设置意图解析的API地址:

private static final String PARSING_URL ="https://dev.rsvp.ai/eparser/api/product/parse/proto?skillid=[your-skill-id]&sentence="

(2) 解析输入句

用户在对话机器人处输入:“订一张明天去武汉的机票”。 这句话在意图技能中进行解析,返回结果里包含了此句话的意图名,以及包含的槽位等。

(3) 匹配对话状态

该意图解析结果与当前状态(state)下的所有transitions进行匹配。 因缺少必需信息(出发地、目的地、日期),程序与XML文件中定义的所有transition states进行匹配,选出最匹配项,并进入此状态。 上面例子为:缺少出发地。此时机器人会回复stimulate中的句子:请问您的出发地是哪里呢?

(4) 查询

当全部信息(槽位)填写完毕后,系统将会连接String url = "https://dev.rsvp.ai:5001/server",进入到“查询”状态。 此时可以调用外部程序查询机票信息。

例如用Python编写外部接口程序:

  • server.py 创建服务接口,读取GET的参数,将其传入py_sql.py中。
  • py_sql.py 连接数据库,并根据传入参数进行数据库数据插入和查询功能。 返回JsonArray形式的数据,由用户选择对应航班或进一步筛选(比如选择舱位、价格区间等),最后出票。 若控制导入数据的参数为True,将调用json2sql.py进行新数据导入。
  • json2sql.py 将数据导入数据库(去重)。

server测试

  1. 在resources程序中修改路由,如图,修改@Path

  2. 使用ngrok进行代理,方便本地调试。

并将回答服务连接到此代理。

运行StandaloneServer,进行测试。若出现以下信息,为成功。

  1. 在轻语平台进行测试

  2. 流程

程序流程与本地测试里写的无异。

部署

打war包。将Python文件、war包放入服务器,并启动Python、MySQL服务。 然后将轻语平台的回答服务的地址改为正确的服务器地址,即可正常使用。

高级功能

可以使用富回复格式:

list(可储存航班信息)

  • 功能:卡片列表回复,用于展示一组同类型的信息
  • 外观:可选横向滚动或竖向滚动,最多10个卡片
  • 交互:根据type值设定,用户可以上下或左右滚动列表,点击卡片上的按钮可以完成相应操作

quick_replies

  • 功能:针对当前上下文的即时快速回复,
  • 外观:以横向滚动按钮列表形式出现在输入框上方,
  • 交互:用户点选后消失,同时向对话接口发送postback中的文本,或者在默认浏览器中打开url中的地址

message

  • 功能:文本回复,
  • 外观:对话流中常规气泡,
  • 交互:展示

错误处理

  1. 根据解析结果,提取props问题。每一个prop都包含了.key与.value。需根据需要进行提取。
  2. 运行超时问题,要检查轻语平台与远程服务器的连接。
  3. fulfillment解析与URL解析结果有所不同。