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
街口支付QR Code
支付寶QR Code
街口支付QR Code
微信支付QR Code
comments powered by Disqus