Google 翻訳で複数の言語に対応

ビジネス メッセージ ロケールと、Google 翻訳のインテリジェントで自動翻訳された言語を使用して、ユーザーに合った言語でエージェント コミュニケーションをとることで、エージェントのリーチを拡大できます。このチュートリアルでは、Google 翻訳とビジネス メッセージ Webhook の概念実証を統合する概念実証について説明します。

必要なもの

開始するには、以下のものを準備する必要があります。

コードを取得する

このチュートリアルでは、Google 翻訳と統合されるサンプル Webhook コードについて説明します。コードを取得するには、GitHub からリポジトリのクローンを作成します。

git clone https://github.com/google-business-communications/bm-nodejs-translation-tutorial

クローンを作成したディレクトリに移動し、サービス アカウント キーを resources ディレクトリに配置します。

cp credentials.json bm-nodejs-translation-sample/resources/bm-agent-service-account-credentials.json

ヒント: サービスキーの設定やダウンロードについてサポートが必要な場合は、サービス アカウントの管理に関する Google Cloud ガイドをご覧ください。

これを行うと、コードをデプロイできます。

gcloud app deploy

モバイル デバイスを使ってエージェントにメッセージを送信します。さまざまな言語でメッセージを送信して、何が起きるのか見てみましょう。

Translate API を設定する

サンプルコードには、すでに Translate API の Node パッケージが含まれています。Node パッケージのインストール方法や、別のプログラミング言語で Translate API をインストールする方法にご興味がある場合は、Cloud Translate API のドキュメントをご覧ください。

Translate API を使用するには、ライブラリをインポートして、Translate API クライアントを作成する必要があります。routes/index.js ファイルを開きます。関連する行は次のとおりです。

// Import the Translate API library.
const { Translate } = require("@google-cloud/translate").v2;
// Create a new Translate API client.
const translate = new Translate();

今後は、translate オブジェクトで Translate API メソッドにアクセスできます。

ファイルの先頭付近で作成された変数を確認します。

const SERVER_LANGUAGE = "en";
let currentLanguage = SERVER_LANGUAGE;

サンプルコードでは、サーバー言語が比較的固定されているため、定数として格納されています。ただし、会話の現在の言語は変更される可能性があるため、currentLanguage 変数で追跡する必要があります。

受信言語の検出

サンプルコードは、受信言語が変更されたかどうかを検出し、変更された場合、会話で使用する言語を選択するようユーザーに促します。 モバイル デバイスでこの機能を試すには、英語以外の言語でエージェントにメッセージを入力します。他の言語がわからない場合は、「Hola」と入力してください(スペイン語の「こんにちは」)。

エージェントは、ユーザーが言語を切り替えるかどうかを尋ねるプロンプトで応答します。このメッセージには、ユーザーがクリックして言語に切り替えることができる返信文の候補が表示されます。

まず、言語検出機能を見てみましょう。

/**
 * Detects input text language.
 *
 * @param {string} text The text received from the consumer.
 * @param {Context} context The user message request context.
 * @return A Promise with the detected language code.
 */
async function detectLanguage(text, context) {
  return new Promise(function (resolve, reject) {
    translate
      .detect(text)
      .then((result) => {
        if (result && result.length > 0) {
          if (result[0].confidence > CONFIDENCE_THRESHOLD) {
            resolve(result[0].language);
          }
          resolve(bcp47.parse(context.resolvedLocale).language);
        } else {
          reject("No language detected");
        }
      })
      .catch((err) => {
        console.error("ERROR:", err);
        reject(err);
      });
  });
}

このメソッドは、翻訳クライアントの検出メソッドを使用します。Translate API はさまざまな信頼度で複数の言語を検出することがあるため(また、複数の入力をサポートしているため)、このメソッドは結果の配列を返します。このサンプルは最初の結果(最も信頼度の高い結果)を受け取ります。

解決されたロケールの使用

Translate API では、高い信頼性でメッセージ言語を判別できないことがあります。たとえば、猫がキーボード全体を実行して意味のない文字列を入力した場合、Translate API は言語の検出を試みますが、検出された言語はおそらく正しくありません。(なお、Google 翻訳は猫に関する言語をサポートしていません)。Translate API は translate.detect の結果に信頼度の低い値を設定しています。

このシナリオでは、サンプルコードはビジネス メッセージの解決言語 / 地域の言語にフォールバックします。これは、Business Messages API がメッセージのコンテキストに基づいて言語を推測する最良の言語です。解決されたロケールは BCP-47 形式であるため、対応する Node.js パッケージを使用して、ロケールから言語コードを解析できます。

