% cd ..

翻訳プロンプトを3パターン試してみた

翻訳プロンプトを3パターン試してみた

発端: 自動翻訳が硬い

このブログは Markdown で書いた日本語記事を、Gemini で英訳して posts/en/ に書き出す翻訳パイプラインを動かしています。先日、最初の記事 hello-world.md を編集したので、自動翻訳パイプラインが走りました。出てきた英訳がこちら。

This is the first post of Dazy Dayz Diary.

In this blog, I plan to write tech notes and share my thoughts on movies and anime I have watched.

### Features of this blog

- Articles written in Japanese are automatically translated by AI.
- Translation quality is automatically verified using back-translation.
- Multiple translation models are compared to select the optimal translation.

意味は完全に正しいんですが、英文として 硬いIn this blog, I plan toFeatures of this blogI have watched あたりが典型的な「翻訳された英語」の匂いです。一方、以前手動で書いていた版はこう。

This is the very first post on Dazy Dayz Diary.

I'll be writing about movies, anime, and tech notes on this blog.

### What Makes This Blog Unique

- Blog posts written in Japanese are automatically translated by AI
- Translation quality is verified through back-translation
- Multiple translation models are compared to select the best output

明らかに後者の方が「英語ブログを書いている人の口調」なんですよね。短い・キャッチーな見出し・contraction(I'll)・直接話法。

ところがこの2つを往復翻訳スコア(source_embeddingback_translation_embedding の cosine similarity)で評価すると、AI 版の方がスコアが高い(0.9858)という結果になります。「スコアは高いのに英文としては硬い」という現象が起きていて、これがまさに別記事で詳しく扱った「スコアと人間評価の乖離」の好例です。

仮説: プロンプトに自然さの指示がないのが原因か

translate.ts の翻訳プロンプトを見ると、こんな感じでした。

Translate the following Japanese text to English.
Output ONLY the translated text, no explanations or metadata.
Keep markdown formatting intact.

CRITICAL: Preserve all URLs in markdown links EXACTLY as they appear in the source.
- Do NOT modify, shorten, or "clean up" any URL path...

URL を壊すなとか markdown を保持せよとは書いてあるけど、文体・自然さ・トーンに関する指示が何もない。これでは literal translation に倒れて当然ですね。

そこで、プロンプトを段階的に「自然さ重視」に振った 3 パターンを試して、英訳の品質と往復翻訳スコアを比較してみました。

3 パターン実験

Pattern A: 軽め — 一行追加

  Translate the following Japanese text to English.
+ Write as a native speaker would write a personal blog post — natural, conversational, idiomatic.
  Output ONLY the translated text...

Pattern B: 中 — アンチパターン明示

A に加えて、避けるべき表現を具体的に列挙。

Avoid translation-ese patterns:
- JA→EN: Don't start sentences with "In this blog," or "I plan to" — use direct, conversational voice.
- JA→EN: Use contractions where natural (I'll, I've, don't, it's).
- JA→EN: Headings should be punchy and engaging, not literal restatements of the Japanese.
- EN→JA: 不自然な「〜について」「〜することができます」「この記事では」を避ける。
- EN→JA: 原文にない装飾語(「記念すべき」「ようこそ」「気ままに」など)を勝手に追加しない。

Pattern C: 強め — 「翻訳ではなく rewriting」

「翻訳者」ではなく「バイリンガルブログ編集者」として書き直すように指示。文構造の再構築を積極的に許可。

You are a bilingual blog editor, not a literal translator.
Rewrite the following Japanese text in English so it reads as if it were originally written by a native speaker for a personal blog.
Style requirements:
- Native, idiomatic, conversational. Restructure sentences freely if it helps naturalness.
...

結果

PatternScore英訳の冒頭文
Baseline0.9858This is the first post of Dazy Dayz Diary.
A: 軽め0.9798This is the first post on Dazy Dayz Diary.
B: 中0.9725This is the first post on the Dazy Dayz Diary.
C: 強め0.9383This is my very first post on Dazy Dayz Diary.
手動版(参考)This is the very first post on Dazy Dayz Diary.

英訳の自然さは C が一番手動版に近いmy very first post はまさに手動版の the very first post と同じ味付け。続いて B も I'll be using this space to jot down tech notes のような明らかにブログ的な口調が出てきました。

ところが スコアはきれいに反比例 していて、自然さを上げれば上げるほど score が下がります。

考察: なぜスコアが下がったのか

最初は「自然な意訳をすると意味の保持率が下がるのは仕方ない」と思いました。でも再和訳の中身を見て、もっと根深い問題に気づきました。

Pattern C の再和訳結果がこちら。

# はじめまして!

## ついにスタート

Dazy Dayz Diaryへようこそ。記念すべき初投稿です。

ここでは、日々の技術的な備忘録や、最近観た映画やアニメについての感想を気ままに綴っていこうと思っています。

原文には無い「はじめまして!」「ついにスタート」「ようこそ」「記念すべき」「気ままに」が大量に混入しています。「自然なブログ口調で書け」と指示した結果、LLM が 原文にない装飾を勝手に追加 してしまった。

ここで気づいたのが、translate.ts の構造です。

translateText(sourceText, "Japanese", "English", model)   // forward: 自然な英訳
translateText(translated,  "English",  "Japanese", model) // back:    自然な日訳に!

往復翻訳の両方向で同じプロンプト(自然さ重視)が使われている。つまり再和訳側でも「ネイティブブログ口調で自然に書け」と LLM に頼んでいるので、再和訳が勝手に装飾を追加してしまう。それが原文との cosine 距離を広げ、スコアが下がる、という流れ。

これは「翻訳品質が下がった」のではなく 「評価メカニズムが汚染された」 だけなんですよね。

評価メカニズム汚染という現象

往復翻訳スコアを公平な指標として使うには、再和訳は 常に同じ条件 で行う必要があります。具体的には:

  1. 再和訳側のプロンプトは固定(厳格・literal)にすべき
  2. forward translation はどんなに自由に意訳してもよい
  3. back-translation は「意味だけ正確に拾う、装飾は一切しない」モードで動かす

こうすれば、forward 翻訳がどれだけ自然になっても、back-translation が同じ literal モードで動くので、score は純粋に「forward 翻訳が原文の意味をどれだけ保持しているか」を測れます。

今回の実験では両方向に同じプロンプトを使ってしまったので、Pattern C のスコア 0.9383 は「意味が大きくズレた」のではなく「back-translation が勝手に盛った分だけ離れた」が大半を占めている、と推測できます。

ここまでのまとめ

  1. プロンプト指示で文体は確実に変わるWrite as a native speaker の一行追加だけでも英文の硬さは目に見えて改善する
  2. LLM は禁止指示を必ずしも守らない。「装飾を追加するな」と書いても、ネイティブな日本語を生成する欲求が勝つことがある
  3. 往復翻訳の forward と back は別物として扱う。同じプロンプトで両方を回すと、評価メカニズムが汚染される
  4. スコアは万能ではない。スコアが高い = 英文として優れている、ではない。スコアは「意味の保持率」の代理指標であって、文体の自然さや読みやすさは測れない

続編: プロンプトを分離してみたら、新しい汚染が出てきた

ここまでの考察を踏まえて、translateTextforwardTranslate(自然さ重視、Pattern B 相当)と backTranslate(評価用、literal 固定)の 2 つに分離してみました。これで forward は自由に意訳できて、back は常に同じ条件で測れる、はず。

実行結果がこちら(5 つ目のデータ点)。

PatternScoreback の特徴
Baseline0.9858自然プロンプト両方向
A: 軽め0.9798同上
B: 中0.9725同上
C: 強め0.9383同上、装飾盛り
forward 自然 / back literal0.9537back が機械的・直訳的

英訳の品質は今までで一番良くなりました。

This is the very first post on the Dazy Dayz Diary.

I'll be using this space to jot down tech notes, along with my thoughts on the movies and anime I've been watching lately.

### What makes this blog tick

- All Japanese posts get automatically translated by AI.
- I'm using back-translation to keep the quality in check.
- I'm putting multiple translation models to the test to pick the best results.

This is the very first post は手動版とほぼ同じ。What makes this blog tick も自然な口語表現。再和訳側も「ようこそ」「気ままに」のような装飾が消えて、ちゃんと literal モードで動いている。期待通りです。

ところがスコアは Pattern B (0.9725) より下がって 0.9537。なぜか。

再和訳の中身を見るとわかります。

私はこのスペースを、技術的なメモを書き留めるため、そして最近見ている映画やアニメについての私の考えを書き留めるために使用します。

### このブログを動かしているもの

- すべての日本語の投稿は、AIによって自動的に翻訳されます。
- 私は品質を確認するために、逆翻訳を使用しています。
- 私は最良の結果を選ぶために、複数の翻訳モデルをテストにかけています。

literal 化したことで、機械的・硬い書面語になっています。「私は…使用します」「私は…使用しています」「私は…テストにかけています」みたいな、誰も普段使わない日本語。

一方、原文の同じ範囲はこうでした。

このブログでは、テック系メモや鑑賞した映画・アニメの感想などを書いていく予定です。

### このブログの特徴

- 日本語で書いた記事をAIによって多言語に自動翻訳する
- 往復翻訳(Back-Translation)で翻訳品質を自動検証
- 複数の翻訳モデルを比較して、最適な翻訳を選定

カジュアルな「です・ます」調 + 体言止めの口語日本語。

つまり embedding は 意味だけでなく文体・レジスター(register)も拾う。原文がカジュアル口語なのに、back-translation を堅い literal にすると、意味は同じでも embedding 上で距離が広がる、という現象です。

トレードオフの罠

ここまでの実験で見えてきたのが、往復翻訳スコアの本質的な構造問題です。

戦略問題
Forward 自然 + Back 自然back が装飾を勝手に追加して汚染
Forward 自然 + Back literal文体距離が embedding に乗って汚染
Forward 直訳 + Back 直訳公開英訳が硬い(実用性なし)

この 3 つのトレードオフから抜け出すには、back-translation が 「原文と同じ register を保ちつつ、意味だけ機械的に変換する」 という器用なことをする必要があります。プロンプトでこれを完全に制御するのはおそらく無理です。

さらに気づいた、もう一段の構造問題

ここで「ならばプロンプトを固定して、複数モデルで横並び比較すればいいのでは?」という発想が出てきます。プロンプトという変数を消せば、モデルだけが変数になって公平比較ができる、と。

これは大筋で正しいんですが、実は もう一つ落とし穴 があります。

現状のコードを見ると:

forwardTranslate(text, ja, en, translationModel)  // forward
backTranslate(text,    en, ja, translationModel)  // back ← 同じモデル!

forward と back に 同じモデル を使っています。なので「複数モデル比較」をやると、各モデルで:

  • forward 翻訳の品質も変わる
  • back 翻訳の厳格さ(literal 指示の従順さ)も変わる

スコアがこの両者の合算なので、「forward が良いから高スコア」なのか「back がたまたま原文 register に近い文体を出したから高スコア」なのか区別できません。

これを解決するには、back-translation のモデルを 1 つに固定する 必要があります。

forward (評価対象): gemini-2.5-flash, gemini-3.1-flash-lite, claude-opus, ...
back (固定の判定者): claude-opus-4.6  ← 全モデル共通

これは BLEU や BERTScore で「人間の golden translation を 1 つ用意して全モデルそれと比較する」のと同じ思想です。我々の場合「golden 訳」は無いけど、「golden な back-translator」を 1 つ立てれば代用になります。

つまり、評価メカニズムを健全に保つには 2 つの直交する分離 が必要だとわかりました。

  1. プロンプト分離: forward は自然、back は厳格
  2. モデル分離: back は固定の強いモデル、forward は評価対象モデル

教訓

  1. プロンプト指示で文体は確実に変わるWrite as a native speaker の一行追加だけでも英文の硬さは目に見えて改善する
  2. LLM は禁止指示を必ずしも守らない。「装飾を追加するな」と書いても、ネイティブな日本語を生成する欲求が勝つことがある
  3. 往復翻訳の forward と back は別物として扱う。同じプロンプトで両方を回すと、評価メカニズムが汚染される
  4. embedding は文体・register も拾う。意味だけを純粋に測っているわけではない。原文と back の文体距離が広がるとスコアが落ちる
  5. back-translation のモデルも固定すべき。プロンプトとモデル、両方の変数を消して初めて、forward 翻訳の品質を公平に測れる
  6. スコアは万能ではない。スコアが高い = 英文として優れている、ではない。スコアは複数の要因(意味の保持、文体の一致、評価系の素直さ)の合算で、文体の自然さや読みやすさを直接測れるわけではない

次にやること(とその前に)

真っ当な評価メカニズムを実装するために必要なこと:

  1. runTranslate--back-model オプションを追加し、forward と back のモデルを別指定できるようにする
  2. Supabase の translations テーブルに back_translation_model カラムを追加(または既存の model_nameforward_model にリネーム)
  3. forward プロンプトの最終調整
  4. back プロンプトの最終調整(register-match 方向で再検討)
  5. 複数モデルで一斉比較

ただし、その前に もう少し実験データが必要 だと感じています。今回の実験は hello-world.md ただ 1 記事で行ったもので、サンプル数が圧倒的に少ない。そして書いたプロンプトのアンチパターン例(In this blog,I plan to気ままに記念すべき)も、この記事で出てきた具体的な失敗例に依拠した、過剰に特化した指示になっています。汎用的なプロンプトかどうかは、もっと多様な記事で試してみないとわかりません。

ブログの根幹に関わる仕組みなので、ここで急いで方針転換するより、まずは記事数を増やしながら現状の仕組みで多様な題材のデータを貯め、十分なサンプルが揃ってから本格的なリファクタに着手するのが筋だと思います。

おわりに

「往復翻訳スコアによる翻訳品質評価」というアプローチ自体は健在で、コンセプトとしては有効に機能しています。ただ、実装の細部にこういう罠が潜んでいる という発見が今回の実験の収穫でした。1 記事 1 モデルの小さな実験から、評価メカニズム全体の構造問題まで芋づる式に見えてくる体験は、なかなかスリリングでした。

BLEU や BERTScore のような既存手法も、こういう細部の罠を経て改良されてきたんだろうな、と想像します。個人ブログという小さなスケールでも、研究テーマに正面から取り組むと既存手法の苦労が追体験できるのは、なかなか得難い経験です。

このブログの研究テーマは続きます。