LoginSignup
16
15

More than 5 years have passed since last update.

PHPで書いたLINE BOTからWatson ConversationのREST APIを叩く

Posted at

LINE Bot Awardsの締め切りも間もなくですね。
LINE Bot Awards

何かいい対話APIがないか調べていた所、Watson Conversationがかなりいい精度で学習機能もあるので、LINE BOTに組み込んでみることにしました。

Watson Conversationの特徴

  • 対話シミュレーションを実現するシステム
  • 自然言語処理能力を備えている
  • インテント(意図)、エンティティ(対象)、ダイアログ(トリガー+レスポンス)を組み合わせて対話シナリオを作る
  • 対話のシナリオはブラウザで。割りと使いやすい。専門知識不要
  • 学習も同じく、ミスってるところをクリックして修正してやればすぐに反映
  • スクリプト書いて制御するようなことも可能。

登録

Bluemix

のアカウントを作ってから、サービスの1つとしてConversationを紐付ける形。
「組織」を作る時に米国南部を選択しておかないと後でサービスが行方不明になるので気をつける。

結構面倒くさい。

対話シナリオの作成

ここに完璧にまとまっているのでこの通りにすれば簡単です。感謝。

LINE BOTとの接続

LINE BOTをHerokuとPHPで作っていたのですが、Watson ConversationにはPHPのSDKがありません。Javaとかはあります。

ですがREST APIがあるのでこれを使って叩きます。

こんな感じ。

index.php
<?php

require_once __DIR__ . '/vendor/autoload.php';

$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient('YOUR_LINEBOT_ACCESS_TOKEN');
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => 'YOUR_LINEBOT_CHANNEL_SECRET']);

$signature = $_SERVER['HTTP_' . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];
try {
  $events = $bot->parseEventRequest(file_get_contents('php://input'), $signature);
} catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) {
  error_log('parseEventRequest failed. InvalidSignatureException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) {
  error_log('parseEventRequest failed. UnknownEventTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) {
  error_log('parseEventRequest failed. UnknownMessageTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) {
  error_log('parseEventRequest failed. InvalidEventRequestException => '.var_export($e, true));
}

foreach ($events as $event) {
  if (!($event instanceof \LINE\LINEBot\Event\MessageEvent)) {
    error_log('Non message event has come');
    continue;
  }
  if (!($event instanceof \LINE\LINEBot\Event\MessageEvent\TextMessage)) {
    error_log('Non text message has come');
    continue;
  }

  $data = array('input' => array("text" => $event->getText()));

  if(getLastConversationData($event->getUserId()) !== PDO::PARAM_NULL) {
    $lastConversationData = getLastConversationData($event->getUserId());

    $data["context"] = array("conversation_id" => $lastConversationData["conversation_id"],
      "system" => array("dialog_stack" => array(array("dialog_node" => $lastConversationData["dialog_node"])), 
      "dialog_turn_counter" => 1,
      "dialog_request_counter" => 1));
  }

  // https://www.ibmwatsonconversation.com で取得可能
  $url = 'https://gateway.watsonplatform.net/conversation/api/v1/workspaces/' . 'YOUR_CONVERSATION_WORKSPACE_ID' . '/message?version=2016-09-20';
  $curl = curl_init($url);

  $options = array(
    CURLOPT_HTTPHEADER => array(
      'Content-Type: application/json',
    ),
    // https://console.ng.bluemix.net/ で取得可能
    CURLOPT_USERPWD => 'YOUR_BLUEMIX_USERNAME' . ':' . 'YOUR_BLUEMIX_PASSWORD',
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($data),
    CURLOPT_RETURNTRANSFER => true,
  );

  curl_setopt_array($curl, $options);
  $jsonString = curl_exec($curl);
  $json = json_decode($jsonString, true);

  $conversationId = $json["context"]["conversation_id"];
  $dialogNode = $json["context"]["system"]["dialog_stack"][0]["dialog_node"];

  $conversationData = array('conversation_id' => $conversationId, 'dialog_node' => $dialogNode);
  setLastConversationData($event->getUserId(), $conversationData);

  $outputText = $json['output']['text'][count($json['output']['text']) - 1];

  replyTextMessage($bot, $event->getReplyToken(), $outputText);
}

function setLastConversationData($userId, $lastConversationData) {
  $conversationId = $lastConversationData['conversation_id'];
  $dialogNode = $lastConversationData['dialog_node'];

  // conversation_idとdialog_nodeをDBとかに保存
}

function getLastConversationData($userId) {
  // 保存しておいたconversation_idとdialog_nodeを取得
}

?>

conversation_idとdialog_nodeがないと過去の会話データが取れないので階層をまたぐ会話が出来ません。

結果

LINE BOTから自分が作成したWatson Conversationのワークスペースにアクセスし、対話が出来るようになりました。

まとめ

シナリオ対話型のチャットボットは、特に難しいことやらなくてもコンテンツやセンス次第で面白いボットが作れると思うので、何か作ってみたい方にはおすすめです。

尚、Bot Awardsにも対話エンジン部門があるようです。

16
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
15