在本篇部落格中,我們将會學習到零代碼情況下,如何利用已有的技術建立自己的知識問答系統,這種系統的可以廣泛适用于學校、企業、客服、政府公開資訊等領域,代替傳統的電話咨詢、電子郵件溝通等高人工負荷的方式。
建立知識庫
什麼叫QnA Maker?
知識庫,就是人們總結出的一些曆史知識的集合,存儲、索引以後,可以被友善的檢索出來供後人查詢/學習。QnA Maker是用于建立知識庫的工具,使用 QnA Maker,可以根據 FAQ(常見問題解答)文檔或者 URL 和産品手冊等半結構化内容打造一項問題與解答服務。可以生成一個問題與解答模型,以便靈活地應對使用者查詢,即使用者不必輸入精确的查詢條件,而是提供以自然對話方式受訓的機器人來響應。
下圖中是知識庫與Bot Service的結合使用架構圖:
與"半結構化資料"并列的是"結構化資料"和"非結構化資料",其中結構化資料可以用關系式資料庫來解決,非結構化資料用搜尋引擎技術來解決。實際上搜尋引擎就是把散落在網際網路各個角落的非結構資訊變成半結構化或結構化資訊。
不同于搜尋引擎,本文介紹的基于半結構化資料的QnA系統實作方式,是基于小規模資料量的,比如Million級别,而搜尋引擎的技術要進階很多,因為要面對Billion級别的資料。但是從原理上講,大家可以管中窺豹可見一斑。
在Azure中申請QnA Maker服務
用MSA登入Azure門戶,點選"建立資源",然後點選"AI + Machine Learning":
在下圖中點選"檢視全部":
在下圖中點選"更多:"
在下圖中點選"QnA Maker":
在下圖中的有紅色*的輸入框中,輸入必要的資訊,比如在Name中輸入" SchoolQASystem":
點選"建立"後,稍等一會兒,會得到以下通知消息:
小提示:可以點選"固定到儀表闆",友善後續查找。
至此,我們的QnA服務已經申請好了,下一步是建立知識庫,填寫資料。
在QnA Maker網站上建立知識庫
用Edge浏覽器打開https://www.qnamaker.ai,登入自己的MSA賬号。如果是第一進入該網站,你的My knowledge bases将會是空白頁,點選Create a knowledge base來建立自己的第一個知識庫:
小提示:這裡用的MSA賬号應該與申請認知服務的MSA賬号相同。
STEP 1我們已經做過了,現在在STEP 2中從下拉清單中選擇自己的相關資訊:
在STEP 3中填寫一個知識庫的名字,比如SchoolQASystemKB:
在STEP 5中點選"Create your KB"來建立知識庫:
小提示:STEP 4可以運作使用者通過提供一個靜态網頁或者一個固定格式的檔案,來自動提取問題和答案。
稍等一會兒,進入如下頁面:
我們以學校中常用的一些問答資訊為例,點選"+ Add QnA pair"填寫如下資料:
當然可以根據實際情況,填寫其它一些資訊。需要注意的是,每個Question需要有唯一的一個Answer來對應,而每個Answer可以有很多個Question,是N:1的關系。
小提示:以上資料均為虛構,請填寫符合自己學校實際情況的資料。
資料填寫的差不多了(一次填寫不完沒關系,可以以後修改),點選"Save and train"按鈕,稍等一會兒,點選那個"Test"按鈕,進行線上測試。在問題框中輸入"報帳"或者一個整句“醫療費如何報帳”,可以很快得到系統的回複,如下圖就是測試結果:
此時也可以點選"Inspect"來看細節,比如Confidence score的值是79.75分,也可以在左側填寫更多的問題來對應這個答案,比如"看病報帳":
覺得滿意後,點選"PUBLISH"按鈕來釋出這個知識庫:
稍等一會兒,得到如下資訊:
好啦!到目前為止,我們已經成功建立了第一個知識庫。
小提示:保留這個網頁或者請記住上圖中的資訊,一會兒我們還會用到它。
下面我們有兩個選擇:
1)寫代碼來通路這個知識庫,提供界面供他人使用。
2)用微軟的另外一項技術 – 聊天機器人技術,以問答方式來提供通路該知識庫的界面。這個内容我們在下一個大章節講述。
用代碼通路QnA知識庫
打開利器VS2017,建立一個Windows Desktop WPF項目,給個名字叫QAClient:
在MainWindow.xaml中填寫如下XAML界面設計代碼:
<Window x:Class="QAClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:QAClient"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<TextBox Name="tb_Dialog" Grid.Row="0"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<TextBox Name="tb_Question" MaxLines="1" Grid.Column="0"/>
<Button Name="btn_Send" Content="Send" Grid.Column="1" Click="btn_Send_Click"/>
</Grid>
</Grid>
</Window>
在MainWindow.xaml.cs中添加按鈕事件處理函數:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void btn_Send_Click(object sender, RoutedEventArgs e)
{
// send http post request to qa service
Answers results = await QAServiceAgent.DoQuery(this.tb_Question.Text);
if (results.answers != null && results.answers.Length > 0)
{
this.tb_Dialog.Text += "問:" + this.tb_Question.Text + "\r\n";
this.tb_Dialog.Text += results.answers[0].ToString() + "\r\n";
}
}
}
在工程中添加QAServiceAgent.cs檔案,填寫以下内容:
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace QAClient
{
class QAServiceAgent
{
const string Endpoint = "/knowledgebases/90690b7-dae-4e0d-bda9-16c05e0f163/generateAnswer";
const string Host = "https://openmindqnamaker.azurewebsites.net/qnamaker";
const string Key = "e7e3c51-dc5-4d65-aa3-8da1024c3e13";
const string ContentType = "application/json";
// {"question":"<Your question>"}
public static async Task<Answers> DoQuery(string question)
{
try
{
using (HttpClient hc = new HttpClient())
{
hc.DefaultRequestHeaders.Add("authorization", "EndpointKey " + Key);
string jsonBody = CreateJsonBodyElement(question);
StringContent content = new StringContent(jsonBody, Encoding.UTF8, ContentType);
string uri = Host + Endpoint;
HttpResponseMessage resp = await hc.PostAsync(uri, content);
string json = await resp.Content.ReadAsStringAsync();
var ro = Newtonsoft.Json.JsonConvert.DeserializeObject<Answers>(json);
return ro;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return null;
}
}
private static string CreateJsonBodyElement(string question)
{
string a = "{\"question\":\"" + question + "\"}";
return a;
}
}
}
小提示:上面代碼中的Endpoint和Key已經經過修改,是不可用的,請用你自己申請的資料來代替。
在工程中添加另外一個檔案Result.cs,用于反序列化JSON資料:
namespace QAClient
{
public class Answers
{
public Answer[] answers { get; set; }
}
public class Answer
{
public string[] questions { get; set; }
public string answer { get; set; }
public float score { get; set; }
public int id { get; set; }
public string source { get; set; }
public object[] metadata { get; set; }
public override string ToString()
{
return string.Format("Answer: {0}, Score:{1}", answer, score);
}
}
}
代碼完成!搓搓雙手,按Ctrl+F5走起一波!哇哦!好俊的界面:
在下方的輸入框中輸入"報帳"、"開學日期"、"補考"等問題,都會得到預定的答案。輸入"校長是誰"就沒有match到任何答案,因為我們沒有在資料中準備這個問題。
我們是用用戶端形式做了一個問答界面,當然也可以在網站上用REST API實作同樣的功能。同時,微軟提供了Bot Service,下一章我們看看如何在不寫任何代碼的情況下,完成機器人與QnA服務的內建。
建立對話機器人服務
什麼是機器人服務?
機器人是使用者使用文本、圖形(卡片)或語音通過聊天的方式進行互動的應用。它可以是一個簡單的問答對話,也可以是一個複雜的機器人,允許使用者使用模式比對、狀态跟蹤和與現有業務服務完美內建的人工智能技術通過智能的方式與服務進行互動。常見的機器人服務有以下幾類:
- 商務/金融服務,如銀行提供的線上客服
- 資訊服務,如政府部門的常用資訊問答服務
- 産品服務,如企業提供的産品咨詢服務
總之,機器人服務就是用計算機代替人來完成一些具有标準化流程的人機對話服務。
微軟提供的機器人服務的概述在這個連結裡面,建立一個機器人服務和一般的軟體其實沒多大差別,也要經過以下幾個步驟然後再疊代:
計劃:确定需求,需要什麼類型的機器人服務
建構:選擇工具/語言/架構等等
測試:機器人其實知識界面,後端連接配接了一堆智能服務,要通過機器人界面測試好所有功能
釋出:釋出的Azure上或者自己的Web伺服器上
連接配接:可以将機器人連接配接到以有的用戶端軟體上,友善使用者接入,比如Cortana、Skype等
評估:根據運作日志獲得基本運作名額,如流量、延遲、故障等等,作為疊代的依據
建立對話機器人
用MSA登入Azure門戶,點選"建立資源":
小提示:此MSA賬号需要與前面的QnA服務的MSA賬号相同。
選擇"AI + Machine Learning",在右側選擇"Web App Bot":
在上圖中選擇Web App Bot,在右側彈出的視窗中點選"建立"按鈕,得到下圖:
在上圖中填寫必要的資訊,比如機器人名稱是"SchoolQnAWebBot",機器人模闆要選擇"Question and Answer",可以關閉Application Insights來簡化過程。
小提示:記住要點選"選擇"按鈕,否則不生效。
最後點選"建立"按鈕,稍等一會兒,得到以下通知:
小提示:此時可以固定到儀表闆,友善以後通路。
連接配接知識庫
在儀表闆上點選這個機器人,然後點選左側的"網絡聊天測試":
在上圖中下方輸入"報帳",機器人傻傻的回了一句"you said 報帳"。因為這個機器人剛剛建立,還沒有連到上面建立的知識庫上,是以它并不知道如何回答你的問題。是以點選左側的"應用程式設定",看到一個吓人的頁面,不要慌,鎮定地向下卷滾,直到看到QnA開頭的項目,一共有三個,如下圖:
這三個值本來是空的,我們需要用以前得到一個資訊來填寫:
把顔色對應的資訊填寫到空白處就可以了。填寫完畢後,點選最上方的"儲存"按鈕,稍等一會兒,這個Bot service會被重新編譯部署。等到部署完畢收到通知後,可以再測試一下,輸入"報帳"并回車,機器人就會給你傳回知識庫中的答案:
WoW! 我們沒寫一行code,就完成了知識庫和機器人的連接配接,龍顔大悅,喝口燕窩銀耳湯,看看還有什麼好玩兒的!
連接配接已有應用
這個機器人雖然已經建立起來了,可是用什麼常見的用戶端來激活這個機器人呢?
我們在下圖中點選左側那個"信道"看看:
很神奇的樣子,好像可以連接配接這麼多種用戶端!我們用Skype先試驗一下。點選Skype圖示,進入一個頁面,但是可以不管它,退回到"信道"頁面,可以看到下圖:
點選那個"Skype"文字連結(不是點選圖示),會另起一個網頁:
點選"Add to Contacts",如果機器上安裝了Skype UWP版(如下圖),就可以啟動它了。如果沒有安裝,剛才那個網頁會給你一個"Download Skype"的選項。
Skype啟動後,SchoolQnAWebBot會作為一個聯系人出現在對話中,我們可以問它一些事情,如下圖所示,"報帳"、"補考"、"開學"等,機器人都可以回答。但是輸入比如"誰是校長"之類的不在知識庫裡的詞彙,機器人就隻能裝傻充愣了。