一般來說Chatbot試圖以模擬自然對話做為應用軟體的一種溝通模式,然而畢竟不是真的人類,要能達到理想上的完全像人類一樣的對話,就目前來說是有困難的,因此在Chatbot的一些情境裡,我們會利用資訊卡的UI來讓對話更流暢。
這些資訊卡你可以把它想像成應用程式裡的UI 控制項,用於讓使用者與Chatbot做互動,協助引導與Chatbot之間的交談,例如,提供項目選擇清單、摘要內容等,在bot framework裡(不管是V3或V4版本)皆有支援資訊卡,以下針對目前資訊卡的種類及程式碼片段做說明
AdaptiveCard
透過json的宣告,在各種通訊平台上產生自適應的資訊卡UI,不同通訊平台所呈現的UI會有些差異,直接來看這個例子,利用AdaptiveCard呈現個人資訊
private static Attachment CreateAdaptiveCardAttachment()
{
// combine path for cross platform support
string[] paths = { ".", "myprofile.json" };
var adaptiveCardJson = File.ReadAllText(Path.Combine(paths), System.Text.Encoding.UTF8);
var adaptiveCardAttachment = new Attachment()
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = JsonConvert.DeserializeObject(adaptiveCardJson),
};
return adaptiveCardAttachment;
}
從程式碼我們可以看到使用AdaptiveCard時須先定義一個json檔案,這個json檔案包含以下資訊
- type (必填) 固定值"AdaptiveCard"
- version (非必填) 指定資訊卡schema版本
- body (非必填) 顯示在AdaptiveCard裡的元素
- actions (非必填) 在資訊卡的action bar要呈現的功能按鈕
- selectAction (非必填) 點擊資訊卡時要調用的動作
- fallbackText (非必填) 當通訊平台不支援所指定的資訊卡schema版本時,要顯示的文字
- backgroundImage (非必填) 背景圖不用多解釋了吧
- speak (非必填) AdaptiveCard簡要內容文字
- lang (非必填) 指定本地化日期/時間格式
再進一步展開body內容
看似複雜,但簡單來說在body的部份主要是建構AdaptiveCard的主體內容,先利用Container把區塊劃分出來,接著在每個Container內放置內容,可以是圖檔、文字等,並且可以細部設置以ColumnSet或TextBlock型態編排,以及寬度、字型大小等等。
接著在AdaptiveCard最後面可以放置actions,讓使用者可以做點選操作。
這二種資訊卡分別支援聲音及影音方面,程式碼方面大致相同,差別在於給予是聲音檔案或是影音檔案,直接來看VideoCard
private static Attachment CreateVideoCard()
{
var card = new VideoCard
{
Title = "AI實作範例-Chatbot",
Subtitle = "使用bot framework 打造Chatbot",
Text = "這是一個使用bot framework+LUIS打造Chatbot的範例",
Media = new List<MediaUrl>
{
new MediaUrl()
{
Url = "https://www.youtube.com/watch?v=bWUoaIJ6KUw",
},
},
Buttons = new List<CardAction>
{
new CardAction()
{
Title = "Read More",
Type = ActionTypes.OpenUrl,
Value = "https://www.youtube.com/watch?v=bWUoaIJ6KUw",
},
},
};
return card.ToAttachment();
}
從程式碼我們可以看到使用VideoCard時,除了Title、Subtitle、Text屬性可以給予文字資訊之外,影像檔案的部份是設置Media屬性,接著同樣可以提供CardAction讓使用者可以進一步點選進行互動,不管是VideoCard或AudioCard,都是可以直接在Chatbot裡就進行播放的
這二種資訊卡程式碼方面大致相同,差別在於UI上的圖示大小呈現不同,HeroCard會呈現大尺吋圖示,比較適合用來呈現與內容本文相關的圖,而ThumbnailCard則是小圖示,比較適合用來呈現品牌Logo或產品Logo
private static Attachment CreateHeroCard()
{
var heroCard = new HeroCard
{
Title = "BotFramework Chatbot",
Subtitle = "Use Microsoft Bot Framework v4 Create Chatbot",
Text = "使用Microsoft Bot Framework v4打造聊天機器人",
Images = new List<CardImage> {
new CardImage("http://anthillonline.com/wp-content/uploads/2018/07/chatbot-300x350.jpg")
},
Buttons = new List<CardAction> {
new CardAction(ActionTypes.OpenUrl, "View More", value: "https://docs.microsoft.com/bot-framework")
},
};
return heroCard.ToAttachment();
}
從程式碼我們可以看到除了Title、Subtitle、Text屬性可以給予文字資訊之外,透過設置Images屬性可以決定要呈現的圖示,接著同樣可以提供CardAction讓使用者可以進一步點選進行互動
這個資訊卡比較特別,類似收據的格式,用於呈現購物項目清單以及金額等資訊
private static Attachment CreateReceiptCard()
{
var receiptCard = new ReceiptCard
{
Title = "Ian Chen",
Facts = new List<Fact> {
new Fact("訂單編號", "A12345678"),
new Fact("消費日期", "2018/5/1"),
new Fact("付款方式", "VISA 8888-****")
},
Items = new List<ReceiptItem>
{
new ReceiptItem("球棒型加油棒",
price: "$ 200",
quantity: "1",
image: new CardImage(url: "https://img1.momoshop.com.tw/goodsimg/0004/706/410/4706410_X.jpg")),
new ReceiptItem("應援毛巾(藍)",
price: "$ 250",
quantity: "1",
image: new CardImage(url: "https://img1.momoshop.com.tw/goodsimg/0004/781/728/4781728_X.jpg")),
},
Tax = "$ 0",
Total = "$ 450",
Buttons = new List<CardAction>
{
new CardAction(
ActionTypes.OpenUrl,
"詳細資訊",
"https://img1.momoshop.com.tw/ecm/img/online/21/411/00/000/bt_1_019_01/bt_1_019_01_e3.jpg",
value: "https://www.momoshop.com.tw/category/LgrpCategory.jsp?l_code=2141100000")
}
};
return receiptCard.ToAttachment();
}
程式碼的部份,Factsg屬性用於呈現最上方的資訊,而Items屬性用於呈現項目清單,Tax及Total則是稅金和總金額資訊,同樣的可以提供CardAction讓使用者可以進一步點選進行互動
用於呈現播放 GIF 或短片的資訊卡
private static Attachment GetAnimationCard()
{
var animationCard = new AnimationCard
{
Title = "Microsoft Bot Framework",
Subtitle = "Animation Card",
Media = new List<MediaUrl>
{
new MediaUrl()
{
Url = "https://freight.cargo.site/w/600/q/94/i/125b3fa7090d4d0e880febc7e29f6d0095f58f6d75ab76ccd6db623a046f2346/giphy-7.gif",
},
},
};
return animationCard.ToAttachment();
}
程式碼很簡單,設置Media屬性提供gif圖檔的URL即可,當然做為一個資訊卡,基本的Title、Subtitle還是有的。
最後在主程式碼的部份,我們來看看如何把資訊卡做為一個回覆訊息,回傳給使用者,透過turnContext的Activity物件呼叫CreateReply方法,產生一個回覆的Activity物件,接著在這個Activity物件的Attachments屬性加入Attachment,最後呼叫SendActivityAsync(reply)把回覆的Activity物件送回去即可
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
if (turnContext.Activity.Type == ActivityTypes.Message)
{
var reply = turnContext.Activity.CreateReply();
reply.Attachments.Add(GetAnimationCard());
await turnContext.SendActivityAsync(reply);
}
}
By No.18