[chatbot + AI = 下一代操作模式][19]把LUIS和BotBuilder整合 @ Alan Tsai 的學習筆記|An Asp .Net Mvc Web Developer Blog

Alan Tsai 的學習筆記


學而不思則罔,思而不學則殆,不思不學則“網貸” 記錄軟體開發的點點滴滴 著重於微軟技術、網頁開發、DevOps、C#, Asp .net Mvc、Azure、AI、Chatbot、Docker、Data Science

[chatbot + AI = 下一代操作模式][19]把LUIS和BotBuilder整合

[chatbot + AI = 下一代操作模式][19]把LUIS和BotBuilder整合.jpg
圖片來源:https://pixabay.com/en/books-spine-colors-pastel-1099067/ 

在上一篇([18]在LUIS建立app - 概念變成實作)看完如何建立一個app,然後定義intent以及utterance。

這篇將來看看如何把上篇建立好的model發佈出去,并且用在實際的程式裡面。這篇將整合LUIS建立出來的Model到目前的chatbot裡面,讓chatbot的判斷不再是呆板的if else。

這篇的程式碼github頁面是alantsai-samples/mhat-hotelbot:blog/chapter-19

如何讓LUIS和BotBuilder結合?

有兩個動作需要做:

  1. 上篇雖然把model建立出來了,但是沒有發佈,因此需要先發佈了之後,外界才可以透過REST Api調用
  2. 調整chatbot的程式 - 目前是在RootDialog裡面透過if else來切換觸發那個Dialog。這個工作將轉交給LUIS來做這個意圖識別

發佈LUIS app

登入到luis.ai的網站上面,并且進入到上篇所建立的app裡面,在上面的menu選擇PUBLISH

chrome_2018-07-24_17-07-45.png
切換到Publish app的畫面

從上圖可以看到,目前的Published Version顯示的是尚未發佈過。

在按下Publish按鈕之前,有一些設定介紹一下:

  1. Select Slot可以選擇發佈到那個slot裡面。好習慣是會有個Staging/UAT環境測試好了才會上Production。而LUIS有提供這個機制可以方便測試好了再上正式
  2. Timezone的部分不太確定作用,不過估計是和分析資料呈現的日期有關。如果有清楚的歡迎更正
  3. Include All Predicted intent scores - 由於識別的時候不同的intent會有不同的分數 - 如果想看到所有的intent分數就打勾,如果只需要最高分的就不打勾。這個影響到回傳的json大小
  4. Enable Bing Spell checker - Bing spell checker是另外一個服務,用來檢測有沒有打錯字。不過這個估計只有英文語系有作用,如果要使用需要加入 Bing spell checker的key
  5. key string - 這個要收好,驗證權限用的key
  6. Endpoint - 這個是服務的地址,由於區域的不同,地址也是不同的。這個是REST API的end point
chrome_2018-07-24_17-10-22.png
一些發佈相關的設定
題外話,免費版本只能夠放在北美,如果想要放在亞洲,需要收費版本。設定很簡單,只需要在Azure上面先建立好LUIS的服務,然後按下按鈕Add Key裡面加入建立的那個服務即可。

設定確認好了之後,就按下Publish,然後會看到之前Published Version會變成0.1。

題外話,看到版號應該會想到版本控制對吧。LUIS設計還蠻好,除了staging和production切換之外,還有把版號這個事情考慮進去。這都是影響服務品質應該有的管控。

發佈完了要測試一下有沒有問題,這個時候直接點下End Point,然後在最後一個參數q輸入想要查詢的,將會得到結果:

chrome_2018-07-24_17-22-54.png
測試發佈的model是否有問題

整合LUIS到BotBuilder

接下來就是把LUIS整合到BotBuilder裡面。

從上面知道,其實LUIS最後提供的就是一個REST API而已,所以可以自己做一個class專門處理溝通然後返回結果, 不過不用那麽麻煩,BotBuilder已經有包好Dialog可以直接使用。

