ChatBot入門-Slack×GAS×docomo雑談対話APIで簡単開発


はじめに

私のチームのボス(社外取締役)は、
業界(特にWebフロント界隈)で有名なフリーランスのエンジニアです。

日頃から、
「SlackさえOnになってたら、どこで仕事しててもいいよ。」
「進捗はGitのコミットログで見るから。」
と言っています。

この方針はすごく有難いです。

これはつまり、Gitの更新は置いておいて、、
Slackでメンション指定で呼びかけられた際にリアクションすれば、
仕事していることになるってことですよ!

ちょっと待てよ。

私はここで気が付いたわけです。

これって今流行りのchatbotでできるんじゃないかと!

Slackでメンション指定で呼びかけられた際に、
とりあえずchatbotでリアクションしておけば、
何も考えずに担当業務に集中できるんじゃないかと。
(最悪、昼寝しててもいけるんじゃないかとw)

ということで、
上司・同僚からSlackで呼びかけられた際に、
自分の代わりにレスポンスしておいてくれるchatbotを作ることにしました。

開発

chatbotの開発事例については、既にQiita上でたくさんの方々が紹介されていましたので、
今回、とても簡単に開発できてしまいました。

先人の方々、本当にありがとうございます。m(_ _)m

リンクと合わせて私が躓いた点をご紹介します。

まずchatbotについて何も知りませんでしたが、以下2つの記事で開発の流れを掴むことができました。
【Botブームに乗り遅れた人たち用】Chat Bot(チャットボット)についてまとめてみたよ。

今さら聞けない、雑談LINE BOTの作り方(1)「おじさんだって、ボットをつくってもいいじゃないか」

開発の流れ

開発の流れは以下の通りです。
1. Slackにて自分宛に投稿があった際に、GoogleAppsScriptに投稿データを飛ばす
2. GoogleAppsScriptで受け取った投稿データから投稿内容を抽出する
3. 抽出した投稿内容をdocomo雑談対話APIに飛ばす
4. docomo雑談対話APIから返ってきたコメントをSlackにBotアカウントで投稿する

Slack上での自身の過去の投稿ログやら何やらから、
自分の投稿を真似る対話エンジンも作りたいと妄想していたのですが、
社内のDeepLearning専門家に相談したら、
よくわからないワードが滝のように降ってきたので、、
今回は、docomo雑談対話APIを使用させて頂くこととしましたm(_ _)m

1. Slackにて自分宛に投稿があった際に、GoogleAppsScriptに投稿データを飛ばす

こちらの記事を参照させて頂きました。
初心者がGASでSlack Botをつくってみた

記事の「2. GASからSlackにメッセージを投稿する 2.1~2.3」の通り、
まずはGoogleAppsScript(以降、GAS)のプロジェクトを作成します。

次に「3. 投稿に反応してメッセージを返す 3.1」の通り、Outgoing WebHooksを設定します。

この時、自分のユーザー名をトリガーとしたいので、
Trigger Word(s)には、「@ユーザー名」と設定していましたが、
これだと上手くフックにかかりませんでした。。

どうやら@付きのメンションの場合、
Slack上でユーザーへのリンクとなっているため、独自のマークアップになっているようです。
詳しくは公式マニュアルにあります。

ですので、Trigger Word(s)を適当な文字(メンションではない)に設定し、
トリガーとしたいユーザーで設定したTrigger Word(s)を含む投稿を行います。

GASにSlackからのPOSTデータが届いたら、


function doPost(e) {
  // パラメーターを取得
  var userId = e.parameter.user_id;
  ~省略~
}

ような形でuserIdをダンプすれば、
<@U4PP6NXHC>※といった形式のユーザーIDが確認できます。
※例です。

このユーザーID(<@U4PP6NXHC>)をTrigger Word(s)に指定することで、
無事、@付きのメンションでもフックできるようになりました。

これでSlackでメンション指定で呼びかけられた際に、
GASに投稿データが飛んできます。

ちなみに、投稿者以外のユーザーIDを確認したい場合は、
投稿文の中に、@付きのメンションを含め、
GASでe.parameter.textの中身を確認すればOKでした。

2. GoogleAppsScriptで受け取った投稿データから投稿内容を抽出する

初心者がGASでSlack Botをつくってみた
で説明頂いている通り、SlackからOurgoing WebHooksのリクエストがあった際、
doPost()が実行されます。

POSTされた投稿データを引数eとして、受け取ることができますので、
以下のように、投稿データからtokenuser_idtextを取得します。
text(投稿内容)からは、含まれる@付きメンション部分を削除しています。


function doPost(e) {
  // パラメーターを取得
  var token = e.parameter.token;
  var userId = e.parameter.user_id;
  var text = e.parameter.text;
  // 念のため、今回作成したOutgoing WebHooks以外からのアクセスを弾く。
  if (token != "Outgoing WebHooksのToken") {
    return;
  }
  // 最初の@付きのメンション<@U4PP6NXHC>は余分なので削除
  text = text.substring(13);
}

