はじめに
ココネ株式会社のサービス基盤開発室クライアントチームでツール開発している鞠(クク)です。
このページではDeepLでSlack用の翻訳ツールを作成してみました。
仕様
本ツールは、Slack上の文言に対してDeepLを利用して自動翻訳してくれるツールになります。
やり方はSlackのメッセージに対して、国旗のリアクションを行うと、自動翻訳されたメッセージがスレッドに投稿されます。
DeepLとは?
DeepL翻訳は、
2017年8月28日にサービスを開始したニューラル機械翻訳サービス。
ドイツのケルンに本拠地を置く DeepL GmbH が開発。
Google 翻訳よりも精度が高く、微妙なニュアンスのある翻訳ができると肯定的な報道と評価を受けている。
2023年1月31日に韓国語とノルウェー語がリリースされました。
開発環境
- DeepL API Pro(for Developers)
- Slack ワークスペース
- AWS API Gateway
- AWS Lambda
DeepL API Pro
無料版でも利用可能ですが、有料版のメリットとしては、
機密性が高い社内の情報を一瞬でもDeepLのサーバー側に保存されない上、
機械学習にも使われないようになります。
1. 契約プラン
月使用量と、1,000,000文字あたり¥2,500
登録料金 ¥630 /月 + 従量課金制 100万文字あたり¥630
2. DeepL API関連技術ドキュメント
3. DeepL APIで使用する認証キー
正常に登録を完了すると、次のアカウント情報ページに認証キーとAPIのドメインが表示されます。
LambdaでAPIコールするとき、必要になります。
4. 使用量確認(文字数&料金)
次のURLで文字数&料金が確認できます。
AWS API Gateway
1. 概要
2. REST APIを作成
3. POSTメソッドを作成
Resourcesの [Actions]->[Create Method]->[POST] メソッドを作成します。
4. Method Execution / - POST - Integration Request設定
Integration typeでLambda関数を選びます。
Use Lambda Proxy integrationをチェックします。
4. REST API のステージのセットアップ
[Actions]->[Deploy API]でDeployment stageで[New Stage]を指定して入力後デプロイします。
Stage名は自由に入力してください。
6. REST API のデプロイ
デプロイ後、生成されたURLを下記のSlack APIのアプリに入力します。
(Slack API -> 登録アプリ -> Event Subscriptions -> Request URL)
AWS Lambda
こちらのコードはPython 3.9 Runtimeで動作確認しました。
import json
import os
import requests
CURRENT_PROJECT_VERSION = "0.0.1"
SLACK_CONVERSATIONS_REPLIES_URL = "https://slack.com/api/conversations.replies"
SLACK_CHAT_POST_MESSAGE_URL = "https://slack.com/api/chat.postMessage"
SLACK_TOKEN = os.environ.get('SLACK_TOKEN')
DEEPL_KEY = os.environ.get('DEEPL_KEY')
DEEPL_URL = os.environ.get('DEEPL_URL')
DEBUG_MODE = os.environ.get('DEBUG_MODE')
#data mapping between reaction names and language codes
LANG_CODES = {
'us': 'en-us', #英語アメリカ
'gb': 'en-gb', #英語イギリス
'cn': 'ZH', #中国語
'de': 'de', #ドイツ語
'fr': 'fr', #フランス語
'it': 'it', #イタリア語
'jp': 'ja', #日本語
'es': 'es',#スペイン語
'nl': 'nl', #オランダ語
'pl': 'pl', #ポーランド語
'ru': 'ru', #ロシア語
'flag-ua': 'uk', #Ukrainian
'kr': 'ko', #韓国語
};
def is_challenge(event):
if 'body' in event:
body = json.loads(event['body'])
if ('type' in body) & (body['type'] == 'url_verification'):
return body['challenge']
def process_message(event):
if 'body' in event:
body = json.loads(event['body'])
event_body = body['event']
if ('type' in event_body) & (event_body['type'] == 'reaction_added') & ('reaction' in event_body) & (event_body['reaction'] in LANG_CODES):
event_reaction = event_body['reaction']
event_item = event_body['item']
event_channel = event_item['channel']
event_ts = event_item['ts']
header_message={
"Authorization": "Bearer {}".format(SLACK_TOKEN)
}
payload = {
"channel" : event_channel,
"ts" : event_ts
}
res = requests.get(SLACK_CONVERSATIONS_REPLIES_URL, headers=header_message, params=payload)
t_data = res.json()
original_message = t_data['messages'][0]['text']
if(DEBUG_MODE):
print("original_message : ", original_message)
trans_lang = LANG_CODES[event_reaction]
# パラメータの指定
deepl_params = {
"auth_key" : DEEPL_KEY,
"text" : original_message,
"target_lang": trans_lang # 翻訳後の言語
}
deepl_response = requests.post(DEEPL_URL, data=deepl_params) # URIは有償版, 無償版で異なるため要注意 -> 個人用
trans_data = deepl_response.json()
translate_messages = trans_data['translations'][0]['text']
if(DEBUG_MODE):
print("translate_messages : ", translate_messages)
#判別ロージック追加
marge_translate_messages = ":"+event_body['reaction']+": "+trans_lang+"\n"+translate_messages
for i in t_data['messages']:
if ('bot_id' in i) & (i['text'] == marge_translate_messages):
return
chatpayload = {
"channel" : event_channel,
"text" : marge_translate_messages,
"thread_ts" : event_ts
}
if(DEBUG_MODE):
print("marge_translate_messages : ", marge_translate_messages)
res_chat = requests.post(SLACK_CHAT_POST_MESSAGE_URL, headers=header_message, params=chatpayload)
return res.json()
return
def lambda_handler(event, context):
# Return Slack challenge parameter
clg = is_challenge(event = event)
process_message(event = event)
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": json.dumps({
"challenge ": clg
})
}
※コメントなどのリアクションがあったら、現ソースコードをリファクタリングする予定です。
Slack アプリケーション登録
1. アプリを登録
Slackにログインした状態で、上記のURLにアクセスします。
[Create an App]をクリックしてアプリの名前と
下記の文言の後にアプリを使用するWorkspaceを選択します。
Pick a workspace to develop your app in:
2. アプリの権限を設定
左上のメニューから Features -> OAuth & Permissions を選択
上記の画面の Scopes -> Bot Token Scopesの[Add an OAuth Scope]で権限をを追加します。
権限 | 詳細 |
---|---|
channels:history | メッセージの参照、履歴の参照 |
groups:history | プライベート チャンネルのメッセージの参照、履歴の参照 |
chat:write | チャンネルに投稿 |
reactions:read | メッセージにつけられたリアクションを参照 |
3. ボットの設定
こちらではボットの名とメンション名の設定します。
左のメニューから Features -> App Home 選択
App Display Name -> Edit ボタンを押して、設定を行います。
4. アプリの外見設定
左のメニューから Settings -> Basic Information -> Display Information
アプリの設定画面で、アプリ名、説明文、バックグラウンドカラー、アイコン画像など設定します。
5. アプリをワークスペースにインストール
左のメニューから Settings -> Install App を選択します。
(Features -> OAuth & Permissionsからも同様の操作が可能です。)
権限によって実装内容が次のように変わります。
A. 管理者権限がある場合
[Install App to Workspace] でインストール後そのまま許可できます。
B. 一般権限の場合
[Request to Install] でインストールを依頼して管理者の承認待ちになります。
Slack Enterprise Grid Planの場合
複数のワークスペースで共通して使える Org-Wide Appをインストールできます。
5. アプリのトークンを取得
インストール後には 左のメニューの
Settings -> Install App 又は Features -> OAuth & Permissionsで
xoxb- から始まる Bot User OAuth Access Token が取得できます。
また、セキュリティなどの必要に応じていつでもトークンが再発行できます。
Features -> OAuth & Permissions -> Revoke All OAuth Tokens -> [Revoke Tokens]
6. Event Subscriptions設定
翻訳するときリアクションが付けることになりますが、
その時の確認のためイベントのサブスクライブ機能を使用します。
左のメニューの Features -> Event Subscriptions -> Enable Events -> [Off] クリックします。
Request URLにAWS HTTP GatewayからデプロイしたURLを記入します。
最初にURLを登録するにはchallenge認証が必要です。
Lambdaの次の関数で実装されています。
def is_challenge(event):
設定内容としては以下のように機能を有効にして Request URL を設定し、bot events の方に reaction_added を追加し [Save Changes] ボタンを押して保存するだけです。
Basic Information -> Building Apps for Slack -> Add features and functionalityの
設定画面は最終的に次のようになります。
7. アプリをチャンネルに招待して動作確認
対象Slack チャンネルアプリのボットユーザーを招待します。
チャンネル詳細 -> インテグレーション -> App -> [アプリを追加する]
アプリを検索して [追加]
メッセージに翻訳したい国の国旗の絵文字をリアクションでつけてください。
:flag-fr:
参照コード一覧
Python以外の言語(JS, TS) で実装する方はこちらをご参考ください。
まとめ
一通り実装してみた感想はDeepL API周りは割と分かりやすくて、特に問題なかったんですが、
Slackの設定とAWS実装で色々試行錯誤しました。
今回の実装の開発環境で必須になるSlackとDeepLとは違って
AWS環境は自作サーバーでも他のサーバーレスクラウドでも何でも使いやすい環境で各自試してみてください。
サーバー周りの環境をHerokuでご利用の方は次のKazuhiro Sera様の次のドキュメントをご参考ください。