Node.js
lambda
APIGateway
Clova
CEK

AWS LambdaでLINE Clovaのスキルを作成する

要旨

Clova Extensions Kit(以下、CEK)が公開され,LINE Clovaのスキルを自作できるようになりました.
そこで,今回はAWS Lambdaを使用して,オリジナルスキルを作成する手順を紹介します.

今回は,例として,おみくじを行うBotを作ります.

基本的に,手順は公式のチュートリアル1に準じています.

前提

  • AWSのアカウントを作っているものとします
  • LINE Developersのアカウントを作っているものとします
  • ストアでの掲載はしないものとします(個人利用)
  • セキュリティはあまり気にしないものとします(攻撃されてもデメリットの少ないものですが...)

概要

LINE Clova

LINE Clova2はLINEが提供しているAIアシスタントですとその周辺技術の総称です.
スピーカー本体を購入し,自分のLINEアカウントを紐づけることで使用が可能になります.

スキル

Clova ExtensionはClovaの機能を拡張して、ユーザーに様々な経験を提供するWebアプリケーションです。3

そして,それは利用者側から「スキル」として利用されます.

開発者がClova Extensionを開発するときは,CEKを利用します.以下のようなデータフローになります.

image.png
https://clova-developers.line.me/guide/#/CEK/CEK_Overview.md

  1. ユーザーがそのスキルを起動してClovaに話しかける
  2. その結果に応じて「あらかじめ指定されたサーバ」にJSONがPOSTされる
  3. そのPOSTに,音声の返事内容を記載したJSONを返却する
  4. そのJSONにしたがってClovaが音声を発する

開発者は,ClovaがJSONをPOSTするサーバを用意する必要があります.

AWS Lambda

AWS Lambda はサーバーをプロビジョニングしたり管理しなくてもコードを実行できるコンピューティングサービスです。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html

簡単に言うと,クラウド場で簡単にプログラムを動かすことのできるサービスです.

また関数等を,API Gatewyと組み合わせることでWebAPIにすることが可能です.

開発の手順

以下の流れで行います.

  • 仕様の決定
  • サーバの構築
  • スキルの登録
  • 対話モデルの作成
  • テスト,使用

仕様を考える

基本的には,「ユーザが何を言ったら何を返すか」という部分を考えます.加えて,スキル起動時の応答も考えます.

今回は,例としておみくじを引くことのできるスキルを考えます.

ユーザのアクション 応答
起動 「おみくじを何回引きますか?」
「おみくじをn回引いて」 おみくじの結果を返す
その他 「おみくじを3回引いて,のように指示してください」

「その他」に関しては,ユーザーの動作確認等を入れておくと自然になるような気がします.

AWS Lambdaを用いたサーバの作成

Clovaからのアクセスに対してJSONを返却するサーバを作成していきます.

ここら辺の操作でわからない場合は,他の資料と一緒に読んで補完してください.

Lambda関数の作成

AWSサービスの中から「Lambda」を選択し,「関数の作成」をクリックします.「設計図」を選択し「microservice-http-endpoint」を選択してください.次に,以下のように設定してください.

項目 設定値 備考
名前 (各自自由) 例 : clovaOmikuji
ロール テンプレートから新しいロールを作成 変更しない
ロール名 (各自自由) 例 : clovaOmikujiRoll
ポリシーテンプレート シンプルなマイクロサービスのアクセス権限 変更しない
API Gateway トリガー 「新規APIの作成」「オープン」

設定が終わったら「関数の作成」をクリックします.

処理内容の編集

作成が完了したら,Lambdaの処理内容を変更します.

画面をスクロールするとエディタが現れます.処理内容を以下のように書き換えます.

