チャットボットUIカスタマイズを簡単に。ライブラリ「Koe UI」を作ってみた

このエントリーをはてなブックマークに追加

こんにちは、岡田です!

これまで何度か、webブラウザからMicrosoft Bot Framework製のbotと対話をする方法をご紹介してきました。

今回は、どんな方でも簡単にwebサイトにbotを設置でき、さらにUIもカスタマイズできるライブラリ「Koe UI」を作ってみました。苦労した点なども含め紹介していきます!

botを作ろうとしている方々の一助になれば幸いです。
>> Koe UI デモページ

KoeUIデモスクショ

KoeUIのポイント

Microsoft Bot Frameworkを使って、webブラウザからbotと対話するには、WebChatやDirect Line APIという仕組みが使えます。

が、UIをカスタマイズできなかったり、カスタマイズできてもイチからUIを作らなければいけなかったり……という問題がありました。

ということで、簡単に設置できるWebChatの特徴は残しつつ、UIをカスタマイズできるようにしたのがKoeUIです!

もちろんUIをイチから作る必要もありません。

KoeUIで使っている技術

今回のライブラリでは、主に下記のような技術を使っています。

  • DirectLineAPI: botとの接続
  • jQuery: UIのアニメーション
  • Riot.js: コンポーネント化されたUIの呼び出し
  • Fetch API: DirectLineAPIとの通信
  • Promise: 処理の順番の制御
  • Cookie: Conversation Idの保存

ここで使っているPromiseって??

Promiseは「いつ終わるかわからないけど、いつか終わる事が約束されている処理」を管理するための仕組みです。今回の場合でいうと、Direct Line APIとのHTTP通信ですね。

本来はいつAPIから結果が返ってくるかはわからないのですが、Promiseで管理すれば、APIから結果が返ってきたタイミングがわかります。

Koe UIでは、Promiseで処理の順番を制御しています。具体的には下記のような処理順序になっています。

APIにメッセージを送信

ローディングアニメーションを表示

APIからメッセージを取得

UIに発言を表示・下までスクロール

ローディングアニメーションを隠す

ソースコードはGitHubで公開していますので、詳細に知りたい方はぜひご覧ください。

Direct Line APIについては、前回の記事で解説しています。

webサイトへの設置はタグを貼り付けるだけ!

Koe UIでこだわった一つのポイントは、設置の簡単さでした。

設置の方法は、まず必要なライブラリ・処理のscriptタグを記述し、

<script src="assets/js/vender/jquery-1.12.4.min.js"></script>
<script src="assets/js/vender/riot+compiler.min.js"></script>
<script src="assets/js/koeUIcore.js"></script>
<script src="assets/js/riot-tags/koe-ui-basic.tag" type="riot/tag"></script>
<script>riot.mount('*');</script>

次に、下記のUIを呼び出すためのタグを好きな場所に貼り付けるだけ

<koe-ui-basic token="_YOUR_DIRECT_LINE_API_SECRET_KEY_"></koe-ui-basic>
botと接続するためには、Direct Line APIのキーが必要です。
_YOUR_DIRECT_LINE_API_SECRET_KEY_ の部分を、そのキーに置き換えて下さい。
詳しくは、前回の記事を参照願います。

設置の説明

たったこれだけの作業で、webサイトにbotを埋め込む事ができます。

独自タグについて

よくみると、 <koe-ui-basic> という見慣れないタグが出てきています。これはKoe UI用の独自タグで、このタグを貼り付けた部分にチャットUIが表示されます。

設置の手軽さを実現しているのが、Riot.jsというフレームワーク。Riot.jsは、ReactやAngularのようなJavaScript製のwebアプリケーション向けフレームワークです。最大の特徴は、マイクロ志向・コンポーネント志向である事です。

読み込むスクリプトのなかに koe-ui-basic.tag というファイルがあります。この中に、HTML・CSS・JavaScriptが全てまとまっていて、 <koe-ui-basic> タグの部分に中身を展開しています。

HTML・CSSはこの内部だけで完結するようにできているので、設置したページの他の部分には干渉しにくいようになっています。

ですので、ライブラリを使う方は難しい事を考えず、タグを貼り付けるだけでチャットUIを埋め込むことができます!

KoeUIの特徴のひとつ。チャットUIの簡単カスタマイズ

さきほどご紹介したように、UIのHTML・CSSは、koe-ui-basic.tag のなかにまとまっています。この中のHTMLとCSSを変更すれば、カスタマイズができます。

今回は例として、Facebook Messengerのように、メッセージの色を濃い青色に変更してみます!

UIの主要な部分のタグ名・クラス名は、下記のようになっています。

UIのクラス解説

さっそくCSSを変更してみます。
CSSのソースコード部分は、39〜163行目です。
>> ソースコードはこちら

今回は、色付きメッセージの部分を濃い青色に変更したいので、クラス .message._me の部分を変更します。

.message._me > span {
  color: #fff;
  background: #41e667;
}

の部分が、色の指定をしている部分です。
こちらを、

.message._me > span {
  color: #fff;
  background: #4080ff;
}

に変更して保存します。

色変更後

変わりました! ちょっとFacebookっぽくなりましたね!

CSSをよく見ると、
.message , input , button などなど。
CSSの指定が汎用的すぎて他の部分とバッティングしないか心配になるかと思いますが、さきほど紹介したよう干渉しないのでご安心下さい。

CSSの範囲が調整される

安心して、CSSが書けますね!

CSS部分には <style scoped> と :scoped といった変わった記述があります。こちらは、Scoped CSSという仕様にのっとった記法です。

Scoped CSSとは「特定の範囲だけでスタイルを適用させる」CSSの仕様。まだまだ対応ブラウザが少ない技術ですが、コンポーネント志向が広まりとともに、注目されている技術です。

