顶顶通呼叫中心中间件(mod_cti基于FreeSWITCH)-电话机器人话术引擎说明

电话机器人话术引擎说明

介绍

介绍请看这个页面 http://www.ddrj.com/smartivr/robot.html
和smartivr接口的区别,smartivr接口只实现了把ASR识别结果提交给http接口进行处理,根据http接口返回的动作执行放音等操作。
新一代电话机器人接口实现了话术解析引擎,可以不依赖外部接口直接完成整个机器人对话过程。

开始执行流程

<action application="cti_robot" data="flowname"/>
<action application="set" data="park_timeout=3600000"/>
<action application="park"/>
  • flowname 流程名字,不需要.josn后缀

流程执行步骤记录

CREATE TABLE `conversation` (
`createtime` DATETIME NULL DEFAULT NULL COMMENT '记录生成事件',
`callid` VARCHAR(50) NULL DEFAULT NULL COMMENT '通话ID' COLLATE 'utf8_unicode_ci',
`current_appid` VARCHAR(50) NULL DEFAULT NULL COMMENT '当前执行APPID' COLLATE 'utf8_unicode_ci',
`sequence` INT(11) NULL DEFAULT NULL COMMENT '序列号',
`current_flowid` VARCHAR(50) NULL DEFAULT NULL COMMENT '当前流程ID' COLLATE 'utf8_unicode_ci',
`input_type` INT(11) NULL DEFAULT NULL COMMENT '输入类型0:TEXT 1:DTMF 2:COMPLETE 10:CREATE 11:DESTORY',
`input_args` VARCHAR(1024) NULL DEFAULT NULL COMMENT '输入参数' COLLATE 'utf8_unicode_ci',
`input_nlp_args` VARCHAR(50) NULL DEFAULT NULL COMMENT 'nlp处理后的参数' COLLATE 'utf8_unicode_ci',
`input_start_time` DATETIME NULL DEFAULT NULL COMMENT '输入开始时间',
`input_duration` INT(11) NULL DEFAULT NULL COMMENT '输入持续时间',
`matching_method` INT(11) NULL DEFAULT NULL COMMENT '匹配方法0:mismatch 1:boot 2:regex 3:full 4:any',
`matching_condition` VARCHAR(256) NULL DEFAULT NULL COMMENT '匹配表达式' COLLATE 'utf8_unicode_ci',
`matching_keyword` VARCHAR(50) NULL DEFAULT NULL COMMENT '匹配关键词' COLLATE 'utf8_unicode_ci',
`response_type` INT(11) NULL DEFAULT NULL COMMENT '响应类型 1:flow 2:kb 3:mismatch',
`response_description` VARCHAR(50) NULL DEFAULT NULL COMMENT '响应描述' COLLATE 'utf8_unicode_ci',
`response_id` VARCHAR(50) NULL DEFAULT NULL COMMENT '响应的FlowID,或者PromptID' COLLATE 'utf8_unicode_ci',
`response_action` VARCHAR(50) NULL DEFAULT NULL COMMENT '响应动作' COLLATE 'utf8_unicode_ci',
`response_args` VARCHAR(2048) NULL DEFAULT NULL COMMENT '响应参数' COLLATE 'utf8_unicode_ci',
`repetition` INT(11) NULL DEFAULT NULL COMMENT 'kb:rompt重复播放次数 ,mismatch:连续未匹配次数 flow:已经执行次数',
`potential` VARCHAR(50) NULL DEFAULT NULL COMMENT '意向ID' COLLATE 'utf8_unicode_ci',
`record` VARCHAR(260) NULL DEFAULT NULL COMMENT '录音' COLLATE 'utf8_unicode_ci'
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;
  • createtime 记录生成事件

  • callid 通话ID

  • current_appid 当前执行APPID

  • sequence 序列号,当前执行动作的次数

  • current_flowid 当前流程ID

  • input_type 输入类型0:TEXT 1:DTMF 2:COMPLETE 10:CREATE 11:DESTORY 20:FLOWID 30:ERROR

    • TEXT asr转换后的文字
    • DTMF 按键
    • COMPLETE 动作执行完成
    • CREATE 进入流程创建上下文(input_args是话术名字:version[话术文件.json可以设置一个version字段设置话术版本])
    • DESTORY 离开流程销毁上下文
    • FLOWID 流程ID,比如通过知识库或者return动作切换流程(input_args:如果空就是返回父流程,否则就是流程ID)
    • ERROR 错误信息,比如切断流程失败(input_args:发生错误的流程ID,matching_condition:错误的流程ID,response_description:错误信息)
  • input_args 输入参数,input_type TEXT时asr识别结果,DTMF时按键内容。COMPLETE是完成输入参数

    • asr识别结果前缀说明
      • 前缀F:一句话识别完成
      • 前缀E:ASR错误
      • 前缀S:用户还在说话,实时识别中。
    • dtmf按键内容
      • d:未匹配到终止符
      • D:已经匹配到终止符
    • 完成输入参数
      • DONE() 输入完成,DONE(F:识别内容1F:识别内容2)
      • TIMEOUT() 输入超时了,TIMEOUT(F:放音时候的识别内容S:超过最大说话时间了)。如果没检测到声音就是TIMEOUT()。TIMEOUT(S:识别内容)这样的也代表一次ASR调用,也要对ASR进行计费。
      • ERROR() 遇到错误
      • BREAK() 外部程序执行了uuid_break
    • HANGUP() 挂机了,如果用户说完就挂机了,识别结果会HANGUP(F说话内容)推送。
  • input_nlp_args nlp 接口返回的数据

  • input_start_time 输入开始时间,比如说话开始时的时间

  • input_duration 输入持续时间 ,比如说话的持续时间

  • matching_method 匹配方法0:mismatch 1:boot 2:regex 3:full 4:any 5:flowid

    • mismatch 未匹配到条件
    • boot 创建流程时从start进入第一个引导结点(开场白)
    • regex 正则表达式匹配
    • full 完整的关键词匹配
    • any 任意匹配(就是关键词设置为any)
    • flowid 匹配到流程ID
  • matching_condition 匹配表达式 ,就是被匹配成功的关键词,或者正则表达式

  • matching_keyword 匹配关键词,就是text中被匹配中的部分

  • response_type 响应类型 0:none 1:flow 2:kb 3:mismatch 4:switchflow 5:timeout 6:globalflow 7:brotherflow 8:noiserule 9:disablebreak

    • none 没反应动作
    • flow 匹配到子流程
    • kb 匹配到知识库
    • mismatch 执行未匹配放音
    • switchflow 切换流程节点
    • timeout 执行无输入放音
    • globalflow 匹配到全局流程
    • brotherflow 匹配到源流程的子流程
    • noiserule 匹配到噪音规则
    • disablebreak 匹配到禁止打断。
  • response_id 响应的FlowID,或者PromptID

  • response_action 响应动作,执行那个FS的APP

  • response_args 响应参数,APP的参数

  • repetition kb:prompt重复播放次数 ,timeout和mismatch:连续未匹配次数 flow:已经执行次数

  • potential 意向ID

  • record 当前输入的录音文件,text输入的时候才有,一个动作(一次放音)的多次说话会记录到一个录音文件。

根据CDR配置,流程执行步骤可以记录到数据库或者redis

如果配置为记录到数据库,input_type 等于DESTORY是 即流程执行结束,可以通知到http接口或者redis的list或者channel。

{
"robot": {
/*机器人对话的执行流程记录*/
"record": {
通知包含的通道变量
"notify_fields": [ "caller_id_name", "destination_number", "call_source", "source_name", "cti_dial_number" ],
/*机器人交换记录是否推送到redis的channel和list*/
"redis": {
"channel": "",
"list": "",
},
"database": {
/*机器人的交换记录插入数据库的那个表*/
"table": "conversation",
},
"log": false //是否输出到redis的JSON和输出SQL。
},
/*机器人对话交互的统计数据*/
"statistic":
{
/*是否推送到redis的channel和list*/
"redis": {
"channel": "",
"list": ""
},
"database": {
/*插入数据库的那个表*/
"table":"classify"
},
"log": false //是否输出到redis的JSON和SQL到日志。
},
"nlp": {
"debug": false //是否输出机器人引擎调试日志,比如要输出正则表达式匹配过程,可以设置为true
},
"httpflow": {
"usecurl": false, //默认使用顶顶通实现的http库,修改成true,使用curl库执行http请求
"retries": 2, //http请求失败时重试次数
"connecttimeout": 3000, //连接超时
"responsetimeout": 10000 //等待响应超时
},
"event_after_hangup":true // 挂断之后是否继续处理事件,如果不开启 用户说话之后没等ASR识别完成就挂机,会丢失识别结果,开启后会有complete事件参数HANGUP(F说话内容)。
}
}

机器人对话交互的统计数据

用于意向分析和比如客户分类

CREATE TABLE `classify` (
`callid` VARCHAR(50) NOT NULL,
`talk_time` INT(11) NULL DEFAULT NULL,
`respond_count` INT(11) NULL DEFAULT NULL,
`positive_respond_count` INT(11) NULL DEFAULT NULL,
`passive_respond_count` INT(11) NULL DEFAULT NULL,
`intentional_count` INT(11) NULL DEFAULT NULL,
`unintentional_count` INT(11) NULL DEFAULT NULL,
`trigger_kb` INT(11) NULL DEFAULT NULL,
`trigger_global_flow` INT(11) NULL DEFAULT NULL,
`proactively_hangup` INT(11) NULL DEFAULT NULL,
`label_result` VARCHAR(50) NULL DEFAULT NULL,
`label_hit_id` VARCHAR(50) NULL DEFAULT NULL,
`label_hit_type` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`callid`)
)
  • talk_time 通话时长
  • respond_count 回答次数
  • positive_respond_count 积极回答(对所以命中关键词权重大于0的进行求和)。举例:比如肯定关键词权重都设置1,那么积极回答的值就是肯定回答了多少次。
  • passive_respond_count 消极回答(对所有命中关键词权重小于0的进行求和然后取绝对值)。举例:比如否定关键词权重都设置-1,那么消极回答的值就是否定回答了多少次。
  • intentional_count 有意向节点(对所有执行节点意向大于0的进行求和)。举例:比如有意向的节点意向都设置1,那么这个值就是执行了多少个有意向的节点。
  • unintentional_count 无意向节点(对所有执行节点意向小于0的进行求和然后取绝对值)。举例:比如无意向的节点意向都设置-1,那么这个值就是执行了多少个无意向的节点。
  • trigger_kb 触发全局流程次数
  • trigger_global_flow 触发全局流程次数
  • proactively_hangup 机器人主动挂断设置为1,否则设置为0
  • label_result 分类结果
  • label_hit_type 分类结果的类型
    1. 流程直接设置的分类(label_hit_id为设置分类的的流程ID)
    2. 知识库直接设置的分类(label_hit_id为设置分类的知识库ID)
    3. 根据配置规则分类(label_hit_id为命中的分配配置规则ID)

