14
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ElixirAdvent Calendar 2022

Day 25

Livebook から Amazon Translate を使ってテキスト翻訳する

Posted at

はじめに

Livebook から AWS のサービスを操作するシリーズです

今回は Amazon Translate を使います

その名の通り、翻訳サービスです

対応言語は 75 言語(日本語含む)、 100 万文字あたり $15 で使用できます

最初の12ヶ月は無料利用枠が適用されるため、 200万文字 / 月まで無料で利用できます

ただし、2022年12月19日現在、東京リージョンでは使えない点に注意してください

実装したノートブックはこちら

事前作業

AWS のアカンウトと、 Translate の権限を持った IAM ユーザーと、その認証情報(ACCESS_KEY_ID と SECRET_ACCESS_KEY)が必要です

実行環境

Livebook 0.8.0 の Docker イメージを元にしたコンテナで動かしました

コンテナ定義はこちらを参照

セットアップ

ex_aws_translate を中心に、必要なモジュールをインストールします

Mix.install([
  {:ex_aws, "~> 2.0"},
  {:ex_aws_translate, "~> 0.3"},
  {:jason, "~> 1.4"},
  {:poison, "~> 5.0"},
  {:hackney, "~> 1.18"},
  {:sweet_xml, "~> 0.7"},
  {:kino, "~> 0.8"}
])

エイリアスを付けておきます

alias ExAws.Translate

認証

入力エリアを用意し、そこに IAM ユーザーの認証情報を入力します

ACCESS_KEY_ID と SECRET_ACCESS_KEY は秘密情報なので、値が見えないように Kino.Input.password を使います

access_key_id_input = Kino.Input.password("ACCESS_KEY_ID")
secret_access_key_input = Kino.Input.password("SECRET_ACCESS_KEY")

普段なら東京リージョンを使うのですが、 Translate は東京リージョンで使えないため、バージニアリージョンを指定します

region_input = Kino.Input.text("REGION", default: "us-east-1")

スクリーンショット 2022-12-19 17.32.14.png

各認証情報を ExAws に渡すためにまとめておきます

秘密情報が実行結果に現れないよう、セルの最後には "dummy" を入れておきましょう

auth_config = [
  access_key_id: Kino.Input.read(access_key_id_input),
  secret_access_key: Kino.Input.read(secret_access_key_input),
  region: Kino.Input.read(region_input)
]

"dummy"

言語一覧の取得

実は ex_aws_translate には list_languages 関数が実装されていません

また、なんと GitHub リポジトリーも閉じられてしまっています

パンがなければ作ればいい、ということで無理矢理実装します

languages =
  %ExAws.Operation.JSON{
    stream_builder: nil,
    http_method: :post,
    parser: nil,
    path: "/",
    data: %{},
    params: %{},
    headers: [
      {"Content-Type", "application/x-amz-json-1.1"},
      {"X-Amz-Target", "AWSShineFrontendService_20170701.ListLanguages"}
    ],
    service: :translate,
    before_request: nil
  }
  |> ExAws.request!(auth_config)
  |> then(& &1["Languages"])
  |> Enum.map(&{&1["LanguageCode"], &1["LanguageName"]})

スクリーンショット 2022-12-19 17.35.32.png

何言語あるか確認してみましょう

Enum.count(languages)

スクリーンショット 2022-12-19 17.39.11.png

公式 FAQ では 75 言語と書いてあるのに、 76 言語ありました

多い分には良いですが

言語の選択

言語を選択できるようにします

src_lang_select = Kino.Input.select("翻訳元言語", languages, default: "en")
src_lang = Kino.Input.read(src_lang_select)
dst_lang_select = Kino.Input.select("翻訳先言語", languages, default: "ja")
dst_lang = Kino.Input.read(dst_lang_select)

languages.gif

翻訳

元言語と先言語を指定して翻訳します

"Hello"
|> Translate.translate_text(src_lang, dst_lang)
|> ExAws.request!(auth_config)

スクリーンショット 2022-12-19 17.43.34.png

文章を翻訳してみましょう

text_input =
  Kino.Input.textarea("TEXT",
    default:
      ~s/Elixir is a dynamic, functional language for building scalable and maintainable applications. Elixir runs on the Erlang VM, known for creating low-latency, distributed, and fault-tolerant systems. These capabilities and Elixir tooling allow developers to be productive in several domains, such as web development, embedded software, data pipelines, and multimedia processing, across a wide range of industries./
  )

スクリーンショット 2022-12-19 17.44.26.png

text_input
|> Kino.Input.read()
|> Translate.translate_text(src_lang, dst_lang)
|> ExAws.request!(auth_config)
|> then(& &1["TranslatedText"])
"Elixirは、スケーラブルで保守可能なアプリケーションを構築するための動的で機能的な言語です。Elixirは、低レイテンシー、分散型、耐障害性のあるシステムを作ることで知られるErlang VM上で動作します。これらの機能とElixirツールにより、開発者は幅広い業界のウェブ開発、組み込みソフトウェア、データパイプライン、マルチメディア処理など、さまざまな分野で生産性を高めることができます。"

かなり良い感じに翻訳できています

ちなみに、翻訳元言語に "auto" を指定すれば自動的に識別してくれます

# 翻訳元言語の自動識別
text_input
|> Kino.Input.read()
|> Translate.translate_text("auto", dst_lang)
|> ExAws.request!(auth_config)
|> then(& &1["TranslatedText"])

用語登録

Translate の翻訳でも、専門用語など、微妙に正しく翻訳してくれない場合があります

そういった場合に特定の単語はこう翻訳しなさい、と指定できます

以下は手巻き寿司の説明文です

text =
  "Temakizushi are cones made of nori seaweed and filled with sushi rice, seafood and vegetables."
text
|> Translate.translate_text("auto", dst_lang)
|> ExAws.request!(auth_config)
|> then(& &1["TranslatedText"])

そのまま翻訳すると以下のような文章になります

"手巻き寿司は、海苔でできたコーンに寿司飯、魚介類、野菜を詰めたものです。"

「コーン」だとトウモロコシだと誤解を招きそうです

「円錐」にしてもらいましょう(それもどうかと思いますが)

用語データは CSV 形式の文字列を BASE64 エンコードして渡します(TSV や TMX にも対応しています)

ヘッダーに言語コード、2行目以降に用語を列挙します

以下のようにすると、英語で「cones」は日本語で「円錐」になります

sushi_terminology_data =
  ("en,ja\n" <>
     "cones,円錐")
  |> Base.encode64()

用語データを Translate に登録します

Translate.import_terminology(
  "sushi_terminology",
  %{
    file: sushi_terminology_data,
    format: "CSV"
  },
  "OVERWRITE"
)
|> ExAws.request!(auth_config)

登録した用語データを terminology_names に指定して翻訳しましょう

text
|> Translate.translate_text("auto", dst_lang, terminology_names: ["sushi_terminology"])
|> ExAws.request!(auth_config)
|> then(& &1["TranslatedText"])
"手巻き寿司は、海苔でできた円錐に寿司飯、魚介類、野菜を詰めたものです。"

きちんと「円錐」になりました

まとめ

翻訳サービスも色々あるのであえてこれを選ばないといけないこともないですが、 AWS 上に建てたシステムからは簡単に呼び出せるので選択肢の一つです

もちろん、 Bumblebee で翻訳できるようになるのももうすぐですが

14
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?