Alan Tsai 的學習筆記


學而不思則罔,思而不學則殆,不思不學則“網貸” 為現任微軟最有價值專家 (MVP)、微軟認證講師 (MCT) 、Blogger、Youtuber:記錄軟體開發的點點滴滴 著重於微軟技術、C#、ASP .NET、Azure、DevOps、Docker、AI、Chatbot、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來處理。感覺程式碼會更加臟。

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

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

FormFlow是什麽?

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

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

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

如何使用FormFlow

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

同樣道理,Bot Builder SDK的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
台灣 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