更聰明的電話語音機器人

有人說AI應用最重要的是工程實現,而不僅僅是算法,誠哉斯言。

電話語音機器人目前應用最多的是電話營銷,我接過幾個這樣的電話,挺傻的,基本聽不懂人話。

我也見過一些廠家的電話機器人界面,配置十分複雜,每個關鍵字要配置一個節點,存儲到數據庫,運行的時候關鍵字匹配,需要在數據庫裏做上百個sql查詢,查來查去,效率極低不說,靈活性反而大受限制。

我實現的電話語音機器人,就是解決上述兩個根本性問題,而且接口十分簡單。

其實,我們完全可以採用AI裏面語意描述的概念:“詞槽”。比如查天氣,需要的詞槽有日期(今天,明天,星期幾),城市。只有這兩個詞槽都填充了,纔可以完成查詢。

簡單說來,詞槽有這麼幾種類型:

const MENU_SLOT = 0;  // 菜單或選擇類型,最爲常見,需預先定義。
const AMOUNT_SLOT = 1;  // 數量
const MONEY_SLOT = 2;  // 金額
const TEXT_SLOT = 3;  // 普通文本輸入

詞槽的描述,我的解決方案是完全採用文本串,配置串可以存儲在ini文件或數據庫,也可以通過api傳入,舉個配置的例子(完全用文本描述),比如需要讓用戶說珠三角的幾個城市,差不多是json格式,請注意我加上的註釋:

slot0 = 
{

 "name" : "city",   // 詞槽的名字

 "type" : MENU_SLOT,   // 菜單類型

 "init" : {"請說一個珠三角城市", "你想去哪裏呢,廣州、深圳、中山、香港還是澳門?", "您可以從廣州、深圳、香港、中山或澳門確定一個城市", "說一個珠三角城市,區縣名也可以"}, 

 "keys" : {  // 關鍵字組

         {"深圳","福田","南山","羅湖","鹽田","龍崗","龍華","寶安","光明"},  // 第1組深圳,索引值默認爲0

         {"廣州","越秀","天河","番禺","增城","花都","海珠","白雲","黃埔"},  // 第2組廣州,索引值爲1

         {"香港","屯門","元朗","新界","九龍","中環","港島"},  // 第3組香港,索引值爲2

         {"澳門"},  // 第4組澳門,只有1個關鍵字,索引值爲3

         {"中山","小欖","東昇","石岐","三角"}  // 第5組中山,索引值爲4

     }

};
   
init 屬性相當於歡迎詞,用TTS(文本語音合成)自動播放出來。在多次交互中,系統會隨機選一個歡迎詞,同樣意思換不同說法,顯得有點智能。
keys 關鍵字後面的每一組關鍵字,具有相同的索引值,表示相同語義或相同的值。

如果用戶說“我在增城市”,系統將匹配到“增城”,返回詞槽的值是1,即廣州那組的索引值。

讓我們再來看看常見的外呼營銷例子:

營銷機器人爲了更逼真,需要播放真人錄音:

slot1 = 
{
 "name" : "sales", "type":MENU_SLOT, 
 "init" : {"voc/Invite-L7PGNX.wav"},   // 這個歡迎詞只有一個,請“林志玲”錄音,極盡溫柔勸說之能事
 "keys" : { 
{"沒興趣","不需要","不參加","不要","不用","騷擾","舉報","沒有","沒時間"},  // 索引值0,否定性質的關鍵詞
{"時間","時候","哪裏","地方","星期","考慮","意思","誰講", "看看"},   // 索引值1,中性關鍵字
{"可以","有興趣","還行","去吧","正要","好的","那行","那好","行吧", "好", "行"} // 索引值2,肯定
             } 
};

如果用戶說話做出反應,詞槽的返回值是下列之一:0否定;1中性,不明所以;2肯定。

應用層可以根據返回值做動作,如果用戶肯定,可以播放進一步聯繫方式(加微信),或者直接轉人工坐席;如果用戶否定,播放一個道歉語音然後掛斷;如果是中性,播放一個說明語音或詳細解釋的語音。

這樣的配置是不是既完備又簡單呢?

下面再說說算法。

有些廠家的電話語音機器人效果不好,用戶問起來,便統統推給ASR廠商:語音識別不準,我有什麼辦法?

現在大多采用免費的ASR接口,如百度、科大訊飛、騰訊、阿里,確實本身是免費的不可能爲你專門做優化,再說免費接口不能爲你的特定領域做訓練,識別效果馬馬虎虎也是無奈。

我對這個問題進行了深入研究,找到了解決方法。

一是儘量提高VAD檢測效果,儘量提交完整句子。

二是對文本匹配進行深入優化,漢字很多同音字,尤其是短語或單字,我找到識別的算法,準確度極高。(我還專門爲這個算法做了封裝成了一個動態庫)。這樣省去海量訓練或加很多同音關鍵字的麻煩。