NLP接口

全局配置设置了NLP接口地址,并且节点配置了FLOWID,那么会调用NLP接口进行处理。

NLP接口原理,话术引擎把输入的数据和需要匹配的关键词发送给NLP接口,由NLP接口返回匹配命中的关键词。

请求参数

{
"flowid": "F1",
"nlpid": "1",
"callid": "58b0733b-8a80-4fdc-860b-ad7e5bb85fbe",
"flowkeywords": "o%7Chello%7Cok%7Cyes%7Cno%7Cwo%7Cxuhuaiyi",
"kbkeywords": "lixi%7Cgongs%7Cnali%7Chello%7Cok%7Cyes%7Cno",
"input": "text",
"text": "SHello%20hello"
}
  • flowkeywords 所有子流程的所有关键词

  • kbkeywords 关联知识库的所有关键词

  • input 输入类型

  • text 输入参数

NLP接口返回数据

{
"keyword":"输入结果匹配到的关键词",
"description":“描述”
}

话术编辑

请看这个页面 http://www.ddrj.com/smartivr/robot.html ,用户可以设计自己的话术编辑界面,只需要按照话术脚本格式生成JSON文件就可以。

话术脚本

{
"flow": {
/*节点ID*/
"F1": {
/*节点执行的动作*/
"action": "cti_play_and_detect_speech",
/*动作参数*/
"argument": "'1' '' '' '0' '' '' '' '' '' '' ''",
/*节点位置信息*/
"position": {
"x": 2499,
"y": 156
},
/*nlp ID*/
"nlpid": "",
/*节点描述*/
"description": "描述",
/*节点放音文件列表*/
"playbacks": [
"测试声音"
],
/*子节点信息*/
"subflow": {
/*子节点ID*/
"F3": {
/*进入字节点的条件*/
"condition": {
/*ASR识别到关键词*/
"text": [
"any"
],
/*动作执行完成*/
"complete": [
"any"
],
/*DTMF输入按键*/
"dtmf": [
"any"
]
}
}
},
/*节点重复执行是放音,用来替换playbacks配置*/
"replaybacks": [],
"filter": {
"text": "S",
"dtmf": "none"
},
/*知识库返回时放音*/
"kbplaybacks": [
"测试声音"
],
/*未匹配到关键词时放音*/
"mismatchplaybacks": [
"不好意思,我没听清!"
],
/*未匹配到关键词放音次数*/
"mismatchrepetition": "2",
/*关联的知识库ID*/
"kb": "C1",
/*节点最大重复进入次数*/
"repetition": "",
/*节点的意向信息*/
"potential": ""
}
}
}

