
問い合わせを翻訳するのにGASのWebアプリ+DeepL APIを使ったらお手軽でいい感じだった話
-
2023年5月9日
はじめに
こんにちは。QA室の杉本です。
今回はQAのお話ではないのですが、以前CXを担当していた繋がりもあり、問い合わせ周りの設定やスクリプト作成をすることもありまして、今回はその辺りの話を少し。
弊社では、顧客対応のスピードを向上するため、CX関係者が問い合わせを Slack で確認できる仕組みを導入しています。
そんな中、グローバル展開しているサービスの場合は色々な言語での問い合わせがあるため、Slack に流れる問い合わせを日本語に翻訳できないか、という話が出てきました。
やり方は色々ありそうですが、なるべく手軽な方法で実現したかったので、Google Apps Script (GAS) 使えないかなぁと思い調べつつやってみたところ、案外サクッと出来たので、参考になる方もいるのではと思い、紹介させていただこうと思います。
現在、お問い合わせの対応には Zendesk を使用しており、翻訳が必要ない環境では、
Zendeskでチケット作成 ⇒ WebhookでSlackに送信
という形になっていますが、翻訳を行うにあたって、
Zendeskでチケット作成 ⇒ WebhookでGAS(API)に送信 ⇒ DeepLで翻訳 ⇒ Slackに送信
という感じで、Zendesk から GAS に処理を渡して翻訳しつつ、Slack に投稿する流れにしました。なお、翻訳対象のデータは慎重に取り扱う必要がある為、翻訳には DeepL API Pro を使っています。
そんな訳でこの記事では、GAS の具体的なコード(POSTリクエスト処理・DeepL翻訳・Slack投稿)と、GAS を Webアプリ (Web API) として公開する方法、そして Zendesk 側での設定についても説明します。
GASコードの流れ
まず、GAS のコードは以下の3つの関数です。(なおエラー処理は省いているのでご容赦ください)
・POST リクエストを処理する
・DeepL API を使用して翻訳する
・Slack API を使用して投稿する
/**
* POST リクエストを処理
*/
function doPost( e )
{
// POSTされたデータを受け取る
let params = JSON.parse(e.postData.getDataAsString());
let text = params.text; // 翻訳対象のテキスト
let lang = params.lang; // 翻訳先の言語
let ch = params.ch; // 投稿先のチャンネル
// DeepLで翻訳
let translation = translateWithDeepL(text,lang);
let sourceLanguage = translation["detected_source_language"];
let translatedText = translation["text"];
// Slackに投稿(翻訳元の言語と翻訳先の言語が同じと判別された場合は、Slack投稿しない)
if (sourceLanguage !== lang) {
postSlack(ch,"```" + translatedText + "```");
}
// レスポンスを返す
let output = ContentService.createTextOutput();
output.setMimeType(ContentService.MimeType.JSON);
output.setContent(JSON.stringify({message:"success"}));
return (output);
}
補足:
doPost() で POSTリクエストを処理します。
受け取った JSONデータのキー “text” から翻訳したいテキスト、“lang” から翻訳したい言語、”ch” から投稿したい Slack のチャンネルを取得します。
それらを元に DeepL で翻訳した後、Slack に投稿しています。
なお DeepL で翻訳すると「元の言語はこれでした」という情報が返ってくるので、翻訳元の言語と翻訳したい言語が同じだった場合は Slack に投稿しないようにしています。
/**
* DeepL API で翻訳
*/
function translateWithDeepL( text, lang )
{
// 送信するデータ
let params = {
"text" : text,
"target_lang" : lang
}
let options = {
"method" : "post",
"headers" : { "Authorization": "DeepL-Auth-Key
xxxxxxxxxxxxxxxx" }, // 認証キー
"payload" : params,
"muteHttpExceptions" : true
}
let translation = null;
// DeepL API で翻訳
let response = UrlFetchApp.fetch("https://api.deepl.com/v2/translate", options);
let responseBody = response.getContentText();
let data = JSON.parse(responseBody);
if ("translations" in data) {
translation = data["translations"][0];
}
return translation;
}
補足:
DeepL API を利用して翻訳しています。もちろん DeepL API の認証キーが必要です。
この API はシンプルで分かりやすいですが、翻訳結果が(おそらく DeepL の API仕様として、複数の文字列を渡せる関係で)配列で返ってくるので、そこだけ注意です。
/**
* Slack に投稿
*/
function postSlack( channel, text )
{
let params = {
"token" : "xxxxxxxxxxxxxxxx", // OAuth token
"channel" : channel,
"text" : text
}
let options = {
"method" : "post",
"payload" : params,
"muteHttpExceptions" : true
}
// Slack に投稿
let response = UrlFetchApp.fetch("https://slack.com/api/chat.postMessage", options);
}
補足:
Slack への投稿。bot の OAuth token を取得することと、該当の bot(アプリ)を投稿したいチャンネルに追加しておく必要があります。
Webhook URL を使って Slack に投稿する形でもいいですが、Zendesk 側から投稿先のチャンネルを指定したかったので、chat.postMessage を使用しています。
GAS を Webアプリ (Web API) として公開(デプロイ)
まず、GAS のエディタ画面の右上にある「デプロイ」から「新しいデプロイ」を選択します。
「新しいデプロイ」の画面にある歯車アイコンをクリックし、「ウェブアプリ」を選択します。
諸々の設定をします。
・新しい説明文:デプロイされたバージョンを把握する為の説明文です
・次のユーザーとして実行:自分(※個人ではなくbot専用のGoogleアカウントが良いでしょう)
・アクセスできるユーザー:全員
そして「デプロイ」ボタンをクリックするとデプロイ完了です。
発行された URL をコピーしておいてください。(後で Zendesk に設定します)
デプロイが終わったところで、動作テストしてみると安心です
(Mac のターミナル等で)。
curl で動作テストする場合、以下のようになります(もちろん、投稿先チャンネルとエンドポイントURLは環境に合わせて設定)。
curl -L -H "Content-Type: application/json" -d '{"text":"I have a pen.", "lang":"JA", "ch":"<投稿先チャンネル>"}' https://script.google.com/macros/s/xxxxxxxxxxxxxxxx/exec
curl を実行したターミナルに「{“message”:”success”}」と表示され、指定した Slackチャンネルに「ペンを持っています。」のような訳文が表示されれば成功です。
※Zendesk の設定の流れの中でもテストできるので、ここは スキップでも大丈夫です
※ちなみによくある失敗は、投稿したい Slackチャンネルに bot(アプリ)が追加されていないパターンです
デプロイについての補足:
・コードを修正した場合、改めてデプロイする必要があります
・この際に発行済みのURLを変更したくない場合は、以下の操作をしてください
- デプロイ>デプロイを管理
- アクティブなデプロイを選択した状態で、右上の鉛筆マークをクリック
- バージョンを「新バージョン」に変更
- その他は変更せず「デプロイ」をクリック
・この操作により、以前のデプロイは自動的にアーカイブされて無効化されます
Zendesk の設定
流れとしては、
・Webhook設定で、デプロイした Webアプリ (Web API) のエンドポイントURL を登録
・トリガ設定で、チケットのコメントを Webhook に送信
です。やることが分かってさえいれば案外簡単です。
翻訳したい Zendesk の「管理センター」を開き、「アプリおよびインテグレーション」の中にある「Webhook」を選択します。
開いた「Webhook」画面の右上にある「Webhookを作成する」ボタンをクリックします。
次の「Webhookを作成する」画面で、「トリガまたは自動化」を選択して「次へ」をクリックします。
諸々の設定をします。
・名前:後でトリガを設定する時に分かるような名前を書いてください
・エンドポイントURL:GAS をデプロイした時に発行された URL を貼り付けます
・リクエスト方法:POST
・リクエスト形式:JSON
ここまで設定して「Webhookをテスト」をクリックすると、画面の右側にテスト用の設定画面が表示されます。
「テストするイベントを選択」の欄で「カスタムテスト」を選択、すると「リクエストJSONボディ」の欄に自由に JSON 文字列を書き込めるようになるので、以下のように(さっき curl でテストしたのと同じ内容でOK)編集します。そして「テストを送信」をクリック。
画面下に「200 OK」「{“message”:”success”}」と表示され、指定した Slackチャンネルに「ペンを持っています。」のような訳文が表示されれば成功です。
続けて画面右下にある「Webhookを作成する」をクリックすれば、Webhookの作成は完了です。
次に「トリガ」を設定します。
Zendesk の「トリガ」は、問い合わせのチケットが作成されたら〜する、のように「チケットに対するアクションに対応して、何らかの処理を行う簡易的なスクリプト機能」のようなものです(ガンビットって言ったら伝わる…かも?)。
画面左側にあるメニューの「オブジェクトとルール」の中にある「トリガ」を選択します。
開いた「トリガ」画面の右上にある「トリガを追加」ボタンをクリックします。
諸々の設定をします。
・トリガ名:分かりやすい名前を付けてください
・条件:以下の条件をすべて満たす、に「チケット=作成された」を追加
※この条件だけだとCXスタッフが作成したチケットも通知されてしまうので、実態に合わせて条件を追加してください
続いて、条件の下にある「アクション」部分を記入します。
トリガ条件に合致したチケットがあった際に実行される部分、ということになります。
・アクションを入力または選択:アクティブなWebhookに通知、を選択
・その右の欄は、先ほど作成した Webhook につけた名前を選択
・”text” には、{{ticket.latest_public_comment}}=最新のコメント、を設定
そして右下にある「作成」ボタンをクリックすると、トリガが作成できます。
トリガについての補足:
・トリガは設定されている並びの通りに上から順番に実行されます
・基本的には Slack通知のようなアクションは、最後に実行するのが良いと思います
・JSONボディの “text” で渡すテキストを、ここで Liquid markup で加工することも出来ますが、今回の場合は GAS に渡してから加工したほうが良いかも…知れません(Liquid でもそこそこ行けますが、結構大変です)
以上で完成です!
最後に
今回やってみて、GAS を Webアプリとして公開することが思ったよりお手軽で、簡易的な Web API として利用できて便利だなーと個人的に思ったので、まだ使ったことの無い方はぜひ使ってみてください。
という訳で、こういった仕組みづくりをQA業務の方にも取り入れて行っていますので、テストの自動化とかテストエンジニアに興味のある方は是非、ココネのQA室に遊びに来てくださいませ!
QAに関する過去のブログも参考にどうぞ。
サービス品質と向き合い続けるインハウスのQAについて語ってみる
ココネでは一緒に働く仲間を募集中です。
ご興味のある方は、ぜひこちらの採用特設サイトをご覧ください。