題外話:還蠻驚訝沒找到有現成的C# Library獨立在做和LUIS溝通的這個事情,不過BotBuilder裡面有包含,如果非chatbot的程式需要和LUIS溝通,可以參考一下BotBuilder的原始碼,省的自己寫。

接下來,改造一下現行程式來用LUIS判斷使用者的意圖,總共有幾個部分:

  1. 建立一個RootLuisDialog繼承LuisDialog
  2. 調整每一個intent對應需要發生的事情
  3. 調整進入的起始Dialog
  4. 測試結果

建立一個Dialog繼承LuisDialog

首先,在Dialogs資料夾下面,在建立另外一個class叫做RootLuisDialog.cs

這個新的Dialog將會繼承LuisDialog,并且透過LuisModelAttribute來設定使用的app id,以及key

因此,整個class内容如下:

[LuisModel("<app id>", "<key>")]
[Serializable]
public class RootLuisDialog : LuisDialog<object>
{
}
app idkey最快的取得方式是從Luis那邊不是有透過endpoint做測試,網址的末端是app id,subscription-key則是需要的key:
chrome_2018-07-24_17-52-47.png
取得app id 以及 key的方式
注意一下,key要保存好,避免被人濫用您的服務。
注意:如果不是使用預設的key(在美國的region),那麽endpoint會不同,這個時候把對應endpoint的domain name輸入到參數domain這個參數即可。

調整每一個intent對應需要發生的事情

透過使用LuisIntentAttribute,設定intent的名稱作爲參數,只要當LUIS判斷的intent和那個名字對應上的話,那個方法就會被執行。

如果LuisIntentAttribute的名稱為空,表示所有沒match到都會由這個方法來處理。

有了這個概念之後,調整程式碼如下:

...
public class RootLuisDialog : LuisDialog<object>
{
	[LuisIntent("")]
	public async Task None
		(IDialogContext context, LuisResult result)
	{
		await context.PostAsync("無法理解您的請求");

		context.Wait(MessageReceived);
	}

	[LuisIntent("SearchHotel")]
	public Task SearchHotel
		(IDialogContext context, LuisResult result)
	{
		context.Call(new SearchHotelDialog(), async (ctx, r) =>
		{
			var imessageActivity = ctx.Activity as Activity;

			var returnMessage = imessageActivity.CreateReply();
			var attachments = await r;
			returnMessage.Attachments = attachments;

			await context.PostAsync(returnMessage);
			context.Wait(MessageReceived);
		});

		return Task.CompletedTask;
	}
}

調整初始進入的Dialog

上面設定好了Dialog了之後,接下來就是調整讓RootLuisDialog替代RootDialog

因此進入MessagesController調整如下:

...
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
	if (activity.GetActivityType() == ActivityTypes.Message)
	{
		await Conversation.SendAsync(activity, MakeLuisDialog);
	}
	else
	{
		HandleSystemMessage(activity);
	}
	var response = Request.CreateResponse(HttpStatusCode.OK);
	return response;
}

private IDialog<object> MakeLuisDialog()
{
	return Chain.From(() => new RootLuisDialog());
}
...

對應的調整有標黃了,基本上,這邊建立了一個方法,MakeLuisDialog避免整個inline呼叫看起來很亂。

測試結果

最後,使用bot emulator來測試剛剛的修改。

botframework-emulator_2018-07-24_22-58-27.png
測試結果

接下來就是把其他的intent也加進去即可。

結語

這篇介紹了如何把建立出來的LUIS app發佈成爲服務,并且如何和BotBuilder結合,讓chatbot能夠使用LUIS的威力來識別使用者的意圖。

到目前爲止,對於LUIS的基本概念以及使用已經有了基本概念,不過裡面還有蠻多的細節,例如entities的使用、持續維護LUIS app等,下一篇([20]LUIS深入使用 - 定義Entities來截取參數)先從entities開始介紹。

comments powered by Disqus