exports.handler = (event, context, callback) => {
  let reqJson = JSON.parse(event.body);
  let text = ``;

  //ユーザのアクションによって処理を振り分ける
  switch (reqJson.request.type) {
    case 'LaunchRequest':
      text = 'ようこそ!おみくじを,いくつ引きますか?';
      break;
    case 'SessionEndedRequest':
      text = 'また遊んでくださいね';
      break;
    case 'IntentRequest':
      if(reqJson.request.intent.name == 'DrawOmikujiIntent'){
        text = drawOmikuji(reqJson);
      }else{
        text = "おみくじを3回引いて,のように指示してください";
      }
      break;
    default:
      text = "おみくじを3回引いて,のように指示してください";
  }

  //返却するJSONを用意する
  let res_json = {
    "version": "1.0",
    "sessionAttributes": {},
    "response": {
      "outputSpeech": {
        "type": "SimpleSpeech",
        "values": {
          "type": "PlainText",
          "lang": "ja",
          "value": text
        }
      },
      "card": {},
      "directives": [],
      "shouldEndSession": false
    }
  };

  //レスポンスを返す
  var res ={
    "statusCode": 200,
    "headers": {
      "Content-Type": "application/json;charset=UTF-8"
    },
    body: JSON.stringify(res_json)
  };
  callback(null, res);
};

//おみくじの結果を返すFunction
function drawOmikuji(reqJson){

  //おみくじを引く回数を取得する
  const slots = reqJson.request.intent.slots;
  let numberOfDraw = 0;
  if( slots && slots.numberOfDraw && slots.numberOfDraw.value){
    numberOfDraw = parseInt(slots.numberOfDraw.value, 10);
  }
  if( isNaN(numberOfDraw) || numberOfDraw==0 ){
    return "おみくじを3回引いて,のように指示してください";
  }

  //おみくじ結果を文字列として作成する
  const results = ["大吉","ちゅうきち","吉","凶"];
  const ctr = new Array(results.length).fill(0);

  for(let i = 0; i < numberOfDraw; i++){
      let rand = Math.floor(Math.random()*results.length);
      ctr[rand]++;
  }

  return results.map((val,i)=>val+"は"+ctr[i]+"枚").join("、")+"です";
}

処理内容を解説します.(が,LambdaやJS自体の説明はしません)

まず,postされたJSONの中身を見て,

  • TYPE : reqJson.request.type
  • INTENT_NAME : reqJson.equest.intent.name

の二つを確認し,処理を振り分けています.

ユーザのアクションは,以下のように判別することができます.

ユーザのアクション JSONの内容
起動 TYPEが'LaunchRequest'
「おみくじをn回引いて」 TYPEが'LaunchRequest'かつINTENT_NAMEが'DrawOmikujiIntent'の場合('DrawOmikujiIntent'はあとで設定)
その他 それ以外の場合

上の判定をもとに,応答する内容(変数text)を作っていきます.

次に,返答するJSONを作ります.今回は,

  • 返答が複数に別れない
  • 音楽等を流さない

ということなので,以下のような形で返答します.

返答するJSONの形式はドキュメントが参考になります.

{
  "version": "1.0",
  "sessionAttributes": {},
  "response": {
    "outputSpeech": {
      "type": "SimpleSpeech",
      "values": {
        "type": "PlainText",
        "lang": "ja",
        "value": "返答したいテキスト"
      }
    },
    "card": {},
    "directives": [],
    "shouldEndSession": false
  }
}

基本設定を変更する

エディタの下にある「基本設定」内の「メモリ」を「128 MB」に設定します.
これで,AWSの課金額が最低限になります(無料枠を超えないと思います)

(今回の場合はこれで十分ですが,重い処理をする場合は別途検討してください.)

Lambdaの保存

右上の「保存」をクリックしてください.

API Gatewayによるエンドポイントの確認

画面上部の「Designer」から「API Gateway」をクリックしてください.
下にある「API Gateway」の項目内から「clovaOmikuji-API」(この名前は皆さんの環境による)の下にある三角をクリックしてメニューを展開してください.
そして,「URL の呼び出し」にあるURLをあとで使うので,どこかにメモしてください.