3. 抽出した投稿内容をdocomo雑談対話APIに飛ばす

まずdocomo Developer supportの公式サイトから、
雑談対話APIの利用申請を行います。

利用申請を行うと、
以下のAPI利用申請・管理画面からAPI keyが確認できます。

そして、今さら聞けない、雑談LINE BOTの作り方(1)「おじさんだって、ボットをつくってもいいじゃないか」で説明頂いている以下のコードのdialogueUrlの値をhttps://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=ドコモ雑談対話APIのAPI keyとすることで、ドコモ雑談対話APIにリクエストを送ることができるようになります。


// ドコモ雑談会話にメッセージを投げ、気の利いた回答を受け取る関数
function getDialogueMessage(userId, mes) {
  var dialogue_options = {
    'utt': mes
  }
  var options = {
    'method': 'POST',
    'contentType': 'text/json',
    'payload': JSON.stringify(dialogue_options)
  };

  // ここでドコモ雑談会話エンドポイントにメッセージを投げる
  var response = UrlFetchApp.fetch(dialogueUrl, options);

  // ドコモAIからの回答はJSON形式なのでオブジェクト変換
  var content = JSON.parse(response.getContentText());

  // ドコモAIから取得した回答部分を呼び出し元に戻す
  return content.utt;
}

4. docomo雑談対話APIから返ってきたコメントをSlackにBotアカウントで投稿する

docomo雑談対話APIからの回答をSlack上の自分のアカウントでSlackに投稿することもできますが、
そうしてしまうと、もはや唯の自動返信になってしまうと考えまして、
あくまでBotの体を取ることとしました。

まずSlackのCustom Integrationsの画面から、Botの統合を追加します。

Botの統合を行うと、API Tokenが確認できますので、
以下のコードのBotのAPI Tokenの箇所に設定します。


  //Create an instance.
  var slackApp = SlackApp.create("BotのAPI Token"); 
  // Return Response
  slackApp.chatPostMessage(e.parameter.channel_id, message, {
  "username" : "kanata2",
  "icon_emoji" : ":suzu:"
  });
  //sendResponse(message);
  return null;
}

usernameには、先ほど作成したBotの名前を設定します。
icon_emojiは、Botが投稿する際のアイコン表示に使用するものです。
自分がSlackでアイコンとしている画像データをemoji登録し、
emojiの名前を設定しました。

完成したGASでのコードは以下の通りです。


function doPost(e) {
  // パラメーターを取得
  var token = e.parameter.token;
  var userId = e.parameter.user_id;
  var text = e.parameter.text;
  if (token != "Outgoing WebHooksのToken") {
    return;
  }
  // 最初の@付きのメンション<@U4PP6NXHC>は余分なので削除
  text = text.substring(13);
  // メッセージの生成
  var message = "<@"+userId+"> "+getDialogueMessage(text);

  //Create an instance.
  var slackApp = SlackApp.create("BotのAPI Token");
  // レスポンスを返す
  slackApp.chatPostMessage(e.parameter.channel_id, message, {
  "username" : "kanata2",
  "icon_emoji" : ":suzu:"
  });
  //sendResponse(message);
  return null;
}

// ドコモ雑談会話にメッセージを投げ、気の利いた回答を受け取る関数
function getDialogueMessage(mes) {
  var dialogue_options = {
    'utt': mes
  }
  var options = {
    'method': 'POST',
    'contentType': 'text/json',
    'payload': JSON.stringify(dialogue_options)
  };

  // ここでドコモ雑談会話エンドポイントにメッセージを投げる
  var response = UrlFetchApp.fetch("https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=ドコモ雑談対話APIのAPI key", options);

  // ドコモAIからの回答はJSON形式なのでオブジェクト変換
  var content = JSON.parse(response.getContentText());

  // ドコモAIから取得した回答部分を呼び出し元に戻す
  return content.utt;
}

まとめ


このような形で自分宛のメンション指定で呼びかけられた際に、chatbotがレスを返してくれるようになりました。

今回使用したdocomo雑談対話APIの他にも、無償で使用できる対話エンジンがないか調べてみたところ、

先日のニュースで、

リクルートテクノロジーズは3月16日、機械学習やディープラーニングを使ったソリューションAPI群「A3RT(アート)」の無料公開を発表した。
リクルート、“プライベートAI”を開放, 2017/03/15, ITpro

と発表され、公開されたAPIの中に、

■Talk API
様々なアプリケーション上でユーザーとの対話を自動化するAPI。入力文から応答文を自動生成する。日常会話レベルでの応答が可能。

というものがありました。

公式サイトはこちらです。

docomo雑談対話APIと同じ感覚で使用できそうなので、次、使ってみようと思います。

お付き合い頂きありがとうございましたm(_ _)m