こんにちは、ブレインズテクノロジーの桑原です。
ブレインズテクノロジーは、ImpulseやNeuronといった、企業の生産性を劇的に向上させるサービス開発に従事していますが、私達自身の生産性も向上させるため、利用するシステムの探求と刷新を繰り返しています。
最近では、アマゾンウェブサービスが提供する機械学習サービスのAmazon Lexを利用して、営業記録やスケジュールの登録を簡素化できないかと模索をしていましたが、Amazon Lexとの会話は全て英語でした。
この度、Amazon Translateが日本語に対応したことを記念して、Amazon Lexとの英会話をリアルタイムに日本語に翻訳するBotを作ってみたいと思います。
Slack Botがやること
Slackでスケジュールを登録したいと呟くと、Amazon Lexが何の予定なのかや日時を聞いてくれるBotです。本記事ではAmazon Lexと会話するところまでを解説しますが、これをGoogle Calendar等のカレンダーと連携させて実際に予定を入れることもできたりします。
なお、ZapierがなくてもSlackとAWS Lambdaをつなぐことは出来ますが、今回は極力プログラムを書かないことを目指すためZapierを採用しています。
Amazon Translateとは?
深層学習モデルを使用して、従来の統計ベースやルールベースの翻訳アルゴリズムよりも正確で自然な翻訳を提供するニューラル機械翻訳サービスです。
2018年4月にサービスが提供され、当初は下記6言語が英語間翻訳に対応していましたが、
- アラビア語
- 中国語 (簡体字)
- フランス語
- ドイツ語
- ポルトガル語
- スペイン語
AWS Summit 2018 New Yorkにて、2018年7月から日本語を含めた下記6言語にも対応することが発表されました。
- 日本語
- ロシア語
- イタリア語
- 中国語 (繁体字)
- トルコ語
- チェコ語
Amazon Translateの詳細はこちら
Amazon Lexとは?
音声やテキストを使用して、任意のアプリケーションに対話型インターフェイスを構築するサービスです。
Amazon Alexaと同様、音声のテキスト変換には自動音声認識 (ASR)、テキストの意図認識には自然言語理解 (NLU) という高度な深層学習機能が使われているため、チャットBotのようなアプリケーションでリアルな会話を実現することができます。しかし、残念ながら現時点の対応言語は英語のみとなっており、日本語には対応していません (2018年8月時点) 。
Amazon Lexの詳細はこちら
Slack Botを作る
それでは、Slack Botを作っていきます。AWS Lambdaのところで簡単なプログラムを書きますが、後はポチポチするだけで構築完了です。大きくハマることがなければ1〜2時間程度で終わるはずです。
構築ステップ
Amazon LexとSlackの融合
公式サイトのマニュアルに詳しい手順が記載されているので、これを参考にしながら設定をしていきます。本記事では、少しややこしい連携設定を補足します。
- ステップ 1: Amazon Lexボットを作成する
- ステップ 2: Slackにサインアップして Slackチームを作成する
- ステップ 3: Slackアプリケーションを作成する
- ステップ 4: SlackアプリケーションとAmazon Lexボットを統合する
- ステップ 5: Slack統合を完了する
- ステップ 6: 中間テストをする
Amazon TranslateとSlackの融合
Amazon LexがSlackに返答した英語をZapierがひろってAWS Lambdaに投げる仕組みです。こちらもGUIを使ってお手軽に設定をしていきます。
- ステップ 7: Slackに着信Webフックを追加する
- ステップ 8: AWS Lambda関数に付与するロールを作成する
- ステップ 9: AWS Lambda関数を作成する
- ステップ 10: ZapierでSlackとAWS Lambdaを統合する
- ステップ 11: 統合テストをする
ステップ 1: Amazon Lexボットを作成する
AWSマネージドコンソールからAmazon Lexを選択します。いくつかサンプルが準備されていますので、今回はその中から[ScheduleAppointment]を選択します。後は、好きなようにサンプルをいじり、[Build]と[Publish]まで実行します。
なお、[Build]が完了すると画面右側の[Test Chatbot]でテストチャットを行うことができます。こちらが入力する言葉を変えても、それに応じた返答をし、アポイントを予約するところまで導いてくれることが確認できます。
ステップ 2: SlackにサインアップしてSlackチームを作成する
既存のSlackチームを使いたい場合は、このステップをとばしてOKです。
ステップ 3: Slackアプリケーションを作成する
Slack APIコンソールを開き、[Start Buildings]を押下してアプリを作成します。 [Bot Users]と[Interactive Components]の設定をした後、 [Basic Information]のClient ID、Client Secret、Verification Tokenをメモしておきます。
ステップ 4: SlackアプリケーションとAmazon Lexボットを統合する
AWSマネージドコンソールからAmazon Lexを選択します。先ほど作成したAmazon Lexボットを選択し、[Channels]タブからSlackとの連携設定をします。Client ID、Client Secret、Verification Tokenにはステップ 3のSlack APIコンソールでメモしておいた値を入力します。
[Activate]が完了するとPostback URLとOAuth URLが表示されるので、こちらをメモしておきます。
ステップ 5: Slack統合を完了する
Slack APIコンソールを開き、[OAuth & Permissions]で権限設定をしたあと、Redirect URLsにステップ 4のAWSマネージドコンソールでメモしておいたOAuth URLを入力します。
[Interactive Components]と[Event Subscriptions]のRequest URLに、ステップ 4のAWSマネージドコンソールでメモしておいたPostback URLを入力します。
これで、連携設定は完了です!
ステップ 6: 中間テストをする
Slackにログインし、テストをしたいチャンネルにSlack APIで作ったBotユーザを招待します。 ここでは、realbot子さんが#test-channelにlexbot子さんを招待しています。
少し分かりづらいのですが、realbot子さんがこちらが入力したメッセージ。lexbot子さんがAmazon Lexが返してくれているメッセージです。
このように、lexbot子さんは英語しか話せないので、次のステップ以降でAmazon TranslateとSlackを融合させて、日本語を話してもらうようにします。
ステップ 7: Slackに着信Webフックを追加する
Slack App ディレクトリを開き、着信 Webフックを追加します。
# lexbot子さんの着信 Webフックを利用してもOKですが、今回は表示名を変えたかったため、別の着信 Webフックを追加しています。
名前やアイコンを指定したあと、Webhook URLをメモしておきます。
ステップ 8: AWS Lambda関数に付与するロールを作成する
AWSマネージドコンソールからIAMを選択します。[ロール]->[ロールの作成]を押下し、AWSサービスのLambdaを選択します。
TranslateReadOnlyポリシーを選択します。
任意のロール名を入力しロールを作成します。
ステップ 9: AWS Lambda関数を作成する
AWSマネージドコンソールからAWS Lambdaを選択します。[関数の作成]を選択して、関数を一から作成します。
Zapierを利用する場合、関数の名前は必ずzapier_eval
としてください。ステップ 8で作成したロールを選択して関数を作成します。
関数コードを入れて保存します。
import json import boto3 import unicodedata from urllib.parse import parse_qs import urllib.request def chk_lang(string): for char in string: name = unicodedata.name(char) if 'CJK UNIFIED' in name or 'HIRAGANA' in name or 'KATAKANA' in name: return True return False def lambda_handler(event, context): plain_text = event['plain'] lang = chk_lang(plain_text) if lang: return {'statusCode': 101} translate = boto3.client(service_name = 'translate', region_name = 'us-east-1', use_ssl = True) response = translate.translate_text(Text = plain_text, SourceLanguageCode = 'en', TargetLanguageCode = 'ja') translated_text = response['TranslatedText'] hook = 'https://hooks.slack.com/services/xxxxx/xxxxx' #ステップ 7で確認したWebhook URLを入力 headers = {'Content-Type' : 'application/json'} method = 'POST' json_data = {'text' : '`(ja) ' + translated_text + '`'} json_data = json.dumps(json_data).encode('utf-8') request = urllib.request.Request(hook, data = json_data, method = method, headers=headers) urllib.request.urlopen(request) return translated_text
ステップ 10: ZapierでSlackとAWS Lambdaを統合する
Zapier Exploreを開き、[Make a Zap!]を選択します。
# Zapierは様々なサービスを無料で連携させることができますが、AWS Lambdaを連携させる場合は有償となります。
Triggerは、SlackにNew Message Posted to Channelがあった場合とします。
Channelを指定し、Trigger for Bot Messages?をnoからyesに変更します。
今回は、Invoke Functionを選択します。返り値を受け取ってあれこれしたい場合はRun Codeがいいでしょう。
Functionにはステップ 9で作成したzapier_eval
を選択、Argumentsでeventオブジェクトに渡すデータとしてSlackのTextを指定します。
ZapのステータスをONにしたら、全ての設定が終了です。ふぅ
ステップ 11: 統合テストをする
Slackにログインし、realbot子さんがlexbot子さんに話しかけます。すると、tranbot子さんが英語を日本語に翻訳してくれました!
おわりに
トリガーとなる英語を適切に入力しないとAmazon Lexは反応してくれませんが、Hi (やあ) やHello (こんにちは) といった簡単な言葉をトリガーにしておけば、
- 英語で入力
- 英語で返答 (by Amazon Lex)
- 日本語に翻訳 (by Amazon Translate)
から
- 日本語で入力
- 英語に翻訳 (by Amazon Translate)
- 英語で返答 (by Amazon Lex)
- 日本語に翻訳 (by Amazon Translate)
とすることもできそうです。
それが実現できると、InputとOutputの言語はAmazon Translateが対応する12言語を自由に組み合わせることができるようになります。 Amazon Lexが英語にしか対応していなくても、多言語コミュニケーションが可能になる訳ですね。
余談
無茶なキーワードを入れたら返ってきた返答です。普段は敬語のtranbot子さんですが、たまに不機嫌になるのでご注意を (笑)
ブレインズテクノロジーでは「共に成長できる仲間」を募集中です。
採用ページはこちら