知识库

{
"kb": {
/*分类ID*/
"C1": {
/*分类名字*/
"name": "常见问题回答",
/*分类下面的条目*/
"prompts": [
"P1"
],
"description": ""
}
},
"prompt": {
/*条目ID*/
"P1": {
/*条目名字*/
"name": "公司介绍",
"ref": 2,
/*最大重复执行次数*/
"repetition": "2",
/*进入知识库的关键词*/
"keyworks": [
"谁",
"哪里",
"公司"
],
/*进入后的放音文件*/
"playbacks": [
"放音测试"
],
/*意向等级*/
"potential": "7",
/*切换到流程 可以配置流程ID,或者当前流程的匹配关键词,"text:"前缀匹配子流程的文本输入,"DTMF:"前缀匹配子流程的DTMF输入,"complete:"前缀匹配子流程的完成输入*/
"switchflow":"",
"description": ""
}
}
}

同义词

{
"synonym": {
/*分类*/
"肯定词": [/*同义词列表*/
"是",
"好",
"要",
"没错",
"有",
"对"
],
"否定词": [
"不",
"没"
]
}
}

全局配置

/*配置tts和asr默认配置*/
"global": {
"voicelist": [],
"defaultvoice": "",
"voicedir": "",
"ttsurl": "http:\/\/180.76.224.191:9989\/tts",
"ttsengine": "",
"ttsconfig": "",
"ttsvolume": 0,
"ttsspeechrate": 0,
"ttspitchrate": 0,
"interrupt": "2",
"asrproxy_addr": "180.76.224.191:9988",
"vad_min_active_time_ms": "150",
"vad_max_end_silence_time_ms": "800",
"wait_speech_timeout_ms": "5000",
"max_speech_time_ms": "20000",
"hot_word": "",
"asr_params": "{\"group\":\"default\"}",
"nlpurl": "",
"vad": "0",
"vad_mode": "0",
"vad_filter": "0.3"
},

tts接口

等待完成

话术流程存入redis

fs启动的时候会自动同步cti_robot_flow和cti_robot_flow@domain 2个哈希表里的话术流程,到fs话术目录,然后自动加载。

cti_robot_flow和cti_robot_flow@domain的区别,cti_robot_flow@domain指定的domain的fs才加载,cti_robot_flow连接这个redis的所有fs都会加载,用于群集模式。

  • key 流程名称
  • value 流程的json内容

cti_robot_flow改变通知

cti_robot_flow改变PUBLISH 通知到config@all [通道] ,cti_robot_flow@domain改变PUBLISH 通知到config@domain[通道],先修改hash表内容,然后推送通知,fs收到通知会自动同步话术脚本到本地,然后加载。

{
"type":"config_change",
"table":"cti_robot_flow",
"key":"t1"
}