LINE Botで返答するときに、Botに投げかけられたメッセージを感情分析して、テキストとスタンプで返答してみました。
LINE Botの準備
CodeZineの「日本一わかりやすいLINE Bot開発講座」を参考にして準備しました。
http://codezine.jp/article/corner/686
利用した言語とサーバも同様です。
利用言語 | サーバ |
---|---|
PHP | Heroku |
利用した感情分析API
Google Cloud PlatformのCLOUD NATURAL LANGUAGE APIを利用。
https://cloud.google.com/natural-language/
※現在ベータ期間中で、テキスト レコードと呼ばれる測定単位を利用して無料、有料を判断しています。以下のページをご覧ください。
https://cloud.google.com/natural-language/pricing
感情分析APIを利用するための準備 1
まずはGoogle Cloud Plaformサイト上で準備が必要です。
- Google Cloud Platformへの申し込み ※1
- LINE Bot向けのプロジェクトの作成 ※1
- サービスアカウントの作成とダウンロード ※2
※1 1と2の参考サイト
http://www.apps-gcp.com/gcp-startup/
※2 3の参考サイト
https://www.magellanic-clouds.com/blocks/guide/create-gcp-service-account-key/
この例の通り、JSONファイルを保存します。
「3. サービスアカウントの作成とダウンロード」の補足
3で用意したJSONファイルをBotの処理を記述するPHP上で、環境変数に設定することで、CLOUD NATURAL LANGUAGE APIを利用できるようになります。
JSONファイルを、サーバ上のBotの処理を行うPHPが読み取れる場所にアップロードしてください。
感情分析APIを利用するための準備 2
CLOUD NATURAL LANGUAGE APIをPHP上から呼び出すために、Google Cloud Client Library for PHPを利用します。
https://github.com/GoogleCloudPlatform/google-cloud-php
ダウンロードは、上記サイトのREADME.mdのQuick Startにあるように、ローカルPC上のBotのPHPファイルがあるディレクトリで、composerで行いました。
$ composer require google/cloud
感情分析APIを盛り込んだソース
CodeZineの「日本一わかりやすいLINE Bot開発講座」2回目「LINE Bot開発の概要と実装の基本」で紹介されている、スタンプとメッセージを返答するソースを元に作成しました。感情分析用に追加したのは主に1〜5の処理です。
<?php
require_once __DIR__ . '/vendor/autoload.php';
# 1. Google Cloud client libraryをインポート
use Google\Cloud\Language\LanguageClient;
# 2. Google Cloud Natural Languageのクライアントを生成
$language = new LanguageClient([
'projectId' => '[Google Cloud Platformのプロジェクト名を記載]'
]);
# 3. Google Cloud Platformのプロジェクトのサービスアカウントに関する設定
# 環境変数にサービスアカウントのJSONファイルの置き場所を指定する
putenv('GOOGLE_APPLICATION_CREDENTIALS='.dirname(__FILE__) . '[アップロードしたサービスアカウントのJSONファイルを指定]');
# LINE BOTの処理
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(getenv('CHANNEL_ACCESS_TOKEN'));
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => getenv('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;
}
$profile = $bot->getProfile($event->getUserId())->getJSONDecodedBody();
$text = $event->getText();
# 4. BOTに送られてきたテキストの感情を調べる
$annotation = $language->analyzeSentiment($text);
$sentiment = $annotation->sentiment();
$score = $sentiment['score']; //scoreの範囲は-1から1
# 5. scoreに応じて返信するテキストとスタンプを設定する
if ($score >= 0) {
$message = "楽しそうですね!";
$stkid = 138;
}
else {
$message = "悲しそうですね…";
$stkid = 111;
}
$message .= "(スコア:".$score.")";
# 回答する
$bot->replyMessage($event->getReplyToken(),
(new \LINE\LINEBot\MessageBuilder\MultiMessageBuilder())
->add(new \LINE\LINEBot\MessageBuilder\TextMessageBuilder($message))
->add(new \LINE\LINEBot\MessageBuilder\StickerMessageBuilder(1, $stkid))
);
}
?>
CLOUD NATURAL LANGUAGE APIのレスポンス
感情分析した結果については以下を参照してください。
https://cloud.google.com/natural-language/docs/reference/rest/v1beta1/Sentiment
今のところ利用できるのはscoreだけかなと思いました。
LINE Botの実行結果
補足:Herokuを利用する場合
CodeZineの記事の通り、サーバにHerokuを利用する場合、「Google Cloud Client Library for PHP」内のRequestBuilder.phpでエラーが発生しました。
デバッグしたところ、Herokuであるディレクトリ階層以下でPHPの関数file_get_contentsがエラーとなっていたため、読み込もうとしていたJSONファイルの場所と、RequestBuilder.phpの処理を一部変更することで対応しました。
RequestBuilder.phpの場所(composerを利用した場合)
[BotのPHPを置いてある場所]/vendor/google/cloud/src/Core/RequestBuilder.php
エラー内容
2017-05-14T08:03:55.072470+00:00 app[web.1]: [14-May-2017 08:03:55 UTC] PHP Warning: file_get_contents(/app/vendor/google/cloud/src/language/Connection/ServiceDefinition/language-v1.json): failed to open stream: No such file or directory in /app/vendor/google/cloud/src/Core/RequestBuilder.php on line 139
対応内容1
デバッグの結果、[BotのPHPを置いてある場所]/vendor/google/cloud/src/languageまではfile_get_contentsが正常に動いていたので、[BotのPHPを置いてある場所]/vendor/google/cloud/src/language/Connection/ServiceDefinition/language-v1.jsonを、[BotのPHPを置いてある場所]/vendor/google/cloud/src/languageにコピーしました。
対応内容2
RequestBuilder.phpで対応内容1のJSONファイルを読み込むように以下のように変更しました。
/**
* @param string $servicePath
* @return array
*/
private function loadServiceDefinition($servicePath)
{
if ($servicePath == "/app/vendor/google/cloud/src/language/Connection/ServiceDefinition/language-v1.json") {
$servicePath = str_replace("language/Connection/ServiceDefinition", "Language", $servicePath);
}
return $this->jsonDecode(
file_get_contents($servicePath, true),
true
);
}