拙文“更聪明的电话语音机器人”解决了电话语音机器人的两个痛点,即模糊识别和关键词配置,但从实际的效果看,关键词(词槽)配置还是简单了一些,实际应用需要将词槽串接起来。经过改进后的例子如下:
cfg = """ {
"init":{"voc/welcome1.wav","voc/welcome2.wav",},
"keys":{
{{"额度","多少"}, "voc/quota.wav", 0, "额度解释"},
{{"资料","证件","资质","抵押","信用"},"voc/info.wav", 0,"所需资料"},
{{"银行","中行","建行","平安银行","农行","工行","招行"},"voc/banks.wav",0,"银行情况"},
{{"利息","利率"},"voc/interest.wav",0,"利率情况"},
{{"没兴趣","讨厌","投诉","骚扰","不需要","不用了"}, "voc/Sorry.wav", 1, "否定"},
{{"好的","有的","了解","可以","行啊","好啊","正好","好吧"}, "work_or_buss",2,"肯定"} }
} """;
LxjWordSlotAdd("main", cfg); // 词槽名=main
重点的改进在关键字节点,增加了额外的3个值:{{关键词列表}, "动作", flag, "说明"}
其中“动作”:可以是文件放音或TTS合成放音、或下一个词槽名;
flag:0表示不返回,播放tts或语音文件; 1播放后返回; 2转到下一个词槽
“说明”:相当于对节点的一个文字描述
现在可以解释上面的例子了,进入main词槽,随机选择播放welcome1.wav或welcome2.wav后,你可以说话打断,如果你说的话中带有“额度”,则系统会播放“quota.wav”,即解释实际的额度是多少。因为flag值配成1,播完后还是等你说话,并不会退出这个词槽循环。
同样,如果你说“要什么资料”或“利率怎么样”或“支持什么银行”,AI会给你对应的回答。但如果系统捕获到你说的关键字是“没兴趣”“讨厌”,系统会播放抱歉语音,然后退出循环,词槽的值填充为“否定”。如果捕获到“好的”“可以”,系统则将这个词槽填充为“肯定”的值,然后进到下一个词槽"work_or_buss"--询问你是做生意还是上班。
cfg = """ {
"init":{"voc/work_or_buss.wav"},
"keys":{
{{"上班","工作","打工"},"is_has_property" ,2,"上班"},
{{"生意","公司","开店","开工厂","开厂"},"is_has_property" ,2,"做生意"}
}
} """;
LxjWordSlotAdd("work_or_buss", cfg); // 配置调查词槽"work_or_buss":做生意还是上班,
// 出口会到询问有没有房产的词槽"is_has_property"
这个调查词槽就简单了,按要求回答后填充值,然后转到下一个词槽,调查你有没有房产。
cfg = """ {
"init":{"voc/has_property.wav"},
"keys":{
{{"没有"},"to_agent" ,2,"否定"},
{{"有"},"to_agent" ,2,"肯定"}
} } """;
LxjWordSlotAdd("is_has_property", cfg); // 配置调查词槽"is_has_property":有没有房产,
// 出口会到转接客服经理词槽"to_agent"
cfg = """ {
"init":{"voc/goto_agent.wav"},
"keys":{
{{"不用","算了", "下次吧","不需要"},"voc/Sorry.wav" ,1,"否定"},
{{"可以","好","行"},"voc/wait.wav" ,1,"肯定"}
} } """;
LxjWordSlotAdd("to_agent", cfg); // 配置转坐席词槽"to_agent":可以转客服经理吗?
最后这个词槽,是真正的出口,客人说“可以”,放音后将返回应用层,让应用层去转坐席了。
如果你想体验实际的效果,请下载:“蓝星际电话语音机器人”,5路,可免费使用1周。
除了上述改进,新版本组合使用了更先进的WebRTC之VAD算法和我自己实现的VAD算法,效果颇佳。
----
进一步更新,增加了混合放音、外部变量和内部变量:
语音播放串的增强和扩展,格式说明:
1、单纯的语音文件,有".wav"串: "voc/welcome.wav"
2、单纯的文字内容,用TTS合成后播放 "您好,我们这边是做什么什么的。。。"
3、组合语音和文字,注意用^号分隔(^号本身不常见,不会出现在TTS里面): "voc/welcome.wav^7.58元^voc/end.wav" 表示先播放welcome.wav,然后TTS合成播放7.58元,然后播放end.wav文件。
4、外部变量的使用:
使用组合符号下划线包围起来的符号如"_name_"表示变量,然后进行替换扩展 便于播放应用层在运行时确定的内容,比如客人欠费额,地址、电话号码之类: "_welcome_";
对于脚本语言,这样做: 定义好数组:
vars["welcome"] = "voc/welcome.wav^7.58元^voc/end.wav"; AIInit("main", 100, vars);
对于SipServerApi,这样调用:
const char* varsStr =
"\"welcome\":\"voc/welcome.wav^7.58元^voc/end.wav\",\"name\":\"Bill\",\"Year\":\"2018\",\"File\":\"voc/772.wav\"";
LxjSipAIDoing(1, "city", 100, varsStr);
AI引擎会在播放时会对找到对应的模板变量并进行替换
5、内部变量,有时候可能需要复述一下客人说的话,或匹配的结果 用下划线开头的预先定义的变量,如"__txt_" 比如客户刚才说了什么:
_txt = ”客人最后说的一句话“
_key = "客人最后说的这句话匹配到的关键字"
_node = "客人最后说的这句话匹配到的节点描述" 例: "您说的是__txt_,匹配到:__node_,谢谢"