/qa_on_flow

question and answer base flow

Primary LanguagePython

基于状态机和模块化的问答引擎

1. 总体介绍

在产品开发过程中,我们经常遇到一些问答交互场景,例如体检推荐场景中询问用户的健康信息和需求,在智能导诊和预问诊场景中询问患者的不适症状和相关信息,以及我们在很多产品的引导入口,经常遇到询问基本信息和爱好的地方,也属于问答交互场景。如下图所示分别为**人寿蛮牛健康的引导页面、**平安好医生的导诊页面

问答页面

在传统开发中,大多数此类产品功能的开发都采用硬编码的方式,即产品经理设计好状态图(或流程图),前端开发和后端开发按状态图进行硬编码。这样后期每一次需求调整,产品经理要修改设计,前端开发和后端开发要做对应代码开发。在实际场景中,需求是多变的,难免会多次修改需求;若每次需求的微调都会让前后端开发介入,会导致沟通协调的工作量巨大。

在我们提炼的技术框架中,可以直接把产品经理的状态图(或流程图)作为输入自动转换为代码,带来了工作模式的调整,大幅提高了需求的响应速度和响应效率。

而且在技术框架中采用了全面的模块化技术,大幅提高了开发效率,降低了后期的维护成本。

下面分别从两个方面进行介绍:状态机技术和模块化技术

2. 状态机技术

2.1. 状态机原理说明

问答过程可以抽象为状态机的运行过程,如下图所示: 状态机

1、用户打开界面,向后端发送api请求

  • flag=start

2、后端产生问题,返回问句,主要字段为:

  • flag=contine
  • question_seq: 问题编码
  • question_type:问题类型:多选项、单选项、输入项、身高、体重、症状列表,发生频率、持续时间
  • question_content: 问题内容
  • question_option:数组,前端显示的候选项列表
  • default_value: 默认值

3、用户对问题进行回答后,返回后端内容,主要字段为:

  • question_seq: 问题编码
  • question_anwser: 数组,用户填写或者选择的问题答案
  • all_answer: 字典,所有问题答案累加在answer里,作为最终问答结果

4、当后端收到用户回答后,计算下一个状态,若继续问句,则继续第2步;如果计算流程结束,则跳到第5步

5、结束流程,结束问答,此时的主要字段为:

  • flag=end
  • flow_retsult_type:流程结果类型,例如"预问诊结果"、"导诊结果"、"体检结果"
  • flow_result_detail:流程结果详细,当flag=end时,返回flow_retsult_type和flow_result_detail,前端根据type显示不同结果页面

整个问答引擎的核心只有一个API(例如路径为api/p/qa),前端发起事件获取后端响应,即用户回答问题给后端,后端计算返回下一个问题或者终点结果。上述前后端交互过程中的API字段定义如下表:

入参:
    question_seq: 当前的问题编号,如果是第一个问题,为空
    question_anwser: 当前问题的答案,为int或者string或者list或者对象
    all_anwser: 累计的问题答案
    flow_name: 流程名
    extend: 扩展内容,例如token等,用于登录用户信息验证等
出参:
    # 场景1、后端产生问题,返回问句,主要字段为:
    flag: contine
    question_seq: 问题编码
    question_type: 问题类型:多选项、单选项、输入项、身高、体重、症状列表,发生频率、持续时间
    question_content: 问题内容
    question_option: 数组,前端显示的候选项列表
    default_value: 默认值
    # 场景2、结束流程,结束问答,此时的主要字段为:
    flag: end
    flow_retsult_type: 流程结果类型,例如"预问诊结果"、"导诊结果"、"体检结果"
    flow_result_detail: 流程结果详细,当flag=end时,返回flow_retsult_type和flow_result_detail,前端根据type显示不同结果页面

2.2.状态图控制器

状态图控制器是问答引擎的核心,其处理过程如下:

  • 业务经理或者产品经理在processon上绘制完成业务流程图后,导出pos文件上传到程序指定目录(pos格式是ProcessOn的一种基于Json的开放格式,也是ProcessOn自己的格式,可以导出和导入使用)
    • 产品经理也可以使用其他的流程图制作工具,例如visio,导出VisioXML文档类似格式
  • 状态图控制器解析状态图的pos文件,提取节点、节点内信息、节点之间的连线、连线描述
    • 每个节点对应一个问题状态
    • 节点内的信息描述了该问题的内容、主键、类型(前端控件)、(后端)业务处理等
    • 节点之间的连线表示了问题之间的跳转关系
    • 连线描述表示跳转的逻辑表达式,支持and、or not 等逻辑表达
  • 状态图控制器侦听前端的请求,根据当前状态和事件切换到下一状态
  • 状态图控制器能够解析的状态图需要按照“描述规范”进行编写

