[Amazon Lex] HTML+JavaScriptで作成したLexクライアントでカード情報の表示に対応してみました。

1 はじめに

こんにちは、Alソリューション部の平内(SIN)です。

Amazon Lex(以下、Lex)のAPIであるPostText()のレスポンスには、カード情報を追加することが出来ます。

今回は、前回作成したLexクライアントで、このカード情報を表示できるようにして見ました。
[Amazon Lex] HTML+JavaScriptでLexクライアントを作ってみました)

最初に、動作しているようすです。花の種類を聞き取る段階で、送られてきたカードを表示しています。選択は、ボタンで行うことも出来ます。

2 Prompt response cards

カードの情報は、コンソールでもLambdaからでも設定可能です、今回は、コンソールで以下のように設定しました。

3 ResponseCardオブジェクト

ResponseCardにセットされるオブジェクトの内容は以下のとおりです。

(1) ResponseCard

ResponseCardの各アイテムは、以下のとおりです。

Name Type Required Detail
contentType String No application/vnd.amazonaws.card.generic
genericAttachments Array of GenericAttachment No 0〜10個のアイテム
version String No ResponseCardのフォーマットのバージョン


参考:ResponseCard

(2) GenericAttachment

ResponseCardのgenericAttachments配列に設定されるオブジェクトで、表示されるオプションを表します。 画像、ボタン、リンク、又はテキストです。

Name Type Required Detail
attachmentLinkUrl String No 1〜2048文字
buttons Array of Button No 0〜5個のアイテム
imageUrl String No 1〜2048文字
subTitle String No 1〜80文字
title String No 1〜80文字


参考:GenericAttachment

(3) Button

GenericAttachmentのbuttons配列に設定されるオブジェクトで、表示されるテキスト及び、それを押されたときに返す値です。

Name Type Required Detail
text String Yes 1〜15文字
value String Yes 1〜1000文字


参考:Button

4 クライントの実装

実装したコードは、以下のとおりです。 Lexからの戻り値にresponseCardがあった時に、それを表示しています。

<!DOCTYPE html>
<html>

<head>
    <h1><center>Order Flowers</center></h1>
  <script src="https://sdk.amazonaws.com/js/aws-sdk-2.283.1.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

  <style language="text/css">

    div#logView {
      background-color:darkturquoise;
      border: 1px solid #ccc;
      padding: 4px; 
      width: 400px;
      height: 500px;
      overflow: scroll;
    }

    div#logView2 {
      background-color:darkturquoise;
      border: 1px solid #ccc;
      padding: 4px; 
      width: 400px;
      height: 500px;
      overflow: scroll;
    }

    .card {
      float: left;
      padding: 4px; 
      background-color:white;
      text-align:center;
    }
    .card img {
      width: 100%;
    }
    .card button {
      margin: 2px; 
      width: 60%;
      height:30px;
      border-radius:10px;
      background-color:royalblue;
      color:white;
      font-weight:bolder;
    }
    .card .title {
      font-weight:bolder;
    }

    input#message {
        padding: 4px;
        font-size: 1em;
        width: 400px
    }

    log {
        margin: 4px;
        padding: 4px;
        border-radius: 4px;
        min-width: 50%;
        max-width: 85%;
    }

    log.req {
        float: left;
        background-color:white;
    }

    log.res {
        text-align: right;
        float: right;
        background-color:beige;
    }
    log.err {
        text-align: right;
        float: right;
        color: #f77;
    }
    </style>

</head>

<body>
  <script>

    $('#message').focus();

    AWS.config.region = 'us-east-1';
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: 
      'us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx',
    });

    const lexruntime = new AWS.LexRuntime();
    let sessionAttributes = {};


    const botAlias = '$LATEST';
    const botName = 'OrderFlowers';
    const userId = 'id-' + Date.now();

    function pushChat() {

      const message = $('#message').val().trim();
      if(message.length > 0) {

        $('#message').val('');

        const params = {
          botAlias: botAlias,
          botName: botName,
          inputText: message,
          userId: userId,
          sessionAttributes: sessionAttributes
        };

        appendLog(message, 'req');

        lexruntime.postText(params, function(err, data) {
          if (err) {
            console.log(err, err.stack);
            appendLog(err.message, 'err');
          }
          if (data) {
            console.log(JSON.stringify(data));
            sessionAttributes = data.sessionAttributes;
            appendLog(data.message, 'res');
            if(data.responseCard) {
              appendCard(data.responseCard);
            }
          }
        });
      }
      return false;
    }

    function appendLog(message, className) {
      $('<log>', { class:className, text:message }).appendTo('#logView');
      $('#logView').scrollTop(self.innerHeight);
    }

    function appendCard(responseCard) {
      const genericAttachments = responseCard.genericAttachments;
      genericAttachments.forEach(genericAttachment => {
        const card = $('<div class="card"></div>');
        const imageUrl = genericAttachment.imageUrl;
        const title = genericAttachment.title;
        const subTitle = genericAttachment.subTitle;
        $('<img src=' + imageUrl + '>').appendTo(card);
        $('<div class="title">' + title + '</div>').appendTo(card);
        $('<div>' + subTitle + '</div>').appendTo(card);

        const buttons = genericAttachment.buttons;
        buttons.forEach(button => {
            const b = $('<button>' + button.text + '</button>');
            b.click(function(){
              $('#message').val(button.value);
              pushChat();
            });
            b.appendTo(card);
        })
        card.appendTo('#logView');
      });
      $('#logView').scrollTop(self.innerHeight);
    }

  </script>
        <div id="logView"></div>
    <form onsubmit="return pushChat();">
          <input type="text" id="message" size="80" value="">
      </form>
</body>

</html>

5 最後に

今回は、HTML+JavaScriptのLexクライアントでカード情報に対応してみました。

何故(当然)か、オーディオ対応のPostContent()では、ResponseCardを返すことが出来ません。

ってことは、音声対応のLexクライアントでは、音声でもボタンでも応答可能なリッチなクライアントは、ResponseCardでは、対応できないことになります。

Lambda側の実装で、SessionAttributesに、ResponseCardと同じ内容を返すなどの工夫が必要のようです。次回は、この辺の仕様を検討して、音声対応のLexクライアントでもカード表示に対応させて見たいと思います。

6 参考リンク


Amazon Lex Runtime Service » PostText
[Amazon Lex] HTML+JavaScriptでLexクライアントを作ってみました)
[Amazon Lex] HTML+JavaScriptでLexクライアントを作ってみました(音声対応)


弊社ではAmazon Connectのキャンペーンを行なっております。

3月に引き続き、4月も「無料Amazon Connectハンズオンセミナー」を開催致します。導入を検討されておられる方は、是非、お申し込み下さい。

また音声を中心とした各種ソリューションの開発支援も行なっております。

コメントは受け付けていません。