總目錄地址:AI 系列 總目錄 html
須要最新源碼,或技術提問,請加QQ羣:538327407android
個人各類github 開源項目和代碼:https://github.com/linbin524git
1、前言github
咱們都知道如今聊天對話機器是一個頗有意思的東西,好比說蘋果siri,好比說微軟的小冰。json
聊天對話機器的應用場景也很普遍,好比說:銀行的自助辦卡機器人、展會講解解說等等。服務器
咱們對機器人說句話,機器人從聽取,到語義識別,認知轉換,到最後調出咱們所想要的東西,這個過程看似簡單,其實內藏許多黑科技,讓咱們來一一解析一下。session
一、咱們對機器人說句話:我想看一下今天的天氣?app
技術實現:不管是語音、文字,機器首先要採集到咱們的問題,語音還須要語音轉換的一個過程,且內容轉換結果必須準確,不然就有點像不一樣語言體系的人在對話,有種雞同鴨講的感受,結果確定也是一個大坑了。異步
二、語義識別ide
技術實現:一般這個階段,已經將內容轉換爲一段文字,程序會對文字進行分詞,結合關鍵字截取拼接語義(這裏須要AI的訓練)
三、認知轉換
技術實現:上述的那就話中,今天是個關鍵詞,天氣是個關鍵詞, 在訓練庫中須要提煉詞槽,將可能語句儘量提供給機器人
四、調用結果
當認知轉換完成後,須要對關鍵詞進行規則判斷,好比說, 想看 + 今天+ 天氣,組成時候,自動調用查詢天氣接口
上述的結果,更多須要咱們對機器人進行訓練,讓它學習,要否則結果確定不是那麼友好的。
2、技術需求
經過文字輸入問題,動態理解轉化,識別內容,進行機器解答和語音提示。
PS:上述的需求基本能夠理解爲你叫機器人作一件事,機器人領悟,按照你的要求執行。
進階:能夠採用語音輸入,轉換爲文字,以後的序列同樣。(須要陣列麥克風)
3、技術選型
一、採用C# winform 做爲程序主題
二、採用win7 TTS 做爲語音朗讀功能
三、採用百度理解交互技術 UNIT 做爲識別基礎
本篇的重點在於如何對機器UNIT 進行配置與訓練(機器識別會理解錯誤,須要進行糾錯),最後的winform 只是調用結果顯示,不做爲重點關注。
4、實現
一、新建winform 窗體
二、添加TTS,引用System.Speech
三、進行 語音朗讀測試
SpeechSynthesizer voice = new SpeechSynthesizer(); //建立語音實例
voice.Rate = 2; //設置語速,[-10,10]
voice.Volume = 100; //設置音量,[0,100]
voice.SpeakAsync(「您好!」); //播放指定的字符串,這是異步朗讀
PS:有些win7 系統TTS 有問題,須要本身百度查找,下載TTS 進行安裝。目前上述支持中文,輸入英文,只會念字母,由於須要朗讀類別作轉換,詳細請百度speech 操做。
四、結合百度理解與交互技術
百度提供的sdk 目前只支持android 和IOS,但有提供http API,因此筆者採用C#實現了。
先去官網註冊成爲百度開發者。
(1) 建立應用
(2) 建立場景,場景編號是後面須要用到的
(3)新建單元,官方提供對話單元和問答單元,咱們選擇建立對話單元
(4)、對對話單元進行配置,新建詞藻
新建詞藻
詞藻詞典有自定義的,也有系統的,本文中選擇系統通用的。也能夠下載自定義模板,寫入本身的自定義詞典
這個對話單元中,有文本回復和執行函數,咱們這裏選文本回復
觸發的規則:會話規則中,上述的詞藻已填充,那麼文本內容纔會出現
保存完成,後再次新建對話單元,主要說明介紹咱們的公司
跳轉到數據中心,進行新建對話樣本
添加
依法將公司介紹關鍵詞添加
來的訓練與驗證板塊
輸入打開菜單,一開始輸入,可能獲得錯誤答案,你要 @UNIT 糾正意圖與詞槽,手動將關鍵詞和意圖、取詞、詞藻匹配上
完成後的結果:
(1)、
配置基本參數
/// <summary> /// 理解與交互技術UNIT /// </summary> public class ConfigUnit { /// <summary> /// Api key /// </summary> public static String clientId = ""; // 百度雲中開通對應服務應用的 Secret Key public static String clientSecret = ""; //場景Id public static string clientSceneId = ""; }
部分解析實體model
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace BaiduAIAPI.Model.UnitModel { public class UnitModel { public long log_id { get; set; } public string error_code { get; set; } public string error_msg { get; set; } public UnitResult result { get; set; } public bool IsSuccess { get; set; } public string returnSay { get; set; } } public class UnitResult { public string session_id { get; set; } public List<UnitAction_list> action_list { get; set; } public object schema { get; set; } public object qu_res { get; set; } } public class UnitAction_list { public string action_id { get; set; } public object action_type { get; set; } public object arg_list { get; set; } public object code_actions { get; set; } public float confidence { get; set; } public object exe_status { get; set; } public string main_exe { get; set; } public string say { get; set; } public object hint_list { get; set; } } /// <summary> /// 其他的model 還沒補充完整 /// </summary> public class UnitSchema { } }
錯誤信息定義
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace BaiduAIAPI.Type { public class BaiduUnitType { public static string GetErrorCodeToDescription(string errorCode) { string errorDecrition = ""; switch (errorCode) { case "1": errorDecrition = "服務器內部錯誤,請再次請求, 若是持續出現此類錯誤,請經過QQ羣(224994340)聯繫技術支持團隊。"; break; case "2": errorDecrition = "服務暫不可用,請再次請求, 若是持續出現此類錯誤,請經過QQ羣(224994340)或工單聯繫技術支持團隊。"; break; case "3": errorDecrition = "調用的API不存在,請檢查後從新嘗試。"; break; case "4": errorDecrition = "集羣超限額。"; break; case "6": errorDecrition = "無權限訪問該用戶數據。"; break; case "14": errorDecrition = "IAM鑑權失敗,建議用戶參照文檔自查生成sign的方式是否正確,或換用控制檯中ak sk的方式調用。"; break; case "17": errorDecrition = "天天請求量超限額。"; break; case "18": errorDecrition = "QPS超限額。"; break; case "19": errorDecrition = "請求總量超限額。"; break; case "100": errorDecrition = "無效的access_token參數,請檢查後從新嘗試。"; break; case "110": errorDecrition = "access token無效。"; break; case "111": errorDecrition = "access token過時。"; break; case "282004": errorDecrition = "請求參數格式不正確。"; break; case "282900": errorDecrition = "必傳字段爲空。"; break; case "282901": errorDecrition = "場景ID校驗失敗,請確認console中app和場景是否關聯了:https://console.bce.baidu.com/ai/#/ai/unit/app/list。"; break; case "282902": errorDecrition = "UNIT環境啓動中,請稍後再試;若是持續出現此類錯誤,請經過QQ羣(224994340)聯繫技術支持團隊。"; break; case "282903": errorDecrition = "UNIT系統異常;若是持續出現此類錯誤,請經過QQ羣(224994340)聯繫技術支持團隊。"; break; case "282000": errorDecrition = "服務器內部錯誤,若是您使用的是高精度接口,報這個錯誤碼的緣由多是您上傳的圖片中文字過多,識別超時致使的,建議您對圖片進行切割後再識別,其餘狀況請再次請求, 若是持續出現此類錯誤,請經過QQ羣(631977213)或工單聯繫技術支持團隊。"; break; default: errorDecrition = "未知的錯誤!"; break; } return errorDecrition; } } }
封裝的接口方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web.UI.WebControls; using AOP.Common; using BaiduAIAPI.Model.UnitModel; using BaiduAIAPI.Type; namespace BaiduAIAPI.UNIT { public class UnderstandingAndInteractiveTechnology { // unit對話接口 public static UnitModel Unit_Utterance(string token, string sceneId, string query) { UnitModel result = new UnitModel(); #region 基礎校驗 string error = ""; if (string.IsNullOrWhiteSpace(token)) { error += "token不能爲空!"; } if (string.IsNullOrWhiteSpace(sceneId)) { error += "場景編號不能爲空!"; } if (string.IsNullOrWhiteSpace(query)) { error += "詢問問題不能爲空!"; } if (!string.IsNullOrWhiteSpace(error)) { result.error_msg = error; return result; } #endregion string host = "https://aip.baidubce.com/rpc/2.0/solution/v1/unit_utterance?access_token=" + token; string str = "{\"scene_id\":" + sceneId + ",\"query\":\"" + query + "\", \"session_id\":\"\"}"; // json格式 var tempResult = HttpRequestHelper.Post(host, str); result=Json.ToObject<UnitModel>(tempResult); if (!string.IsNullOrWhiteSpace(result.error_code)) { result.error_msg = BaiduUnitType.GetErrorCodeToDescription(result.error_code); result.IsSuccess = false; } else { result.IsSuccess = true; result.returnSay = result.result.action_list[0].say; } return result; } } }
首先用單元測試結果:
using System; using BaiduAIAPI; using BaiduAIAPI.UNIT; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace AIAPIUnitTestProject.BaiduAIAPI { [TestClass] public class BaiduUnitTest { [TestMethod] public void TestChat() { var accessTokenModel = Access_Token.GetAccessToken(ConfigUnit.clientId, ConfigUnit.clientSecret); if (accessTokenModel.IsSuccess) { string queryString = "今每天氣怎麼樣?"; var tempUnitResult = UnderstandingAndInteractiveTechnology.Unit_Utterance(accessTokenModel.SuccessModel.access_token, ConfigUnit.clientSceneId, queryString); } } } }
肯定接口沒有問題,結合到咱們的Demo程序中,界面代碼以下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Speech.Synthesis; using BaiduAIAPI; using BaiduAIAPI.UNIT; using BaiduAIAPI.Model.UnitModel; namespace SpeechDemo { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { if (tb_YourSay.Text.Trim() == "") { MessageBox.Show("請你輸入你要說的話!"); return; } UnitModel result = new UnitModel(); var accessTokenModel = Access_Token.GetAccessToken(ConfigUnit.clientId, ConfigUnit.clientSecret); if (accessTokenModel.IsSuccess) { string queryString = tb_YourSay.Text.Trim(); result = UnderstandingAndInteractiveTechnology.Unit_Utterance(accessTokenModel.SuccessModel.access_token, ConfigUnit.clientSceneId, queryString); } else { result.returnSay = result.error_msg; } tb_RobotSay.Text = result.returnSay; SpeechSynthesizer voice = new SpeechSynthesizer(); //建立語音實例 voice.Rate = 2; //設置語速,[-10,10] voice.Volume = 100; //設置音量,[0,100] voice.SpeakAsync(result.returnSay); //播放指定的字符串,這是異步朗讀 } } }
結果展現
評價
理解和交互須要作大量的對話樣本和語言交互糾錯,才能夠實現相對比較精準的回答。