Facebook(現Meta)の公開した「No Language Left Behind (NLLB)」をWindowsのPythonで動かして、200以上の言語を素早く無制限&無料で翻訳していきます。
モデルサイズが小さいものもあるため、GPUを使用しなくてもそこそこ応答性の高い翻訳が可能です。
1. 概要 NLLB200とは?何が凄いのか
NLLB200は、200以上の言語を翻訳できるAIです。
他の代表的AI翻訳、接続が不安定なGoogle翻訳無料APIや、クレジットカード登録必須のDeepL翻訳APIと違い、ローカル環境で動かせるのでどれだけ翻訳しても無料かつ安定しています。
(なお電気代)
蒸留(distilled)やパラメーター数を削減したことで、我々のようなローカルAI民にも動かせるサイズのモデルがリリースされています。
モデル名 | モデルタイプ | パラメーター数 |
---|---|---|
NLLB-200 | MoE | 54.5B |
NLLB-200 | Dense | 3.3B |
NLLB-200 | Dense | 1.3B |
NLLB-200-蒸留 | Dense | 1.3B |
NLLB-200-蒸留 | Dense | 600M |
グラボ持ちなら、最大で3.3B(33億パラメーター)、CPU勢でも600M(6億パラメーター)なら何とか実用的速度で翻訳できます。
翻訳品質とVRAM消費量はこちらをご覧ください。
2. Windowsで動かしてみる
動作環境を準備する
以下のコマンドで transformers をインストールします。
pip install transformers
グラボのCUDAコアを使いたい方は以下のコマンドで PyTorch も追加でインストールします。
ただし、PyTorchについてはCUDAバージョンなどに左右されるため、エラーなど出たら公式を確認してください。
ここでは一例として当方の環境(上記画像の通り)のコマンドを載せておきます。
pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu117
CPUのみのコード
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("facebook/nllb-200-distilled-600M")
model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-200-distilled-600M")
article = "I watched a lot of interesting animation last week."
inputs = tokenizer(article, return_tensors="pt")
translated_tokens = model.generate(
**inputs, forced_bos_token_id=tokenizer.lang_code_to_id["jpn_Jpan"], max_length=30
)
result=tokenizer.batch_decode(translated_tokens, skip_special_tokens=True)[0]
print(result)
上記コードを実行すると先週,面白いアニメをたくさん観ました.
と出力されます。
日本語の句点読点ではなく、カンマ・ピリオドを使用して出力されるので、適宜置き換えましょう。
CUDAデバイスありの場合のコード
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
import torch
tokenizer = AutoTokenizer.from_pretrained(
"facebook/nllb-200-distilled-600M",src_lang="eng_Latn"
)
model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-200-distilled-600M")
if torch.cuda.is_available():
model = model.to("cuda:0")
article = """I watched a lot of interesting animation last week."""
inputs = tokenizer(article, return_tensors="pt")
with torch.no_grad():
output_ids = model.generate(
**inputs.to(model.device),
forced_bos_token_id=tokenizer.lang_code_to_id["jpn_Jpan"],
max_length=100
)
result = tokenizer.decode(output_ids.tolist()[0])
print(
result.replace("jpn_Jpan ", "")
.replace("</s>", "")
.replace(".", "。")
.replace(",", "、")
)
上記コードの出力は先週、面白いアニメをたくさん観ました。
です。
以下のコードでCUDAコアを利用するよう設定しています。
if torch.cuda.is_available():
model = model.to("cuda:0")
初回実行時は数GBのモデルダウンロードのため時間がかかります。
実質最大みたいな3.3Bモデルでも約20GBのため意外と軽いですね。
3. 諸々の設定パラメーター
言語選択・最大文字数指定
使用可能な言語一覧とキーの対応はコチラのページにあります。
言語 | キー |
English | eng_Latn |
Japanese | jpn_Jpan |
デフォルト(キー未設定)では入力言語を英語と解釈します。
勿論下のように英語と明示してもOK.
tokenizer = AutoTokenizer.from_pretrained(
"facebook/nllb-200-distilled-600M",src_lang="eng_Latn"
)
出力言語は必ず指定してください。ここでは日本語です。
forced_bos_token_id=tokenizer.lang_code_to_id["jpn_Jpan"],
最大文字数は適当で良いです。英語→日本語だと、元の文章の長さの半分くらい?
max_length=100
4. 対話型翻訳くん(雑な実装)
英語・日本語の双方向の翻訳以外を想定しない、200言語翻訳できる理念に喧嘩売った実装ですがご寛恕ください。
対話型翻訳くん コピペ可コード
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
import torch
# 入力言語( https://github.com/facebookresearch/flores/blob/main/flores200/README.md#languages-in-flores-200)
model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-200-distilled-600M")
if torch.cuda.is_available():
model = model.to("cuda:0")
while True:
select_lang = input("翻訳元の言語は?(en,ja): ")
if select_lang == "en" or "":
input_lang = "eng_Latn"
output_lang = "jpn_Jpan"
elif select_lang == "ja":
input_lang = "jpn_Jpan"
output_lang = "eng_Latn"
else:
pass
article = input("翻訳したい文章入力: ")
tokenizer = AutoTokenizer.from_pretrained(
"facebook/nllb-200-distilled-600M", src_lang=input_lang
)
inputs = tokenizer(article, return_tensors="pt")
with torch.no_grad():
output_ids = model.generate(
**inputs.to(model.device),
forced_bos_token_id=tokenizer.lang_code_to_id[output_lang],
max_length=200,
)
result = tokenizer.decode(output_ids.tolist()[0])
if output_lang == "jpn_Jpan":
result.replace(".", "。").replace(",", "、")
print(result.replace(f"{output_lang} ", "").replace("</s>", ""))
これで出力こんな感じです。
翻訳元の言語は?(en,ja): ja
翻訳したい文章入力: 今日の天気は晴れって聴いてたんだが、結局雨やんけ!!
I heard it was nice today, but it didn't rain!
翻訳元の言語は?(en,ja): en
翻訳したい文章入力: I heard it was nice today, but it didn't rain!
今日はいい日だったって聞いたけど,雨は降らなかった!
翻訳元の言語は?(en,ja):
翻訳したい文章入力: I saw a lot of interesting animation last week, but this week I couldn't watch any of it. Hopefully I'll be able to watch it next week...
先週は面白いアニメがたくさん見ましたが 今週は観られなかったので 来週は観られるかな
翻訳品質をみてみる
割りかしいい感じの精度ですが、文脈に沿えてない箇所も少々ありますね。
青文字が微妙な点です。
- but it didn’t rain!→「結局雨やんけ!」の真逆。これはいけない
- niceを後の文に「rain」とあるのに、晴天でなくいい日としている
- アニメがたくさん見ました→アニメをたくさん見ました
- 今週は観られなかったので→勝手に順接「ので」付けてる
- Hopefullyを「かな」と訳すこと自体は間違いじゃないが、
前の「this week I couldn’t(今週全然見れなかった)」を踏まえると、
→「いいなあ」の方が適切
システム負荷と所要時間
モデル名 | モデルタイプ | パラメーター数 |
---|---|---|
NLLB-200 | MoE | 54.5B |
NLLB-200 | Dense | 3.3B |
NLLB-200 | Dense | 1.3B |
NLLB-200-distilled | Dense | 1.3B |
NLLB-200-distilled | Dense | 600M |
600Mモデルでは、VRAM消費量3.3GBでした。
これなら大抵のグラボで動くうえ、CPUでただのRAMに載せて動かす場合も問題無さそうですね☆
翻訳所要時間は当方のrtx3090では、30単語137文字で1~2秒でした。
NLLB200を利用して日本語非対応のGoogle製質疑応答AI「Flan-t5」を日本語対応させました。
追記:日本語と英語に特化した、NLLB200より高精度かつ軽量な翻訳AI「FuguMT」もあります。
他にも色々とAI関連の記事を書いています。合わせてご覧ください。
画像生成AI「Stable Diffusion」を動かす方法
コード生成AI「santacoder」をWindowsローカル環境で動かす方法
文章生成AI「GPT-2/rinna」をWindowsローカルで動かすには