語音系統支持標準SIP,系統運行在64位windows下,效果相當不錯。歡迎索取測試程序。

-------

附:

最新藍星際語音平臺REST接口:
v1.04 2018-04-04 [email protected]
-- 2018-4-20 v1.03  增加會議接口。
-- 2018-5-11 v1.04 增加錄音參數的含義,可進行無緩衝即時寫文件的錄音操作。
-- 2018-5-15 v1.05 增加PlayTTS可選參數charset=utf-8,可指定編碼。
-- 2018-6-30 v1.06 增加暫停放音PausePlay、恢復放音ResumePlay。
-- 2018-7-4   v1.10 增加智能機器人實現和接口


注意:大小寫敏感,方法名總是大寫字母開頭,參數名總是小寫字母開頭。


一、語音平臺作爲服務器:
1、呼叫相關:
1.1. 撥號呼叫:方法Dial:主叫號碼,被叫號碼
       返回:id -相當於通道標識


請求URI樣例:
ttp://172.16.110.140:8000/Dial
請求消息樣例:
{"caller":"4008123","callee":"13902912345"}
返回消息樣例:
{"resultCode":"0","resultContext":"","id":"12"}




1.2. 對來電應答:方法Answer:id
--此方法暫時不用。


1.3. 掛斷通話:方法Hangup:id
請求URI樣例:
ttp://172.16.110.140:8000/Hangup
請求消息樣例:
{"id":"12"}
返回消息樣例:
{"resultCode":"0","resultContext":""}




1.4. 查詢通道狀態:方法GetState: id
       返回:state: 0-空閒,1-通話中,2-外呼振鈴中,3-來電振鈴中
--此方法暫時不用。


2、放音操作
2.1. 放音:方法Play:id, file
    注意:路徑請勿使用反斜槓,使用順斜槓/,參見後面樣例。
     ——如果上一次放音沒有結束,本次調用將自動停止上一次放音,然後開始本次放音
請求URI樣例:
ttp://172.16.110.140:8000/Play
請求消息樣例:
{"id":"12","file":"d:/voc/welcome.wav"}
返回消息樣例:
{"resultCode":"0","resultContext":""}




2.2. TTS方式放音:PlayTTS:id,text-字符串, [charset=utf-8]
注意:如未指定charset=utf-8,默認中文請使用國標碼
請求URI樣例:
ttp://172.16.110.140:8000/PlayTTS
請求消息樣例:
{"id":"12","text":"你的問題我們已經知道了,謝謝!"}
返回消息樣例:
{"resultCode":"0","resultContext":""}
如果是utf8之請求消息樣例:
{"id":"12","text":"你的問題我們已經知道了,謝謝!","charset":"utf-8"}


