Alan Tsai 的學習筆記


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

[chatbot + AI = 下一代操作模式][15]上綫 - 透過Direct Line把chatbot和任意程式做連接

[chatbot + AI = 下一代操作模式][15]上綫 - 透過Direct Line把chatbot和任意程式做連接.jpg
圖片來源:https://pixabay.com/en/books-spine-colors-pastel-1099067/ 

在上一篇([14]上綫 - 把facebook粉絲頁和chatbot接上)介紹了如何把chatbot和Facebook Messenger做了連接。bot channel registration還有好幾個内建的其他channel可以設定做關聯,至於怎麽設定可以透過google的方式去找到相關資料,因此其他内建的channel 這邊不在做介紹。

不過,雖然任意網站可以用web control channel來連接,并且有些内建的channel,可是如果想要在不是内建的channel關聯chatbot怎麽辦?舉例來説,如果今天想要和Line關聯或者微信怎麽辦?或者如果想要在任何程式和chatbot 做關聯?

這就是Direct LIne Channel的目的,只要可以用程式來控制,那麽就可以透過Direct LIne Channel來和chatbot關聯。

這篇將會透過開發一個console程式和chatbot程式溝通。

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

如何使用Direct LIne Channel

要使用Direct Line會經過幾個步奏:

  1. 在bot channel registration 裡面增加Direct Line Channel
  2. 在程式裡面使用Direct Line Api - 這邊將以console程式為例子
  3. 測試

在bot channel registration 裡面增加Direct Line Channel

透過在 Bot Channel Registration 裡面選擇 channel,然後按下Configure Direct Line

chrome_2018-07-19_20-01-44.jpg
設定Direct Line Channel

Configure Direct Line的畫面,可以看到有2組secret key,這兩組是用來和Direct Line 連接的重要資訊,透過按下Show,然後把對應的key複製下來。

chrome_2018-07-19_20-03-15.jpg
取得secrete的截圖

在程式裡面使用Direct Line Api - 這邊將以console程式為例子

建立一個新的console project,并且安裝Direct Line 的Library
開啓一個新的console project,然後透過nuget安裝一個套件叫做:Microsoft.Bot.Connector.Direct Line
透過設定檔取得Direct Line Channel的Secret Key和BotId
private static string directLineSecret = 
	ConfigurationManager.AppSettings["DirectLineSecret"];

private static string botId = ConfigurationManager.AppSettings["BotId"];

private static string fromUser = "DirectLineSampleClientUser";
建立送訊息給chatbot以及從chatbot取得回復的兩個方法
private static async Task StartBotConversation()
{
	DirectLineClient client = new DirectLineClient(directLineSecret);

	var conversation = await client.Conversations.StartConversationAsync();

	new System.Threading.Thread(async () => await 
		ReadBotMessagesAsync(client, conversation.ConversationId)).Start();

	Console.Write("Command> ");

	while (true)
	{
		string input = Console.ReadLine().Trim();

		if (input.ToLower() == "exit")
		{
			break;
		}
		else
		{
			if (input.Length > 0)
			{
				Activity userMessage = new Activity
				{
					From = new ChannelAccount(fromUser),
					Text = input,
					Type = ActivityTypes.Message
				};

				await client.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
			}
		}
	}
}

private static async Task ReadBotMessagesAsync(DirectLineClient client, string conversationId)
{
	string watermark = null;

	while (true)
	{
		var activitySet = await client.Conversations.GetActivitiesAsync(conversationId, watermark);
		watermark = activitySet?.Watermark;

		var activities = from x in activitySet.Activities
						 where x.From.Id == botId
						 select x;

		foreach (Activity activity in activities)
		{
			Console.WriteLine(activity.Text);

			Console.Write("Command> ");
		}

		await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
	}
}
呼叫啓動寄送訊息給chatbot的程式
static void Main(string[] args)
{
    StartBotConversation().Wait();
}

測試結果

接下來在App.Config裡面設定好Direct Line的secret以及bot id。

把console啓動起來。

開始輸入指令。

cmd_2018-07-19_20-21-39.jpg
測試console directline

從上面的截圖可以看到,整個的運作模式和其他channel操作沒什麽兩樣,不過發現查飯店沒有任何東西被顯示出來,這個是爲什麽呢?

微調訊息處理内容

Direct LIne是一個很好學習底層connector在做的事情,還記得connector service做的一件事情是把Activity Message Format(chatbot在看的)轉換成各自的Channel Message Format

b9aa9d2d-1711-4097-ad3b-d929582c3d6d.jpg
整體架構圖

由於Direct Line是一個通用性的channel,因此需要自己處理格式轉換的部分,而其他内建的channel則已經幫忙處理好了這塊。因此,訊息輸出需要依照傳送進來的内容格式不同而做出不同處理。

首先,將建立一個新的方法用來輸出HeroCard

private static void RenderHeroCard(Attachment attachment)
{
	const int Width = 70;
	Func<string, string> contentLine = (content) 
		=> string.Format($"{{0, -{Width}}}", 
			string.Format("{0," + ((Width + content.Length) / 2)
				.ToString() + "}", content));

	var heroCard = JsonConvert
		.DeserializeObject<HeroCard>
			(attachment.Content.ToString());

	if (heroCard != null)
	{
		Console.WriteLine("/{0}", new string('*', Width + 1));
		Console.WriteLine("*{0}*", contentLine(heroCard.Title));
		Console.WriteLine("*{0}*", new string(' ', Width));
		Console.WriteLine("*{0}*", contentLine(heroCard.Text));
		Console.WriteLine("{0}/", new string('*', Width + 1));
	}
}

然後在取得訊息的時候,多一個判斷看看Attachment有沒有HeroCard,有的話在做處理:

...	
foreach (Activity activity in activities)
{
	Console.WriteLine(activity.Text);

	if (activity.Attachments != null)
	{
		foreach (Attachment attachment in activity.Attachments)
		{
			switch (attachment.ContentType)
			{
				case "application/vnd.microsoft.card.hero":
					RenderHeroCard(attachment);
					break;
			}
		}
	}

	Console.Write("Command> ");
}
...

測試結果:

chrome_2018-07-19_20-42-37.jpg
測試查飯店效果,左邊是console,右邊是web control
HeroCard裡面還有鏈接和圖片,如果要完整當然也要做出對應處理。不過,這邊只是要show如何做出對應處理,因此剩下就看大家的情景做微調。

結語

Direct Line非常的强大,讓任何程式只要能夠送出http request就能夠和chatbot做連接。

到目前爲止,開發chatbot的知識有了,chatbot上綫的知識也有了,要寫出一個有用的chatbot已經夠了。chatbot相關的介紹也到了一個尾聲。

在下一篇([16]BotBuilder開發總結 - 下一步是搭AI服務)將來做一個快速的review,看一下目前的chatbot還有的問題,以及接下來AI怎麽進入到整個的開發環節讓chatbot更加智能。


如果文章對您有幫助,就請我喝杯飲料吧
街口支付QR Code
街口支付QR Code
台灣 Pay QR Code
台灣 Pay QR Code
Line Pay 一卡通 QR Code
Line Pay 一卡通 QR Code
街口支付QR Code
支付寶QR Code
街口支付QR Code
微信支付QR Code
comments powered by Disqus