Technology Topics by Brains

ブレインズテクノロジーの研究開発機関「未来工場」で働くエンジニアが、先端オープン技術、機械学習×データ分析(異常検知、予兆検知)に関する取組みをご紹介します。

まだ日本語対応していないAmazon LexのBotをAmazon Translateで翻訳させてみた

こんにちは、ブレインズテクノロジーの桑原です。

ブレインズテクノロジーは、ImpulseやNeuronといった、企業の生産性を劇的に向上させるサービス開発に従事していますが、私達自身の生産性も向上させるため、利用するシステムの探求と刷新を繰り返しています。

最近では、アマゾンウェブサービスが提供する機械学習サービスのAmazon Lexを利用して、営業記録やスケジュールの登録を簡素化できないかと模索をしていましたが、Amazon Lexとの会話は全て英語でした。

この度、Amazon Translateが日本語に対応したことを記念して、Amazon Lexとの英会話をリアルタイムに日本語に翻訳するBotを作ってみたいと思います。

f:id:brains-tech:20180830010820p:plain:w200
アマゾンウェブサービスが提供する機械学習サービス

Slack Botがやること

Slackでスケジュールを登録したいと呟くと、Amazon Lexが何の予定なのかや日時を聞いてくれるBotです。本記事ではAmazon Lexと会話するところまでを解説しますが、これをGoogle Calendar等のカレンダーと連携させて実際に予定を入れることもできたりします。

なお、ZapierがなくてもSlackとAWS Lambdaをつなぐことは出来ますが、今回は極力プログラムを書かないことを目指すためZapierを採用しています。

f:id:brains-tech:20180826220337p:plain

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]まで実行します。

f:id:brains-tech:20180830124454p:plain

なお、[Build]が完了すると画面右側の[Test Chatbot]でテストチャットを行うことができます。こちらが入力する言葉を変えても、それに応じた返答をし、アポイントを予約するところまで導いてくれることが確認できます。

f:id:brains-tech:20180826234133p:plain:w300

ステップ 2: SlackにサインアップしてSlackチームを作成する

既存のSlackチームを使いたい場合は、このステップをとばしてOKです。

ステップ 3: Slackアプリケーションを作成する

Slack APIコンソールを開き、[Start Buildings]を押下してアプリを作成します。 [Bot Users]と[Interactive Components]の設定をした後、 [Basic Information]のClient IDClient SecretVerification Tokenをメモしておきます。

f:id:brains-tech:20180827112047p:plain

ステップ 4: SlackアプリケーションとAmazon Lexボットを統合する

AWSマネージドコンソールからAmazon Lexを選択します。先ほど作成したAmazon Lexボットを選択し、[Channels]タブからSlackとの連携設定をします。Client IDClient SecretVerification Tokenにはステップ 3のSlack APIコンソールでメモしておいた値を入力します。

f:id:brains-tech:20180827210833p:plain

[Activate]が完了するとPostback URLOAuth URLが表示されるので、こちらをメモしておきます。

f:id:brains-tech:20180827212342p:plain

ステップ 5: Slack統合を完了する

Slack APIコンソールを開き、[OAuth & Permissions]で権限設定をしたあと、Redirect URLsにステップ 4のAWSマネージドコンソールでメモしておいたOAuth URLを入力します。

f:id:brains-tech:20180827213800p:plain

[Interactive Components]と[Event Subscriptions]のRequest URLに、ステップ 4のAWSマネージドコンソールでメモしておいたPostback URLを入力します。

f:id:brains-tech:20180827215339p:plain
f:id:brains-tech:20180827215414p:plain

これで、連携設定は完了です!

ステップ 6: 中間テストをする

Slackにログインし、テストをしたいチャンネルにSlack APIで作ったBotユーザを招待します。 ここでは、realbot子さんが#test-channelにlexbot子さんを招待しています。

f:id:brains-tech:20180827223216p:plain

少し分かりづらいのですが、realbot子さんがこちらが入力したメッセージ。lexbot子さんがAmazon Lexが返してくれているメッセージです。

f:id:brains-tech:20180830114539p:plain

このように、lexbot子さんは英語しか話せないので、次のステップ以降でAmazon TranslateとSlackを融合させて、日本語を話してもらうようにします。

ステップ 7: Slackに着信Webフックを追加する

Slack App ディレクトリを開き、着信 Webフックを追加します。

# lexbot子さんの着信 Webフックを利用してもOKですが、今回は表示名を変えたかったため、別の着信 Webフックを追加しています。

f:id:brains-tech:20180829225619p:plain

名前やアイコンを指定したあと、Webhook URLをメモしておきます。

f:id:brains-tech:20180830125305p:plain

ステップ 8: AWS Lambda関数に付与するロールを作成する

AWSマネージドコンソールからIAMを選択します。[ロール]->[ロールの作成]を押下し、AWSサービスのLambdaを選択します。

f:id:brains-tech:20180829214638p:plain

TranslateReadOnlyポリシーを選択します。

f:id:brains-tech:20180829215132p:plain

任意のロール名を入力しロールを作成します。

f:id:brains-tech:20180829215301p:plain

ステップ 9: AWS Lambda関数を作成する

AWSマネージドコンソールからAWS Lambdaを選択します。[関数の作成]を選択して、関数を一から作成します。 Zapierを利用する場合、関数の名前は必ずzapier_evalとしてください。ステップ 8で作成したロールを選択して関数を作成します。

f:id:brains-tech:20180830130047p:plain

関数コードを入れて保存します。

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があった場合とします。

f:id:brains-tech:20180829234023p:plain

Channelを指定し、Trigger for Bot Messages?をnoからyesに変更します。

f:id:brains-tech:20180829235032p:plain

今回は、Invoke Functionを選択します。返り値を受け取ってあれこれしたい場合はRun Codeがいいでしょう。

f:id:brains-tech:20180829235959p:plain

Functionにはステップ 9で作成したzapier_evalを選択、Argumentsでeventオブジェクトに渡すデータとしてSlackのTextを指定します。

f:id:brains-tech:20180830001744p:plain

ZapのステータスをONにしたら、全ての設定が終了です。ふぅ

ステップ 11: 統合テストをする

Slackにログインし、realbot子さんがlexbot子さんに話しかけます。すると、tranbot子さんが英語を日本語に翻訳してくれました!

f:id:brains-tech:20180830131538p:plain

おわりに

トリガーとなる英語を適切に入力しないとAmazon Lexは反応してくれませんが、Hi (やあ) やHello (こんにちは) といった簡単な言葉をトリガーにしておけば、

  1. 英語で入力
  2. 英語で返答 (by Amazon Lex)
  3. 日本語に翻訳 (by Amazon Translate)

から

  1. 日本語で入力
  2. 英語に翻訳 (by Amazon Translate)
  3. 英語で返答 (by Amazon Lex)
  4. 日本語に翻訳 (by Amazon Translate)

とすることもできそうです。

それが実現できると、InputとOutputの言語はAmazon Translateが対応する12言語を自由に組み合わせることができるようになります。 Amazon Lexが英語にしか対応していなくても、多言語コミュニケーションが可能になる訳ですね。

余談

無茶なキーワードを入れたら返ってきた返答です。普段は敬語のtranbot子さんですが、たまに不機嫌になるのでご注意を (笑)

f:id:brains-tech:20180830004242p:plain


ブレインズテクノロジーでは「共に成長できる仲間」を募集中です。
採用ページはこちら