スキルの登録

ここからは,LINE Developersでスキルを登録する作業になります.

チャンネルの作成

まずは,LINE Developessでログインを行ってください.

次にこのリンクからスキルを登録します.

以下のようにそれぞれ設定を行います.

項目 入力内容 備考
プロバイダー 選択 (提供者の名義) 会社だったら会社名です(ぼくはtakanakahikoにしました)
チャネル名 おみくじ 任意の名前

「作成してClova Developer Centerに移動」をクリックします.

基本設定の入力

以下のように入力して,進めてください

項目 入力例 備考
タイプ カスタム
Extension ID 例 : me.takanakahiko.clova.extension.omikuji 何でもいいですが,通常、パッケージ名とExtension名を組み合わせて作成します。
スキル名 例 : おみくじ 今回はストアに掲載しないので何でも大丈夫です
呼び出し名 例:おみくじ 「<呼び出し名>を起動して」のように使用する起動フレーズです
AudioPlayerの使用 いいえ 今回は音楽の再生はしないため
提供者について (自分の情報) ストアに掲載しないので,適当に入力してください

入力したら,下の利用規約等を読み(同意できるのであれば)同意し,「作成」をクリックしてください.

サーバ設定

ページの下にある「次へ」を押すとサーバ設定画面へ移動します

「ExtensionサーバーのURL」に,AWS Lambdaの設定中にメモしたURLを入力します.

「アカウント連携の有無」は「いいえ」を選択し「次へ」をクリックします.

ストアには掲載しないので,情報の入力はここまでです.
これ以降は入力しなくても実機でのテストでは問題ありません.

対話モデルの作成

ここからは「対話モデル」という,音声を認識してサーバへPOSTするJSONの内容を作成する仕組みを作ります.
「おみくじをn回引いて」という文言を受け付けるようにします.

まず,このリンクを開き,今回作成しているスキルの「対話モデル」項目の「修正」リンクをクリックします.

スロットタイプの登録

左のメニューから「ビルトイン スロットタイプ」の隣にある「+」ボタンをクリックします.

image.png

選択肢の中から「CLOVA.NUMBER」をチェックし,保存します.

image.png

インテントの作成

「カスタムインテント」の隣にある「+」ボタンをクリックします.

image.png

「新規のカスタムインテントを作成」で「DrawOmikujiIntent」と入力して「作成」をクリックします.

image.png

スロットの作成

スロットリストから「新規のスロットを...」と書いてある部分に「numberOfDraw」と入力し,隣にある「+」ボタンをクリックします.

image.png

スロットタイプを「CLOVA.NUMBER」に設定します.

image.png

サンプル発話リストの作成

スロットリストから「新しいサンプル発話を...」と書いてある部分に「おみくじを3回引いて」と入力し,隣にある「+」ボタンをクリックします.3はデフォルト値ですので,他の数字でも大丈夫です.

image.png

「3」の部分をドラッグで選択して「numberOfDraw」をクリックします.

image.png

対話モデルをビルドする

保存後,左上の「ビルド」ボタンをクリックします.

image.png

3~5分程度待ったらビルドが終わります.

なんか,失敗するときがありましたが,原因がわかりませんでした.
何回かやったら成功します.(多分)

対話モデルをテストする

左側のメニューから「テスト」を選んでください.

そこで例えば「おみくじを3回引いてください」と入力して「テスト」ボタンをクリックしてください.
正しい応答が表示されていれば成功です.

実機で使用する

ここでやっとClovaの端末を使用します.

自分のアカウントと紐づけてあるClovaであればそのまま使用できます.

「おみくじを起動して」
「おもくじを3回引いて」

などと話しかけてみましょう.

動画埋め込み

おわりに

作り方は以上です.

早足になってしまったため,説明が足りないかもしれません.
わからないとことがあれば,気兼ねなくコメント等で教えてください.

また,間違い等の指摘もしていただけると助かります.

ありがとうございました.