はじめに
私が参画しているプロジェクトの特性で、業界用語、機能特有の英単語を含む会話を、
英語で行わなければならない場面があります...
筆者は英語が不得意であるため、そういった会話の際には、
翻訳ソフトウェアや翻訳サービスが非常に温かい訳です。
皆さんも経験があるのではないでしょうか。
しかし、制約として、
入力したデータの保存や利用がされないされないこと
が追加されると、選択肢がぐっと減ってしまいます...
例えば、Google翻訳では、
Google 翻訳については入力したデータはGoogleが収集し、サービスの提供や維持、向上などに利用されます。
と言ったような記載があります。
そこで、筆者は、自作翻訳ソフトならば、外部にデータが出ることなく、
日本語↔英語を翻訳できるのでは!?
と考えてしまったので、その結果をここに記します。
この記事はTDCソフト株式会社Advent Calendarの11日目の投稿です!
ぜんてい
という事で、ササっと作って使ってみたいので、
生成AIを駆使して、翻訳ソフトを作っていきます。
言語はPythonを使用しました。
翻訳モデルはfacebook m2m100 418Mと言うものを使用しました。
詳しくは後述します。
もでる
選定した、M2M100と言うモデルは、Meta社(旧facebook AI Reserch)が公開している、
多言語翻訳モデルです。
以下からダウンロードし、使用する事が可能です。
特徴としては、多言語、なので、複数の言語に対応しているところです。
また、どうやら翻訳ソフトには、日→英、英→日といった、言語ペアで、
別々のモデルを必要とするみたいですが、M2M100は、これだけでOKという事で、
めんどくさくなかった 敷居が低かったのも採用pointです。
他のモデルも少しだけ試したのですが、翻訳の品質が安定しなかったり、
良いモデルすぎて、実行時のメモリを食べ過ぎると思い見送った、等もありました。
じっそう
まずは、上記のリンクからダウンロードした翻訳モデルを任意のフォルダに配置します。
次に、ダウンロードしたモデルをCTranslate2と言う形式に変換します。
これ、何の変換作業かと言うと、業務用PCで使用するための軽量化変換になります。
使用している業務用PCは、ありふれたWindows端末なのと、
Chormeのタブが大量に開いているため、ある程度、軽量化しておきたく...
変換処理を行うコマンドは、以下の通りです。
ct2-transformers-converter \
--model "models/m2m100_418M" \
--output_dir "models/ct2_m2m100_418M" \
--quantization int8 \
--copy_files tokenizer_config.json special_tokens_map.json sentencepiece.bpe.model generation_config.json
・--model
→ ダウンロードしたM2M100モデルの指定。
・--output_dir
→ 変換後の出力先。
・--quantization int8
→ パラメータを8bitに圧縮して、メモリ使用量と翻訳速度を最適化。
・--copy_files ...
→ 翻訳時に必要なトークナイザ設定ファイル(後述)もコピーする設定。
モデルの作成が完了したら、作成したCTranslate2をPythonから呼び出す処理を作ります。
ここで出てくるのが、先ほど保存した、トークナイザ設定ファイルです。
トークナイザとは、
文字列を、モデルが扱いやすい“トークン”単位に分解するものです。
我々にとっての、「単語の区切り」は、翻訳モデルにとって
扱いにくいデータらしく、ある程度の位置で、文字列を分解します。
例えば、 "国際化" という単語を分割するとしたら、
"国"、"際"、"化"
のように 1文字ずつ になることが多いみたいです。
もしくは、もう少しまとめて
"国際"
"化"
になる場合もあるようです。
※この分け方については、モデルや単語によってことなります。
英語での分割としては、
例えば、Internationalizationと言う単語を分割すると、
"Inter", "national", "ization"
と言ったような感じになるようです。
仕組を何となく解説出来たところで、
実際にCLI上で動くコードにまとめて頂きました。
import sys
from transformers import AutoTokenizer
import ctranslate2
#モデル配置ディレクトリ
TOK_DIR = r"D:/dev/transelater/models/m2m100_418M"
CT2_DIR = r"D:/dev/transelater/models/ct2_m2m100_418M"
def load_translator():
tokenizer = AutoTokenizer.from_pretrained(TOK_DIR, local_files_only=True)
translator = ctranslate2.Translator(CT2_DIR, device="cpu", compute_type="int8")
ja_tok = tokenizer.convert_ids_to_tokens([tokenizer.get_lang_id("ja")])[0]
en_tok = tokenizer.convert_ids_to_tokens([tokenizer.get_lang_id("en")])[0]
return tokenizer, translator, ja_tok, en_tok
def translate_text(text: str, target_lang: str):
tokenizer, translator, ja_tok, en_tok = load_translator()
tokens = tokenizer.convert_ids_to_tokens(
tokenizer.encode(text, add_special_tokens=True)
)
# 翻訳先の言語トークンを指定
target_tok = ja_tok if target_lang == "ja" else en_tok
result = translator.translate_batch(
[tokens],
beam_size=4,
target_prefix=[[target_tok]],
)
ids = tokenizer.convert_tokens_to_ids(result[0].hypotheses[0])
return tokenizer.decode(ids, skip_special_tokens=True)
def main():
if len(sys.argv) < 3:
print("Usage: python translate_cli.py [ja|en] \"text to translate\"")
sys.exit(1)
target_lang = sys.argv[1] # ja / en
text = sys.argv[2]
if target_lang not in ("ja", "en"):
print("Error: target language must be 'ja' or 'en'")
sys.exit(1)
translated = translate_text(text, target_lang)
print(translated)
if __name__ == "__main__":
main()
これを、例えば、
python translate_cli.py en "世の中のあらゆる変革と真摯に向き合い、
技術力と挑戦する姿勢をもって「あたりまえ」を書き換える"
と入力して実行すると...
To face all the changes in the world sincerely, with technical strength and challenging attitude, to change the "right"
という英語に翻訳されます!
...されますが、大事なのは内容ですので、こちらの文章を日本語に戻してみます。
この英文をGoogle翻訳で英語から日本語に翻訳してみると...
世の中のあらゆる変化に真摯に向き合い、技術力と挑戦的な姿勢で「正しい」ものを変えていく
となりました!
...英文の時点で?となっていましたが、
「あたりまえ」の部分が、"right"に訳されたからですかね、
一番大事な部分の意味が変わってしまっています。
とは言え、それ以外の文面については、概ね良い感じ(?)だと思いましたが、
皆さんはいかがでしょうか。
おわりに
このように、公開されているモデルを使用することで、サクッと翻訳ソフトが作成できました!
実際の仕様感としては、可もなく、不可もなく、と言った具合でしょうか...
現状は制約のため、仕方なくと言う感が否めない状態ですね...
自分で使っていくにあたり、業界用語や、機能特有の単語を翻訳できるように、
用語集機能を導入したり、
日英以外の翻訳も出来るようにするなど、
より自分の作業にマッチしたソフトにして良ければ、と思いました!