translategemmaはGoogleが公開した翻訳モデルです。Gemma 3ベースでオープンなモデルで気軽に使えます。Googleさんありがとうございます。早速、Colab L4環境でollama公式にあるtranslategemma:4bで試してみました(VRAM 利用率:3.8GB/22.5GB)。
4bのモデルでも実用的だと感じました。「猫をかぶる」と言った慣用句は知識あるなしに左右されるようです。プロンプトは推奨されているプロンプト程度は指示を入れ込まないと、余計な注釈が加わったりしました。推奨
blog.google
ollama.com
最初に簡略したプロンプトで試しました。
"Translate the following text from {source_lang} to {target_lang}:\n{text}"
回答例:
Original: 猫の手も借りたいほど忙しい。
Translated: I'm so busy that I'm even willing to borrow a cat's paw.
This is an idiom that expresses being extremely busy and having no time for anything.
Duration: 0.8775 seconds
なんだか、注釈が入ってしましました。これは翻訳タスクとしては良くありません。そこで、推奨プロンプトを使ってみます。
推奨プロンプト:
You are a professional {SOURCE_LANG} ({SOURCE_CODE}) to {TARGET_LANG} ({TARGET_CODE}) translator. Your goal is to accurately convey the meaning and nuances of the original {SOURCE_LANG} text while adhering to {TARGET_LANG} grammar, vocabulary, and cultural sensitivities.
Produce only the {TARGET_LANG} translation, without any additional explanations or commentary. Please translate the following {SOURCE_LANG} text into {TARGET_LANG}:
{TEXT}
回答:
Original Text: 猫の手も借りたいほど忙しい。
New Translation: I'm so busy that I'd even borrow a cat's paw.
Duration: 4.0883 seconds
と、翻訳文だけ返信してくれました。
推奨プロンプトを利用して色々と翻訳してもらいます。
回答例1:
Original: The patient presented with acute abdominal pain localized to the right lower quadrant. An MRI scan revealed inflammation consistent with appendicitis, necessitating immediate surgical intervention.
Translated: 患者は、右下腹部に急性腹痛を訴えました。MRI検査の結果、虫垂炎を示唆する炎症が見られ、直ちに手術が必要と判断されました。
Duration: 0.8748 seconds
回答例2:
Original: 我思う、故に我あり。この命題は、すべてを疑ったとしても、疑っている自分自身の存在だけは疑い得ないということを示している。
Translated: I think, therefore I am. This statement demonstrates that, even if we doubt everything, we can never doubt the existence of the very self that is doing the doubting.
Duration: 0.8501 seconds
これは十分な精度ですね。お手軽に利用できるのは有難いです。折角なのでプロンプトによる影響を調べてみます。
Professional, Casual, Robust Few-Shotの3パターンのプロンプトを考えました。詳細は結果を参照してください。分野によって使い分けるといいのでしょう。Fewshotのプロンプトが意外といい感じです。どのような分野・用途で使うのかを決めたら、プロンプトにFewshotも盛り込むといい感じになるかもしれません。
結果:
--- Item 1: Business (English -> Japanese) ---
Original: We regret to inform you that your application has been declined due to policy changes.
[Professional]: ポリシー変更により、ご応募いただいた内容を却下せざるを得ないことをお詫び申し上げます。 (0.74s)
[Casual]: おー、マジすか?なんか、ポリシーが変わって、あなたの申請、ダメになったってこと? (0.66s)
[Robust FS]: 残念ながら、ポリシー変更により、あなたの申請は却下されました。 (0.58s)
--- Item 2: Business (English -> Japanese) ---
Original: Please expedite the shipment of the Q3 financial reports by close of business today.
[Professional]: Q3の財務報告書を、本日営業時間内にできるだけ早く発送してください。 (0.61s)
[Casual]: ねえ、ちょっと!今日の終わりまでに、3つの四半期の財務報告、早く送ってくれる?お願い! (0.72s)
[Robust FS]: 本日営業時間内に、Q3の財務報告書を迅速に発送してください。 (0.61s)
--- Item 3: Casual (English -> Japanese) ---
Original: Yo, I'm gonna be late for the party, start without me.
[Professional]: ねえ、パーティーには遅れるから、私なしで始めてくれる? (0.57s)
[Casual]: よお、パーティー、マジ遅れるから、みんなでワイワイ始めてな。 (0.61s)
[Robust FS]: やっほー、パーティーには遅れるから、私なしでもいいよ。 (0.64s)
--- Item 4: Casual (English -> Japanese) ---
Original: That movie was totally lit, I can't believe the ending!
[Professional]: その映画は本当に最高だった、結末に驚いた! (0.55s)
[Casual]: あー、あの映画マジで最高だった!え、まさかのラストマジでヤバかった! (0.66s)
[Robust FS]: あの映画は最高だった、信じられない結末だった! (0.57s)
--- Item 5: Idiom (English -> Japanese) ---
Original: Let's call it a day and go home.
[Professional]: では、今日はこれで終わり、家に帰ろう。 (0.50s)
[Casual]: じゃあ、今日は終わりじゃね?家に帰るか。 (0.54s)
[Robust FS]: 今日はこれで終わり、家に帰ろう。 (0.50s)
--- Item 6: Idiom (English -> Japanese) ---
Original: Don't spill the beans about the surprise party.
[Professional]: サプライズパーティーについて、秘密を守ってください。 (0.50s)
[Casual]: ねえ、あそこでサプライズパーティーのこと、絶対に誰にも言わないでよ?マジで! (0.66s)
[Robust FS]: サプライズパーティーについて、秘密を守ってください。 (0.51s)
--- Item 7: Technical (English -> Japanese) ---
Original: The latency of the API endpoint increased significantly under high load.
[Professional]: API エンドポイントのレイテンシは、高負荷時に大幅に増加しました。 (0.61s)
[Casual]: え、マジで?APIのレスポンスがめっちゃ遅くなるってこと?アクセスが多すぎるとか? (0.72s)
[Robust FS]: APIエンドポイントの応答時間が、負荷が高い状況下で大幅に増加しました。 (0.62s)
--- Item 8: Literary (English -> Japanese) ---
Original: The moon hung low in the sky, casting long, eerie shadows across the silent forest.
[Professional]: 月が空に沈み、静かな森に長く、不気味な影を落としていた。 (0.68s)
[Casual]: あー、月がめっちゃ低空飛行してるね。森全体に、マジで怖い影が伸びてて。 (0.73s)
[Robust FS]: 月が空に低く輝き、静かな森に長く、不気味な影を落としていた。 (0.75s)
--- Item 9: Business (Japanese -> English) ---
Original: 平素は格別のご高配を賜り、厚く御礼申し上げます。
[Professional]: We would like to express our sincere gratitude for your continued support. (0.55s)
[Casual]: Hey, just wanted to say thanks for everything, you're a real pal. (0.62s)
[Robust FS]: Thank you very much for your continued support. (0.53s)
--- Item 10: Business (Japanese -> English) ---
Original: 恐れ入りますが、至急ご返信いただけますでしょうか。
[Professional]: We would appreciate it if you could reply as soon as possible. (0.54s)
[Casual]: Hey, just wanted to quickly get in touch. Any chance you could get back to me ASAP? (0.67s)
[Robust FS]: I apologize for the trouble, but could you please reply as soon as possible? (0.63s)
--- Item 11: Casual (Japanese -> English) ---
Original: マジで?それ超ウケるんだけどw
[Professional]: Seriously? That's hilarious! (0.46s)
[Casual]: Seriously? That's hilarious, haha! (0.52s)
[Robust FS]: Seriously? That's hilarious! (0.49s)
--- Item 12: Casual (Japanese -> English) ---
Original: ワンチャン、明日なら行けるかも。
[Professional]: Maybe, if I go tomorrow, it might work. (0.51s)
[Casual]: Hey, maybe I could actually make it tomorrow. (0.51s)
[Robust FS]: There's a chance that I might be able to go tomorrow. (0.59s)
--- Item 13: Idiom (Japanese -> English) ---
Original: 石の上にも三年。
[Professional]: Like moving stones, three years will make anything possible. (0.52s)
[Casual]: Dude, you know what I mean? Like, if you put in the effort, eventually you'll get there. It's like, even if it seems impossible, if you stick with it for a long time, you'll eventually make it. (1.12s)
[Robust FS]: Patience pays off. (0.47s)
--- Item 14: Idiom (Japanese -> English) ---
Original: 猿も木から落ちる。
[Professional]: Even monkeys fall from trees. (0.46s)
[Casual]: Hey, you know, even monkeys fall out of trees, right? (0.57s)
[Robust FS]: Even monkeys can fall from trees. (0.47s)
--- Item 15: Technical (Japanese -> English) ---
Original: 本システムは、冗長性を確保するためにアクティブ・スタンバイ構成を採用しています。
[Professional]: This system employs an active-standby configuration to ensure redundancy. (0.54s)
[Casual]: Hey, so this system is set up with an active/standby thing, right? Basically, it's got like, two parts working at the same time to make sure everything keeps running smoothly, even if one part breaks. (1.03s)
[Robust FS]: This system employs an active-standby configuration to ensure redundancy. (0.58s)
--- Item 16: Technical (Japanese -> English) ---
Original: 患者は急性上気道炎と診断され、抗生物質が処方された。
[Professional]: The patient was diagnosed with acute upper airway inflammation and was prescribed antibiotics. (0.57s)
[Casual]: Hey, so, the doc said he had this really bad upper respiratory infection, like a super nasty cold, and they gave him some antibiotics. (0.77s)
[Robust FS]: The patient was diagnosed with acute upper respiratory infection and was prescribed antibiotics. (0.58s)
--- Item 17: Literary (Japanese -> English) ---
Original: 桜の花びらが、春の風に乗って川面を静かに流れていく。
[Professional]: The petals of the cherry blossoms gently float on the surface of the river, carried by the spring breeze. (0.66s)
[Casual]: Hey, check it out! Those cherry blossoms, they're just floating down the river, like, totally peaceful. It's so pretty, man. (0.82s)
[Robust FS]: The petals of the cherry blossoms drift silently along the surface of the river, carried by the spring breeze. (0.67s)
--- Item 18: Literary (Japanese -> English) ---
Original: 彼の瞳には、言い知れぬ孤独と微かな希望が宿っていた。
[Professional]: His eyes held a strange mixture of loneliness and a faint glimmer of hope. (0.57s)
[Casual]: Dude, his eyes… they were just, like, full of this weird mix of loneliness and a little bit of hope. Man, it was intense. (0.82s)
[Robust FS]: His eyes held an unknown loneliness and a faint glimmer of hope. (0.57s)
検討したプロンプト:
def translate_professional(text, source_lang, target_lang):
"""
Translates text using a strict professional persona.
Enforces formal tone and suppresses conversational filler.
"""
start_time = time.time()
src_code = iso_codes.get(source_lang, "")
tgt_code = iso_codes.get(target_lang, "")
prompt = (
f"Translate the following text from {source_lang} ({src_code}) to {target_lang} ({tgt_code}).\n"
"Output ONLY the translated text. Do not provide explanations, notes, or intro text.\n"
f"\n{text}"
)
result = ollama.generate(model=MODEL_NAME, prompt=prompt)
end_time = time.time()
return result['response'].strip(), end_time - start_time
def translate_casual(text, source_lang, target_lang):
"""
Translates text using a 'close friend' persona.
Enforces casual/plain speech and explicitly forbids polite forms (Desu/Masu) for Japanese.
"""
start_time = time.time()
src_code = iso_codes.get(source_lang, "")
tgt_code = iso_codes.get(target_lang, "")
prompt = (
f"Translate the following text from {source_lang} ({src_code}) to {target_lang} ({tgt_code}).\n"
"Act as a close friend speaking to another friend. Use strictly casual, plain speech (slang is okay).\n"
"If translating to Japanese, use plain form (Da/Dayo/Jann) and STRICTLY FORBID polite forms (Desu/Masu).\n"
"Output ONLY the translated text.\n"
f"\n{text}"
)
result = ollama.generate(model=MODEL_NAME, prompt=prompt)
end_time = time.time()
return result['response'].strip(), end_time - start_time
def translate_robust_fewshot(text, source_lang, target_lang):
"""
Translates text using a few-shot strategy with clear delimiters to handle idioms.
"""
start_time = time.time()
src_code = iso_codes.get(source_lang, "")
tgt_code = iso_codes.get(target_lang, "")
prompt = (
f"Translate the text from {source_lang} ({src_code}) to {target_lang} ({tgt_code}).\n"
"### Instructions ###\n"
"Translate the input text naturally, paying attention to idioms.\n"
"Output ONLY the translation.\n\n"
"### Examples ###\n"
"Input: 彼はいつも猫をかぶっている。\n"
"Output: He's always hiding his true colors.\n"
"Input: It costs an arm and a leg.\n"
"Output: めっちゃ高いわ。\n\n"
"### Task ###\n"
f"Input: {text}\n"
"Output:"
)
result = ollama.generate(model=MODEL_NAME, prompt=prompt)
end_time = time.time()
return result['response'].strip(), end_time - start_time
gist.github.com