この動作をテストするには、意味不明な文字列をエージェントに入力します。ほとんどの場合、言語を変更するプロンプトは表示されません(解決されたロケールが現在の言語と異なる場合を除く)。エージェントは、単にリクエストを理解していないと言います。

言語の変更を求めるメッセージ

言語が変更されたことを検出すると、エージェントは言語の変更を求めるプロンプトを返します。

if (detectedLanguage != currentLanguage) {
        translateText(
          "Which language would you like to use?",
          SERVER_LANGUAGE,
          currentLanguage
        ).then((normalizedTranslationNotice) => {
          sendResponse(
            normalizedTranslationNotice,
            conversationId,
            [
              ...new Set([detectedLanguage, currentLanguage, SERVER_LANGUAGE]),
            ].map((x) => createSuggestedReply(x))
          );
        });
      }

このコードはプロンプトを作成し、そのメッセージを現在の言語に翻訳します(詳細は「送信メッセージ翻訳」を参照)。次に、返信文の候補を使用してレスポンスを送信します。ユーザーは次のいずれかの言語で話します。

  • 検出された受信言語。
  • 現在の会話言語。
  • サーバーの組み込み言語。

この 3 つの言語は重複している可能性があります(たとえば、現在の言語がすでにサーバー言語である場合など)。この場合、サーバーは set オブジェクトを使用して重複を削除します。言語ごとに返信の候補を作成します。

/**
 * Create a suggested reply for a language code.
 * @param {string} languageCode A ISO 6391 language code.
 * @return {Suggestion} The suggestion object for switching to the language.
 */
function createSuggestedReply(languageCode) {
  return {
    reply: {
      text: ISO6391.getNativeName(languageCode),
      postbackData: SWITCH_LANGUAGE_POSTBACK + languageCode,
    },
  };
}

候補の返信には、その言語の言語が母国語で表示されます。たとえば、スペイン語は「Español."」と表示されます。2 桁の言語コードから言語に関する情報を取得するには、Node.js 用の ISO-639-1 ライブラリを使用します。

ポストバック データに注目してください。これは、ユーザーがこの候補をクリックするとサーバーに送信されます。ポストバック データは、サーバーに応答する方法と、候補に関するコンテキストを提供します。

sendResponse メソッドは、次の候補オブジェクトを返信に接続します。

let messageObject = {
    …
    suggestions: suggestedReplies,
  };

会話の言語を変更する

モバイル デバイスに戻り、プロンプトのプロンプトで新しい言語オプションをクリックします。たとえば、「Hola」と入力した場合、返信文の候補に「Español」と入力します。

エージェントが新しい言語で応答します。送信返信を翻訳する方法については、後のステップで説明します。ここでは、クリックされた返信の候補を受け取って処理するコードを確認します。

if (requestBody.suggestionResponse !== undefined) {
    let postbackData = requestBody.suggestionResponse.postbackData;
    if (postbackData.startsWith(SWITCH_LANGUAGE_POSTBACK)) {
      let languageCode = postbackData.substr(SWITCH_LANGUAGE_POSTBACK.length);
      currentLanguage = languageCode;
      translateText(
        "The language was set to " +
          ISO6391.getName(languageCode) +
          ". Please repeat your request.",
        SERVER_LANGUAGE,
        languageCode
      ).then((translationNotice) => {
        sendResponse(translationNotice, conversationId, []);
      });
    }
  }

リクエストに候補に対する返信が含まれている場合、サーバーはポストバック データを使用して対処法を決定します。この単純なケースでは、SwITCH_LANGUAGE_POSTBACK という 1 種類のポストバック データのみがサポートされます。これは、会話が直後に続く言語コードで言語に変更される必要があることを示しています。この言語コードを解析した後、サーバーは、言語が変更されたことを知らせるメッセージをユーザーに送信します。

受信メッセージ翻訳

言語が変更されたら、モバイル デバイスでその言語のエージェントにリクエストを送信できます。新しい言語で「help」と入力して送信します。言語をスペイン語に変更した場合は、「ayuda」と入力してメッセージを送信します。

サーバーはサポート リクエストを認識し、オプション メニューで応答します。ハードコードされたサンプルのレスポンスを確認するには、次のいずれかの方法をお試しください。

サンプルコードでは、translateText メソッドを使用して、受信メッセージと送信メッセージの両方を翻訳しています。ぜひご確認ください。

/**
 * Translates text to a given target language. No translation if source and
 * target language match.
 *
 * @param {string} text the text to translate
 * @param {string} sourceLanguage The language of the source text.
 * @param {string} targetLanguage The target language.
 * @return A Promise with the translated text.
 */