2.3. 停止放音:方法StopPlay:id
請求URI樣例:
ttp://172.16.110.140:8000/StopPlay
請求消息樣例:
{"id":"12"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


2.4. 暫停放音:方法PausePlay:id
----暫停後可用ResumePlay方法恢復放音
請求URI樣例:
ttp://172.16.110.140:8000/PausePlay
請求消息樣例:
{"id":"12"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


2.5. 恢復放音:方法ResumePlay:id
----恢復被PausePlay暫停的放音,從上次暫停的地方繼續播放
請求URI樣例:
ttp://172.16.110.140:8000/ResumePlay
請求消息樣例:
{"id":"12"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


3、錄音操作
3.1. 開始錄音:方法StartRec:id, file, isVad=[0-不檢測對方說話一直錄音直到掛斷或調用停止錄音,1-錄音過程進行活動語音檢測,檢測結果及時上報,2-無緩衝大文件錄音]
    注意:路徑請勿使用反斜槓,使用順斜槓/,參見後面樣例。
      ——參數file:基本文件名,當有多個產生時,系統會自動加上後綴;如果文件已經存在,則會被覆蓋
     所有file參數務必帶上id,如下例:
請求URI樣例:
ttp://172.16.110.140:8000/StartRec
請求消息樣例:
{"id":"12","file":"d:/rec/r12","isVad":"1"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


3.2. 停止錄音:方法StopRec:id
請求URI樣例:
ttp://172.16.110.140:8000/StopRec
請求消息樣例:
{"id":"12"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


4、會議
說明:轉坐席相當於兩路橋接(外線通道和坐席通道),即兩方會議,外線通道和坐席通道加入相同的一個會議後,雙方就可以通話了。
當然,更多的通道也能加入,構成真正的多方語音會議。


4.1. 加入會議:方法JoinConf:id, confName, isListen=[1,只聽方式加入,如班長監聽功能; 0,正常方式加入,可說可聽]
      ——參數confName:會議名,標識當前會議,要有唯一性。
     將通道id加入到會議confName。
如下例:
請求URI樣例:
ttp://172.16.110.140:8000/JoinConf
請求消息樣例:
{"id":"12","confName":"20180420_131201_12","isListen":"0"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


4.2. 退出會議:方法ExitConf:id
     將通道id退出會議。本方法不是必須,通道掛斷會自動退出會議。
如下例:
請求URI樣例:
ttp://172.16.110.140:8000/ExitConf
請求消息樣例:
{"id":"12"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


4.3. 對會議放音:方法PlayConf:id,confName, file
    注意:路徑請勿使用反斜槓,使用順斜槓/,參見後面樣例。
     ——如果上一次會議放音沒有結束,本次調用將什麼也不幹
    注意:本方法放音全體成員均可聽到。某通道加入會議後,2.1.放音方法Play仍然可用,但Play只對id通道進行放音,會議的其它成員聽不到。
請求URI樣例:
ttp://172.16.110.140:8000/PlayConf
請求消息樣例:
{"id":"12","confName":"20180420_131201_12","file":"d:/voc/welcome.wav"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


4.4. 停止對會議放音:方法StopPlayConf:id,confName
請求URI樣例:
ttp://172.16.110.140:8000/StopPlayConf
請求消息樣例:
{"id":"12","confName":"20180420_131201_12"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


4.5. 對會議錄音:方法RecConf:id,confName, file
    注意:路徑請勿使用反斜槓,使用順斜槓/,參見後面樣例。
    注意:某通道加入會議後3.1.開始錄音方法StartRec仍然可用,但StartRec只對id通道的說話進行錄音,不會錄進其他成員說話的聲音。
請求URI樣例:
ttp://172.16.110.140:8000/RecConf
請求消息樣例:
{"id":"12","confName":"20180420_131201_12","file":"d:/voc/rec12.wav"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


4.6. 停止對會議錄音:方法StopRecConf:id,confName
請求URI樣例:
ttp://172.16.110.140:8000/StopRecConf
請求消息樣例:
{"id":"12","confName":"20180420_131201_12"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


5、語音機器人
需要預先配置好AI.ini,並獲取相關模塊的授權。
本系統會字段自動執行相關流程,放音並獲取對方說話送至百度asr服務器進行識別,然後進行AI匹配。
AI結果將報告返回。
5.1. AI流程請求:方法AI: id, slotName-詞槽名稱,需預先在AI.ini配置好。
一般在外呼對方摘機後調用,或收到來電應答後調用。
請求URI樣例:
ttp://172.16.110.140:8000/AI
請求消息樣例:
{"id":"12","slotName":"city"}
返回消息樣例:
{"resultCode":"0","resultContext":""}
{"resultCode":"-1","resultContext":"slot not found"}




二、語音平臺作爲客戶端:
1、報告通道狀態變化:方法OnState:id, state=[-1-對方掛斷, 1-接通,2-外呼振鈴, 3-有來電],callerId-主叫號碼,calleeId-被叫號碼
請求URI樣例:
ttp://172.16.110.140:8020/OnState
請求消息樣例:
{"id":"12","state":"1","caller":"8888333","callee":"13902912345"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


2、報告VAD(語音活動檢測)結果:方法OnVad:id,file,vadVal=[1偵測到說話,2偵測到說話結束(靜音)]
請求URI樣例:
ttp://172.16.110.140:8020/OnVad
請求消息樣例:
{"id":"12","vadVal":"2","file":"d:/rec/r12_1_2_3"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


3、報告DTMF按鍵:方法OnDtmf:id,dtmf=[可能的值:0-9,*,#]
請求URI樣例:
ttp://172.16.110.140:8020/OnDtmf
請求消息樣例:
{"id":"12","dtmf":"1"}
返回消息樣例:
{"resultCode":"0","resultContext":""}


4、報告機器人AI執行結果: 方法OnAI: id, resultIndex-匹配到詞槽關鍵字組的下標, retsultKey-匹配到的關鍵字, inputTxt-用戶說的原始內容文本
請求URI樣例:
ttp://172.16.110.140:8020/OnAI
請求消息樣例1:
{"id":"12","resultIndex":"1", "resultKey":"白雲", "inputTxt":"白雲區附近"}
請求消息樣例2:
{"id":"12","resultIndex":"-100", "resultKey":"time out", "inputTxt":""}
請求消息樣例3:
{"id":"12","resultIndex":"-1", "resultKey":"not match", "inputTxt":"河水東區啊"}


返回消息樣例:
{"resultCode":"0","resultContext":""}




注:暫不提供放音結束的報告,應用層能夠根據文件長度估算出放音時長。


三、配置:
1、Web服務端口
2、應用層Web服務地址和端口


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章