前書き
AWSのTranslateが少し前に日本語に対応しました。
翻訳系もGoogleから少し離れれるのかなぁと思ったぐらいで特に気にしていなかったのですが
AWSのサービスをみていて「Comprehend」というサービスがあるのに気づきました。
--
Amazon Comprehend は、機械学習を使用してテキスト内でインサイトや関係性を検出する自然言語処理 (NLP) サービスです。機械学習の経験は必要ありません。
--
昔から機械学習とかには興味があったのですが、敷居が高く手が出せず。。。
ですが、Comprehendを利用することで簡単に自然言語処理ができます。
単語と単語の関係や、単語の抜き出し、あとは感情分析ができるということです。
ですが、日本語には対応していないらしく...というのを知った際に、 Translateの日本語対応を思い出しました。
というわけで、入力された日本語を英語に変換してそれの感情分析を行うLINE BOTを作ってみました。
構成
ざつですが、ざっくり↓みたいな感じです。
LINE BOTへのメッセージをWebHookでAPI Gatewayが受け取り、Lambda側で
まず、言語を英語へTranslateで変換して、Comporehendへ渡して感情を数値化して、LINE BOTへ返信を行います。
WebHook作成
LINE Developerの設定やLambdaなどの構成については割愛します。
Serverless FrameworkのPythonテンプレートで作成します。
serverless.yaml
Yaml的にはこんな感じです。
service: comprehend-bot
provider:
name: aws
runtime: python3.6
stage: v1
region: us-east-1
functions:
bot_hook:
handler: handler.bot_hook
events:
- http:
path: bot/hook
method: post
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
dockerizePip: true
iamRoleStatements:
- Effect: "Allow"
Action:
- "dynamodb:*"
- "comprehend:*"
- "translate:*"
Comprehendのリージョン的に、東京リージョンだと使えないためバージニアにしています。
特筆事項としては、iamRoleにtranslateとcomprehendを足しています(dynamodbは特に使いませんが、メッセージを保存とかの際に利用できます)
あと、Pythonのline-bot-sdkを使いますので、reruirementsを使用します。
requests==2.18.4
flask
line-bot-sdk
serverlessを利用せずにzipでやる場合は必要ありませんが、serverless-python-requirementsを使う場合はdockerが必要になります。
API実装
Pythonのboto3を使って実装します。
処理の流れ的には、
- Lineのメッセージを受け取る
- Translateで英語に翻訳
- Comprehendで感情を分析
- Lineへ返す。
みたいな流れです。
ソース的にはこんな感じ
# -*- coding: utf-8 -*-
import os
import sys
import logging
import json
import boto3
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,
)
# 翻訳
translate = boto3.client('translate')
# 言語処理
comprehend = boto3.client('comprehend')
logger = logging.getLogger()
logger.setLevel(logging.INFO)
LINE_CHANNEL_ACCESS_TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]
LINE_CHANNEL_SECRET = os.environ["LINE_CHANNEL_SECRET"]
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)
def bot_hook(event, context):
line_event = json.loads(event['body'])['events'][0]
logger.info(line_event)
# 引数テキストを英語変換
trans = translate.translate_text(
Text=line_event['message']['text'],
SourceLanguageCode='auto',
TargetLanguageCode='en'
)
translatedText = trans['TranslatedText']
logger.info(translatedText)
# 感情表現を取得
detect_sentiment = comprehend.batch_detect_sentiment(
TextList = [
translatedText
],
LanguageCode='en'
)
logger.info(detect_sentiment)
logger.info(detect_sentiment['ResultList'][0]['Sentiment'])
sentiment = detect_sentiment['ResultList'][0]['Sentiment']
line_bot_api.reply_message(
line_event['replyToken'],
TextSendMessage(text=sentiment)
)
response = {
"statusCode": 200
}
return response
boto3が便利すぎますね笑
boto3のtranslateとcomprehendで翻訳と感情分析を行います。
comprehendの返り値はこんな感じ
'Sentiment': 'NEGATIVE',
'SentimentScore': {'Positive': 0.05495094880461693, 'Negative': 0.8831858038902283, 'Neutral': 0.03225637972354889, 'Mixed': 0.02960692159831524}}
非常に面白いです。
Sentimentに入るのが、リクエストされた言葉の感情
SentimentScoreにあるのが、それぞれの感情数値です。
POSITIVE, NEGATIVE, NEUTRAL, MIXED の4つで数値化されます。
その中で一番高いのが、Sentimentに入ります。
そのため、 レスポンスのSentimentをLineへ返すのが、下記の処理です。
line_bot_api.reply_message(
line_event['replyToken'],
TextSendMessage(text=sentiment)
)
はい。実装は以上です。
デプロイ、動作確認
sls deployでLambdaをデプロイして、API GatewayのパスをLineのWebhookとして設定します。
(すみません。割愛します。)
あとは、LINE BOTに対して、メッセージを送ります。
うまくいけば、こんな感じ。
(今まで喋ることがなかったオリキャラBOTが動きました。)
はい。以上です。
メッセージですが、これだとTHE BOTなので
せっかく、他の感情数値もComprehendがくれているので、下記みたいな感じで Formatしても面白いですね。
あとがき
正直なところ、これといって使い道がありませんが、
Translateと組み合わせれば、日本語の感情分析もなんとなくできるので
ツイートの分析とか、統計で何か面白い使い道があるかなと思います。
AWSは単一のサービスで見ても面白いですが、さらに夢を広げるために別サービスを利用することの楽しみが
さらに広がった一件でした♪