async function translateText(text, sourceLanguage, targetLanguage) {
  if (sourceLanguage === targetLanguage) {
    return new Promise(function (resolve, reject) {
      resolve(text);
    });
  }
  return new Promise(function (resolve, reject) {
    translate
      .translate(text, targetLanguage)
      .then((result) => {
        if (result && result.length > 0) {
          resolve(result[0]);
        } else {
          reject("Could not translate message");
        }
      })
      .catch((err) => {
        console.error("ERROR:", err);
        reject(err);
      });
  });
}

ソース言語がターゲット言語と同じである場合、何もする必要はありません。そうしないと、サーバーは Translate API クライアントで翻訳メソッドを呼び出します。検出メソッドと同様に、translate メソッドは複数の入力を受け取ります。サーバーは、入力が 1 つしかないため、Translate API から最初の結果を取得します。

現在のメッセージで受信メッセージに応答するコールバック メソッドのセクションを見てみましょう。

translateText(incomingMessage, currentLanguage, SERVER_LANGUAGE).then(
          (normalizedMessage) => {
            let serverResponse = chooseResponseMessage(normalizedMessage);
            …
          }
        );

サーバーは translateText からの出力を使用して、レスポンス メッセージを選択します。次のセクションでは、レスポンス メッセージを選択して翻訳するプロセスについて詳しく説明します。

送信メールの翻訳

サーバーは受信したメッセージを母国語に翻訳した後、ユーザーのリクエストを選択、翻訳して適切なレスポンスを送信する必要があります。サンプルコードでは、キーワードをレスポンスにマッピングする非常に単純なスキームを使用しています。chooseResponseMessage メソッドをご覧ください。

/**
 * Select a topically appropriate response based on the message
 * content that the user sent to the agent.
 *
 * @param {string} incomingMessage The content of the message that the user typed in.
 * @param {string} conversationId The unique id for this user and agent.
 * @return {string} A response message.
 */
function chooseResponseMessage(incomingMessage) {
  let responseMapping = {
    balance: "Your current balance is $500.",
    deposit: "Please enter your deposit amount.",
    transfer:
      "Please enter the account number where you wish to transfer the funds.",
    withdraw: "Please enter the amount you wish to withdraw.",
    help: "Please choose what you'd like to do: balance, deposit, transfer, or withdraw.",
  };

  for (const [key, value] of Object.entries(responseMapping)) {
    if (incomingMessage.toLowerCase().includes(key)) {
      return value;
    }
  }

  return "I didn't understand your request. Please try again.";
}

このスキームでは、サーバーで英語のみがサポートされています。つまり、サーバーがすべての受信メッセージと送信メッセージを翻訳する必要があります。高度なシステムの場合、複数の言語がサポートされ、他の言語のリクエストにネイティブに応答されることがあります。たとえば、エージェントがスペイン語をサポートしている場合は、レスポンス マップに「ayuda」のキーがすでに存在している可能性があります。より高度なシステムの場合、適切なレスポンスを選択するために他の手法(ML やスコアリング アルゴリズムなど)に依存することがあります。ビジネス メッセージでよりインテリジェントな回答を得る方法の 1 つは、Dialogflow と統合することです。

ここで、選択したメッセージをユーザーに返すコードを見てみましょう。

let serverResponse = chooseResponseMessage(normalizedMessage);
            translateText(
              serverResponse,
              SERVER_LANGUAGE,
              currentLanguage
            ).then((normalizedResponse) => {
              sendResponse(normalizedResponse, conversationId, []);
            });

サンプルコードでは、translateText メソッドを再利用して、選択したレスポンスを現在の会話言語に変換します。次に、sendResponse メソッドは新しい Message オブジェクトを作成し、ユーザーに送信します。

まとめ

このチュートリアルでは、Cloud Translate API とのシンプルな統合を作成し、ビジネス メッセージのロケール機能を利用してより多くのユーザーにリーチする方法を学習しました。必要に応じて、このチュートリアルのサンプルコードを独自の統合の開始点として使用することも、新しい方法を試すこともできます。以下のヒントをご覧ください。

  • 元のメッセージ コンテンツと自動翻訳されたコンテンツの両方を含むバイリンガル メッセージを送信します。
  • ユーザーが会話を開始するときに、サポートされている言語の一覧メニューを表示します。
  • 翻訳 API の高度な機能。用語集などを使用して、ビジネスに固有の単語を確実に翻訳する。

Translate API と統合することで、高品質な機械翻訳を活用して、より多くのユーザーが最適な言語でコミュニケーションをとることができます。エージェントの生産性と効率性を高め、顧客満足度とタスク完了率を向上できます。