Riot.jsでは、Scoped CSSの記法が使用できます。

HTMLにも手を入れれば、大幅なカスタマイズも可能

もっと大きくカスタマイズしたい方は、HTMLも変更してみてください。

<!-- Google Material Icon -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<div class="chatScreen">
  <div class="message _welcome">
    <span>Hi, I am a bot! How are you?</span>
  </div>
  <div each="{ msgObj.messages }">
    <div class="message {filter_me( from )}">
     <span>{ text }</span>
    </div>
  </div>
</div>
<div>
  <form onsubmit="{ send_and_polling }">
    <input type="text" onkeyup="{ edit }">
    <div class='loader'>loading</div>
    <button disabled="{ !text }">
      <i class="material-icons">send</i>
    </button>
  </form>
</div>

>> HTMLはこちら

HTML部分はRiot.js用に、特殊な記法になっています。 { } でくくられている部分は、Riot.jsによって自動で変換されます。

上から順に、HTMLの簡単な解説をしていきます。

Hi, I am a bot! How are you? の部分を変更すれば、初期メッセージを変更する事ができます。

each=”{ msgObj.messages }” の部分は、Direct Line APIで取得したメッセージの分、<div class=”message”> の部分をループする事を意味しています。この部分に、ユーザーとbotのやり取りが表示されます。

{filter_me( from )} は、ユーザー側の発言だった場合に _me というクラスが付きます。これによって、bot側・ユーザー側の発言を色分けしています。

<form onsubmit=”{ send_and_polling }”> で、フォーム送信時に、メッセージ送信とポーリングを開始する関数を呼び出すように設定しています。

<input type=”text” onkeyup=”{ edit }”> で、テキスト入力欄の判定をしています。
<button disabled=”{ !text }”> では、テキスト入力欄が空の時に、disabled属性を有効にしています。つまり、ボタンが押せない状態になります。

リアルタイム感を出すためのワザ

Direct Line APIは、リアルタイムな双方向通信ができません。つまり「botから返事がきた」ということを自動では察知できないのです。

そのため、メッセージ取得をリクエストしても、タイミングが悪いとbotからまだ返事が返ってきていない状態になることも……。

結果、ユーザーがメッセージを送信してから、botの返事が来るまで、体感で約2〜3秒程かかります。(初回bot呼び出し時は、さらに時間がかかってしまいます)

つまり、約2〜3秒待ってからメッセージ取得をリクエストしないとユーザーは、botからのメッセージが取得できないという事です。しかし、2〜3秒もユーザーにただ待ってもらう事は現実的ではありませんよね……。

そこで今回はポーリングという方法と、アニメーションで改善に当たってみました。

botからの返事を逃さない。ポーリング技術

ポーリングは、簡単に言えば、応答があるまでリクエストを送り続けるという方法です。実際のポーリング部分のソースコードは、下記のようになっています。(2016年8月現在)

polling() {
  var that = this;
  return new Promise(function (resolve, reject) {
    Promise.all([that.get_prms(), that.sleep(300)])
      .then(function () {

        // 再帰処理
        // カウンタが最大より、まだ小さい。or Botからの新しいメッセージが取得されていない場合

        if (that.c_polling < that.polling_max && that.lastestBotMsgId != that.latestMsg.id) {
          that.c_polling++; //カウンタ更新
          that.polling(); //再帰呼出し
        } else {

        (以下省略)

>> 詳細コードはこちら

具体的な処理としては、「メッセージを取得する get_prms()・300ミリ秒待つ sleep(300)」という2つの処理が完全に終わったら、また「メッセージを取得する・300ミリ秒待つ」という処理を呼び出す、という事をしています。

つまり、
「メッセージを取得する・300ミリ秒待つ」の2つが終わればまた呼び出し…
「メッセージを取得する・300ミリ秒待つ」の2つが終わればまた……
といったように、条件が満たされるまで、この処理を永遠に繰り返し続けます。

その条件というのは、「設定したポーリング最大回数に達するか」「botからの新しいメッセージがあるか」の2つです。

ポーリング最大回数は、
koe-ui-basic.tag内の this.polling_max = 100; の部分を変更することで、調整できます。
>> コードはこちら

こちらのタイミング制御にも、さきほど紹介したPromiseを使っています。

これで、botからの返事を逃してしまうという事は避ける事ができました。

待機時間の体感を短くする。スピナーアニメーション

ポーリングは、内部の話であって、このままではユーザーが2〜3秒をただ待つ事に変わりはありません。

そこで、ユーザーのストレスを少しでも軽減するために、ポーリング中にはローディングのアニメーションをつける事にしました。
(このくるくる回るアイコンを、正式には「スピナー」と呼ぶそうです)

デモアニメ

これで、ユーザーに「プログラム内部で通信中です。少々お待ちください!」という事をビジュアルで伝える事ができました。

視覚情報によって、だいぶ印象が変わりますね。

さいごに

今回は、webサイトにbotを埋め込むUIライブラリを作成してみました。

これで、これまでbotのwebサイト埋め込みで、モヤモヤしていた部分が解消されたかと思います。興味が湧いた方は、ぜひ触ってみてください。まだまだ改善の余地もあるため、GitHubでのプルリク等も大歓迎です!

さてこのKoe UI、Direct Line APIのようなAPIがあるbotフレームワークであれば、Microsoft Bot Framework以外のbotとも接続できそうです。

というのも、UI部分はすでにできているので、基本的には、内部で処理しているリクエスト先・リクエスト内容を、他のbotフレームワーク用のAPI向けに変更してあげれば良いだけだからです。

ちょっと変更を加えるだけで、他のbotフレームワーク版も作れちゃうかもしれませんね。

それではー!