2.3.状态图描述规范

  • 开始状态采用"Flowchat流程图"中的”开始/结束“,命名方式为"开始:流程名",其中‘流程名’是个变量,可以支持子流程调用
  • 结束状态采用"Flowchat流程图"中的”开始/结束“,命名方式为"结束:终点名",其中‘终点名’是个变量,表示采用的是哪个终点状态结果进行处理
  • 中间状态采用"Flowchat流程图"中的”流程“表示,格式如下:
    • 第一行为问句内容,例如"你的$性别$为?"、”请问您描述的症状发生多久了?“,其中$围起来的变量表示这个状态的主键
    • 第二行表示前端显示控件,例如 "单选项:X1、X2",“输入项:”,“自定义项:身高”等
    • 除第一行和第二行外,下面内容为可选项:
      • 主键:状态的主键名称,如果再第一行中用$标识,则不需要再单独定义
      • 前置处理 :相似症状推导,后端的业务处理模块,产生问题前调用
      • 后置处理:后端的业务处理模块,收到问答后调用,一般是进行值转换
      • 默认值: 前端显示时的默认值
  • 状态与状态之间的跳转逻辑,直接在中间的连线上用表达式描述
    • 变量名用 $围起来
    • 支持、 、=、=、=、contains等比较运算符
    • 支持and、or、not等逻辑运算符
  • 若状态与状态之间连线上没有条件,则表示默认跳转,为低优先级

下图是一个“健康APP引导流程”样例

健康APP引导流程

3.模块化技术

  • 整个问答引擎采用彻底的模块化原理
    • 前端显示问题内容,采用模块化前端显示控件,如:多选项、单选项、输入项、症状列表、症状时间等
    • 每个问题的后端逻辑,采用模块化业务处理,如:相似症状、年龄段处理
    • 所有问答结束后,后端采用模块化结果计算,前端进行模块化结果展示,如:预问诊结果、导诊结果、体检结果
    • 与第三方对接,支持模块化接口扩展,如:仁济掌医接口、健康静安接口、上海互联网总医院接口

3.1.前端显示控件的模块化

前端控件举例:

  • 单选项
  • 多选选
  • 输入项
  • 身高  
  • 体重
  • 日期选择

3.2.后端业务处理的模块化

后端业务处理细分为两种类型:前置处理和后置处理,分别表示产生问题前调用和回答结果后调用。在后端业务处理模块中,可以灵活引入各种算法模型,从而提供整个系统的智能化!

  • 年龄段处理:为了减少用户输入,让用户选择年龄范围,后台要把范围采样为某个年龄值
  • 相似症状推导模型:根据用户先前输入的症状和基础信息,通过算法推导出相似症状
  • 身高估算模型:根据年龄、性别等已知条件估算身高,尽量让用户少调整数值
  • 体重估算模型:根据年龄、性别、身高等已知条件估算体重,尽量让用户少调整数值

3.3.终点状态结果的模块化

所有问答结束后,后端采用模块化进行终点状态结果结算,前端进行模块化结果展示,如:

  • 预问诊结果
  • 导诊结果
  • 体检结果
  • 个性化推荐结果

3.4.与第三方对接的模块化

在真实场景中,存在下面场景:在进入问答系统之前,已经从第三方系统获取了用户基本信息,如姓名、年龄、身份证号、挂号流水号等信息,这些信息可以通过extend字段进行传递

上海仁济医院的extend定义:

extend_type: 上海仁济医院
sigh: 对身份证号、挂号流水号的加密信息

上海互联网总医院的extend定义:

extend_type: 上海互联网总医院
姓名: xx
性别: xx

技术总结

本模块用到的关键技术点:

  • 流程图解析与流程执行引擎
  • 表达式执行、规则执行引擎
  • 模块化封装、业务解耦、函数注册

4.总结语

当前人工智能的现状是呼声高,落地少,类似“只见人工,不见智能“,”有多少人工就有多少智能”这样的吐槽,不管行业内大家外笑而不语。

毛主席能称之为伟人,就在于其伟大的**,一个持久战**就可以应用在太多地方,在我们人工智能领域也一样适用。按其《论持久战》的观点,对于人工智能解决问题的能力,有两种观点都是需要纠正的,一种是"亡国论"认为人工智能解决不了啥问题,对其拒绝接受,远离之;另一种是"速胜论"认为人工智能啥都能解决,盲目制定目标,然后撞个头破血流。

对于一个问题的解决,既不能亡国论(不要讲什么智能、算法这些忽悠人的东西,只要手工给我做完就行),也不能速胜论(人都没想清楚的情况下,只要采用某个先进的算法就能短时间解决所有问题)。正确做法是要采用持久战的**,算法只是用来提高效率的工具,人要想清楚做什么,怎么做,人能做哪些东西,算法能做哪些东西,这样循序渐进人机配合,才可以真正解决问题,把事情做好。

在我们基于状态机的智能问答引擎中,前半部分的状态图(或流程图)可以帮助产品经理想清楚人可以做哪些工作,机器和算法可以做哪些工作;后半部分的模块化可以把各种智能算法有机融合到系统中,比如相似症状推导模型可以采用词向量、关联矩阵、SVD算法等,个性化推荐结果采用协同过滤、聚类、深度学习等,中间一些小的估算模型也可以很好提高用户的智能体验。

这样人工做一部分工作、机器和算法做一部分,整体组合起来,就是一个很好用的人工智能产品。

参考文档: