Chatbotで画像コミュニケーションを実現する

2018年5月14日(月)
樋口 勝一
連載9回目となる今回は、Chatbotとの文字でのやり取りに画像を追加する方法を解説します。

前回までは、Chatbotとの会話の手段として、ダイアログのボタンによるメニュー選択と、AIによる文字列解析を行うために直接テキスト文字を入力する方法を紹介してきました。この二つの方法は、文字によるコミュニケーションを想定して実装したもので、入力ミスを減らす意味合いもあります。

これ以外にもChatbotと会話する方法として、Bot Frameworkには画像によるコミュニケーションを実現する仕組みが用意されています。チャットによるコミュニケーションでは文字だけではなく、写真のやり取りや宣伝のために商品のイメージの表示、さらにLINEのスタンプのようにそれだけでも会話が成り立ってしまうほど、画像によるコミュニケーションは一般的に利用されています。加えて、単なる文字の羅列だけではなくアプリケーションの中に画像を適度に配置することで、インターフェースとしての見栄えの向上にも有効な手段となっています。今回は、Chatbotの画像によるコミュニケーション方法を紹介します。

今回の記事で使用するファイル一式は、以下のリンクからダウンロード可能です。

Chatbot201707_09.zip

ユーザーから画像を送信する

まずは、ユーザー側から画像を送信する方法です。画像の送信機能は、最初から用意されているのでとても簡単です。Bot Frameworkのエミュレーターを見てみると、メッセージ入力のテキストボックスの左に画像送信のボタンがあります。エミュレーターに限らずBot Frameworkが提供しているチャンネルで利用できるアプリケーションにはすべて共通の機能が実装されています。こちらをクリックして送信したい画像を選択します。

画像の送信方法

画像の送信方法

送信した画像は、対話の中に表示されます。あとはこの画像に対するロジックを実装することになります。例えばAIを使って画像を解析して、その画像が何の写真なのかを判断してメッセージを表示したり、対話の中で文字の代わりにスタンプとして利用したりするといったことが考えられます。

画像の送信

画像の送信

Chatbotから画像を送信する

Chabot側から画像を送信する場合は、対話のメッセージに画像などを添付して表示するという考え方となります。

画像を添付して表示

画像を添付して表示

メッセージの送信方法としては、RootDialog.csを例にすると

リスト1:メッセージの送信方法(RootDialog.csでの例

await context.PostAsync($@"いらっしゃいませ!ご注文を伺います。
(メニューをご覧になる場合は「メニュー」と入力してください。)");

のように、「context.PostAsync」メソッドを利用できます。この場合送信する内容はテキスト文字列だけでしたが、ダイアログの中でメッセージを作成して送信することが可能です。メッセージの中には文字列だけではなく、画像やボタン、クリックされた時のアクションも含められるようになっています。具体例として、Chatbot201707のデザートメニューのDessertDialog.csで、画像送信ができるように修正していきましょう。

DessertDialog.csは呼び出されるとすぐに選択ボタンが表示されるようになっていますが、まずはこちらをメッセージが表示されるように変更します。

リスト2:DessertDialog.csの修正箇所

    public async Task StartAsync(IDialogContext context)
    {
        var message = context.MakeMessage();
        message.Text = "デザートをお選びください。";
        await context.PostAsync(message);
        context.Wait(MessageReceivedAsync);
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {
        var activity = await result as Activity;
        context.Done(activity.Text);
    }

重要な箇所なので、1行ずつ説明していきます。

StartAsync

ダイアログが開かれた時に最初に処理される部分です。

var message = context.MakeMessage()

Chatbotから送信するメッセージオブジェクトを作成します。

message.Text = "デザートをお選びください。"

メッセージオブジェクトに送信するテキストを指定します。

await context.PostAsync(message)

作成したメッセージを送信します。

context.Wait(MessageReceivedAsync)

メッセージを送信したらユーザーからの入力を待ちます。

MessageReceivedAsync

ユーザーから入力があった場合の処理です。

context.Done(activity.Text)

ユーザーからの入力内容を戻り値としてダイアログを終了します。終了後はRootDialogに戻ります。

ここまでの状態を確認してみましょう。デザートメニューを選択するとメッセージが表示されています。

デザートダイアログを修正

デザートダイアログを修正

送信するメッセージが作成できたので、こちらに画像を添付してみましょう。表示するための画像を「img」フォルダを作成して配置しておきます。

画像の配置

画像の配置

リスト3:画像を配置するためのコード

    public async Task StartAsync(IDialogContext context)
    {
        var message = context.MakeMessage();
        message.Text = "デザートをお選びください。";
        message.Attachments.Add(new Attachment { ContentUrl = "https://chatbot201707.azurewebsites.net/img/strawberry.jpg", ContentType = "image/jpeg", Name = "季節のフルーツ" });
        await context.PostAsync(message);
        context.Wait(MessageReceivedAsync);
    }

message.Attachments.Add(new Attachment{~})

メッセージに添付します。添付する内容は、画像のパス、ContentType、名前です。

変更内容を確認してみましょう。以下のように、Chatbotから画像が送信されるようになりました。

画像が表示されるようになった

画像が表示されるようになった

シンプルにChatbotからのメッセージに写真を添付するだけであればこれでよいのですが、デザートメニューとして利用するには機能が足りません。そこで次は、複数のデザートの画像を表示して、画像の説明と選択するためのボタンを追加しましょう。そうなると、メッセージに画像だけでなく、ボタンやボタンをクリックした際の動作を追加する必要があります。このような場合には「カード」を利用します。カードに画像やボタンを追加してメッセージに添付することで、上記のデザートメニューを実現できます。今回はカードの一種である「HeroCard」を使って、デザートメニューを作成します。

まずはカードの作り方です。

リスト4:HeroCardを作る

    private static HeroCard SetHeroCard(string title, string imagePath)
    {
        var cardImage = new CardImage { Url = imagePath };
        var cardAction = new CardAction { Type = ActionTypes.ImBack, Title = "注文する", Value = title, Image = imagePath };
        var heroCard = new HeroCard { Title = title, Images = new List<CardImage> { cardImage }, Buttons = new List<CardAction> { cardAction }, Tap = cardAction };
        return heroCard;
    }

各行のポイントを説明します。

SetHeroCard

「HeroCard」を作成するSetHeroCardメソッドを定義します。

var cardImage = new CardImage { Url = imagePath }

カードに表示する画像を定義します。

var cardAction = new CardAction ……

カードもしくは、ボタンをクリックしたときの動作を定義します。ActionTypes.ImBack は、Valueに指定した値をChatbotに送信するという意味です。この他にも、様々な種類の動作を指定することができます。

var heroCard = new HeroCard ……

「HeroCard」を作成します。タイトル、画像(配列型)、ボタン(配列型)、選択した場合の動作を設定します。

カードは複数作成してメッセージに添付できるので、デザートメニューのアイテムごとにカードを作成し、配列として格納します。

リスト5:複数のカードを配列に格納

    public static HeroCard[] SetHeroCards()
    {
        var cards = new HeroCard[3];
        cards[0] = SetHeroCard("季節のフルーツ", "https://chatbot201707.azurewebsites.net/img/strawberry.jpg");
        cards[1] = SetHeroCard("アイスクリーム", "https://chatbot201707.azurewebsites.net/img/icecream.jpg");
        cards[2] = SetHeroCard("プリン", "https://chatbot201707.azurewebsites.net/img/pudding.jpg");
        return cards;
    }

着目すべき点をおさえておきましょう。

SetHeroCards

複数のカードを配列として一つにまとめるメソッドを定義します。

var cards = new HeroCard[3]

デザートは3種類あるので、配列に3つのHeroCardを格納します。

cards[0] = SetHeroCard ……

デザートのアイテムごとにSetHeroCardメソッドを呼び出してカードを作成します。

return cards

3つのカードが格納された配列を戻り値としています。

StartAsyncメソッドを修正します。

リスト6:StartAsyncメソッドの修正

    public async Task StartAsync(IDialogContext context)
    {
        var message = context.MakeMessage();
        message.Text = "デザートをお選びください。";

        var menuCards = SetHeroCards();
        foreach (var card in menuCards)
        {
            message.Attachments.Add(card.ToAttachment());
        }
        message.AttachmentLayout = AttachmentLayoutTypes.Carousel;
        await context.PostAsync(message);
        context.Wait(MessageReceivedAsync);
    }

着目すべき点をおさえておきましょう。

var menuCards = SetHeroCards()

3つのデザートのカードが格納された配列を取得します。

foreach (var card in menuCards)

配列に格納されたカード一つずつをメッセージに添付します。

message.AttachmentLayout = ……

通常メッセージに添付されたカードは縦に並べて表示されます。この設定を行うことで、複数のカードを横スクロールで表示することができます。

では、エミュレーターで確認してみましょう。おいしそうなデザートメニューが表示されました。デザートを選択したときの動作としても、選択名が表示されて、Chatbotに送信されているのが確認できます。

デザートメニューの表示

デザートメニューの表示

最終的なDessertDialog.csは以下となります。

リスト7:DessertDialog.cs

using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using System.Collections.Generic;

namespace Chatbot201707.Dialogs
{
    [Serializable]
    public class DessertDialog : IDialog<string>
    {
        public async Task StartAsync(IDialogContext context)
        {
            var message = context.MakeMessage();
            message.Text = "デザートをお選びください。";

            var menuCards = SetHeroCards();
            foreach (var card in menuCards)
            {
                message.Attachments.Add(card.ToAttachment());
            }
            message.AttachmentLayout = AttachmentLayoutTypes.Carousel;
            await context.PostAsync(message);
            context.Wait(MessageReceivedAsync);
        }

        public static HeroCard[] SetHeroCards()
        {
            var cards = new HeroCard[3];
            cards[0] = SetHeroCard("季節のフルーツ", "https://chatbot201707.azurewebsites.net/img/strawberry.jpg");
            cards[1] = SetHeroCard("アイスクリーム", "https://chatbot201707.azurewebsites.net/img/icecream.jpg");
            cards[2] = SetHeroCard("プリン", "https://chatbot201707.azurewebsites.net/img/pudding.jpg");
            return cards;
        }

        private static HeroCard SetHeroCard(string title, string imagePath)
        {
            var cardImage = new CardImage { Url = imagePath };
            var cardAction = new CardAction { Type = ActionTypes.ImBack, Title = "注文する", Value = title, Image = imagePath };
            var heroCard = new HeroCard { Title = title, Images = new List<CardImage> { cardImage }, Buttons = new List<CardAction> { cardAction }, Tap = cardAction };
            return heroCard;
        }

        private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
        {
            var activity = await result as Activity;
            context.Done(activity.Text);
        }
    }
}

今回は、Chatbotの画像によるコミュニケーション方法を紹介しました。デザート以外のメニューについても画像を用意してメニューを表示することで、見栄よく使いやすいChatbotに生まれ変わります。また少しChatbotが成長しましたね。

GMOインターネット株式会社 Windowsソリューション チーフエグゼクティブ

GMOインターネットでWindowsのサービス開発運用に関わって16年、数年単位で進化し続けるMicrosoftのWindowsは新しもの好きにはたまらない製品です。自動販売機に見たことのないジュースがあれば、迷わすボタンを押します。そんなチャレンジが僕の人生を明るく、楽しくしてくれています。

お名前.com デスクトップクラウド
http://www.onamae-desktop.com/

お名前.com VPS Hyper-V
http://www.onamae-server.com/vps/hyperv/

連載バックナンバー

Web開発技術解説
第10回

Chatbotから話しかける(プロアクティブメッセージの送信)

2018/5/18
連載10回目となる今回は、Chatbotから先に話しかけるための手順を紹介します。
Web開発技術解説
第9回

Chatbotで画像コミュニケーションを実現する

2018/5/14
連載9回目となる今回は、Chatbotとの文字でのやり取りに画像を追加する方法を解説します。
Web開発技術解説
第8回

FacebookでChatbotを公開する

2018/4/17
連載8回目となる今回は、FacebookのMessengerを介してChatbotとやり取りする方法を解説します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています