Alan Tsai 的學習筆記


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

[chatbot + AI = 下一代操作模式][07]使用FormFlow讓Chatbot搜集表單資訊更容易

[chatbot + AI = 下一代操作模式][07]使用FormFlow讓Chatbot搜集表單資訊更容易.jpg
圖片來源:https://pixabay.com/en/books-spine-colors-pastel-1099067/ 

在上一篇([06]不只能輸出文字 - 看看各種内建卡片模式以及可自定的Adaptive Card)介紹了如何透過Rich Card把bot輸出的内容變成更加漂亮的卡片樣式。

到目前爲止,所有的邏輯都在一起,作爲開發人員會開始覺得程式碼已經開始有些味道了(smell)了。如果今天我們想要透過交談對話中取得一些使用者的資訊,例如填寫表單,那可以想象要寫更多的if/else來處理。感覺程式碼會更加臟。

還好BotBuilder在表單類型的溝通有一個模組叫做FormFlow,在這一篇將來介紹如何使用FormFlow來設計從使用者收集資料。

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

FormFlow是什麽?

我們使用服務性類型的網站多多少少都需要填寫表單,例如,搜索飯店需要輸入一些條件,要注冊帳號需要輸入使用者資訊等。這些類型資訊可以統稱為表單類型的輸入。

回到chatbot角度,想一下這種表單開發在bot裡面要怎麽做?以我們現有知識的做法其實就是一堆if/else,同時還要記錄上下文(知道那些欄位有輸入過,那些沒有),并且要提供功能讓使用者看目前輸入了那些,并且如何修改已經輸入過的欄位 等等。

因此,要做好一個流程以及體驗需要花蠻多時間,因此BotBuilder有提供了一個模組叫做FormFlow。透過FormFlow,我們在開發這種表單輸入將會變得非常簡單。我們就來看看怎麽使用FormFlow。

如何使用FormFlow

如果有寫過MVC的會知道,當我們要開發一個表單的時候,第一件事情先定義出最後表單的Model。因爲透過Model我們可以做Model Binding得到强型別的物件,在C#處理會變得更加方便。

同樣道理,BotBuilder的FormFlow也是從Model開始。我們定義出一個我們表單的模型,并且透過使用Attribute調整呈現内容,最後我們收到的結果就會是這個Model。

實際使用FormFlow

我們會經歷過幾個步奏:

    1. 定義Model
    2. 把Model轉成FormFlow
    3. 觸發FormFlow

1. 定義Model

在我們的使用情景來説,訂房者想透過chatbot來訂房,那我們就會問一些問題來取得一些資訊,我們會需要:

  • 從那天入住
  • 住幾個晚上
  • 幾個人
  • 床大小

因此我們可以先建立一個Model有這些資訊:

public enum BedSizeOptions
{
	King = 1,
	Queen,
	Single
}

[Serializable]
public class RoomReservation
{
	public DateTime StartDate { get; set; }
	public int NumberOfNightToStay { get; set; }
	public int NumberOfOccupants { get; set; }
	public BedSizeOptions BedSize { get; set; }
}

這邊可以看到有不同的欄位形態,我們的床大小使用的是enum,透過enum可以限制使用者不要亂輸入。

然後我們的model需要定義爲Serializable

2. 把Model轉成FormFlow

Model有了之後,再來是我們要一個方法把Model轉換成爲一個FormFlow。直接在RoomReservation裡面定義一個方法:

...
public static IForm<RoomReservation> BuildForm()
{
	return new FormBuilder<RoomReservation>()
		.Build();
}

3. 觸發FormFlow

最後,只需要在需要的時候觸發即可。FormFlow的結果是用CallBack方式來接:

...
else if(activity.Text == "訂房v2")
{
	var reserveRoomForm = 
		FormDialog.FromForm(RoomReservation.BuildForm,
			FormOptions.PromptInStart);

	context.Call(reserveRoomForm, AfterReserveRoomAsync);
}
...
private async Task AfterReserveRoomAsync(IDialogContext context
            , IAwaitable<RoomReservation> result)
{
	RoomReservation reservation = null;

	reservation = await result;

	await context.PostAsync($"得到的結果:{Environment.NewLine} {JsonConvert.SerializeObject(reservation)}");

	context.Wait(MessageReceivedAsync);
}
這邊要注意一個事情,由於FormFlow觸發的方式不同,因此context.Wait(MessageReceivedAsync)不能集中在一個地方,而是每一個else裡面要放一個,然後FormFlow放在結束的callback裡面

測試FormFlow

首先可以測試順的流程(輸入的内容都對),可以參考以下的git動畫:

2018-07-11_07-55-25.gif
測試對流程的功能

不過其實在輸入的過程當中是有形態保護,例如,如果日期我輸入錯誤:

Bot Framework Emulator_2018-07-11_07-56-33.png
日期形態的防呆

在表單填寫過程其實有些特殊指令,這些可以從輸入Help看到有哪些:

Bot Framework Emulator_2018-07-11_07-57-48.png
Help畫面内容

假設想要看到目前輸入那些内容,可以輸入status

Bot Framework Emulator_2018-07-11_07-59-19.png
輸入status看到目前輸入過的内容

結語

透過這篇可以看到要有個好使用的表單輸入流程並不容易,需要考慮怎麽防呆欄位,怎麽修改目前已經輸入的内容等等。而這些FormFlow都幫我們處理好了。

不過透過這篇我們會發現,目前介紹的FormFlow雖然夠用,但是使用上還不那麽順暢。例如,英文當然沒有什麽問題,但是如果中文客戶怎麽辦?如果要退出FormFlow如何讓使用者看到更友善的訊息? 因此,下一篇([08]如何微調FormFlow讓使用上更流暢)將會對如何調整FormFlow在做個介紹。


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