3つのLLMでブラインド多数決!構築中の Claude Sonnet 4.6 翻訳パイプラインを検証してみた

3つのLLMでブラインド多数決!構築中の Claude Sonnet 4.6 翻訳パイプラインを検証してみた

DevelopersIOの技術ブログ翻訳パイプラインをClaude Sonnet 4.6(Amazon Bedrock)へ刷新。Structured Outputsを活用した実装と、3つのモデル(Nova, gpt-oss, Gemini 3.1 Pro)を用いたLLM-as-a-Judgeによる品質評価の裏側を解説します。
2026.03.05

DevelopersIO では 2025 年末より、Amazon Bedrock と Claude を活用した記事の自動英訳機能を提供しています。

https://dev.classmethod.jp/articles/developersio-bedrock-translation-launch/

従来のパイプラインでも Markdown の構造を保持した翻訳はある程度実現できていましたが、本記事では Claude の最新モデル Sonnet 4.6 を採用し、さらなる翻訳品質の向上と、API の効率的な利用を目指す取り組みについて紹介します。

構成

構築中の翻訳パイプラインの構成です。

コンポーネント 技術
翻訳エンジン Amazon Bedrock(Claude Sonnet 4.6、Structured Outputs)
評価エンジン Amazon Bedrock(Nova Pro、gpt-oss-120b)+ Gemini 3.1 Pro
実行環境 AWS Lambda(Python 3.12 / arm64)
データストア Amazon DynamoDB
デプロイ AWS SAM

Structured Outputs で翻訳+要約+推薦文を 1 コールで

翻訳以外の情報、検索などに役立つ要約なども、1 回の LLM 実行から取得したい。その手段として最適だったのが、Bedrock の Structured Outputs でした。

https://dev.classmethod.jp/articles/amazon-bedrock-structured-outputs-json/

スキーマ設計

Bedrock の output_config.format.json_schema を使い、1 回の API コールで 9 フィールドを返させます。

{
  "type": "object",
  "properties": {
    "title":          { "type": "string" },
    "excerpt":        { "type": "string" },
    "content":        { "type": "string" },
    "summary_en":     { "type": "string" },
    "rag_en_s":       { "type": "string" },
    "rag_en_m":       { "type": "string" },
    "rag_en_l":       { "type": "string" },
    "recommendation": { "type": "string" },
    "confidence":     { "type": "integer" }
  },
  "required": ["title", "excerpt", "content", "summary_en",
               "rag_en_s", "rag_en_m", "rag_en_l", "recommendation",
               "confidence"],
  "additionalProperties": false
}
フィールド 用途
title, excerpt, content 翻訳結果(タイトル・抜粋・Markdown 本文)
summary_en 英語要約(3 行箇条書き)
rag_en_s / rag_en_m / rag_en_l 検索プレビュー用 / ベクトル検索用 / 包括的技術要約
recommendation 推薦文(2-3 文)
confidence AI 自己評価(0-100)。異常検知用

additionalProperties: false を指定することで、スキーマ外のフィールドが混入することを防いでいます。

Bedrock 呼び出し

body = {
    "anthropic_version": "bedrock-2023-05-31",
    "max_tokens": 60000,
    "system": [{"type": "text", "text": system_prompt,
                "cache_control": {"type": "ephemeral"}}],
    "messages": [{"role": "user", "content": user_prompt}],
    "output_config": {"format": {"type": "json_schema", "schema": SCHEMA}}
}
response = bedrock.invoke_model(modelId="us.anthropic.claude-sonnet-4-6", body=json.dumps(body))

翻訳プロンプトのポイント

翻訳プロンプトは system prompt に配置しています。全文は長いため、ポイントとなるルール指示を抜粋します。

- Preserve all Markdown formatting symbols (#, *, _, [], (), etc.) in their exact positions
- Never edit, modify, or translate URLs. Keep all URLs exactly as they appear in the original
- Preserve the line break structure of the original document
- Do not start the content translation with a heading

Markdown の構造保持を明示的に指示しています。URL の改変禁止は、翻訳モデルが URL 内の日本語パスを英訳してしまう問題を防ぐためです。

要約フィールドについては、用途ごとに語数と内容の粒度を指定しています。

- summary_en: 3 lines in English, max 50 words per line, Markdown bullet format (- )
- rag_en_s: ~200 words, 1 paragraph. First 80 words MUST contain what the article covers and key outcome
- rag_en_m: ~150 words, dense factual summary. Include technologies used, problem solved, approach taken

実行結果

13,479 文字の技術記事(コードブロック 8 個、Mermaid 図、テーブル多数)で検証しました。

項目
入力トークン 7,704
出力トークン 7,435
処理時間 109 秒
メモリ使用 90 / 256 MB
JSON パースエラー 0 件

Structured Outputs により、長文 Markdown を含む JSON でもパースエラーはゼロでした。Markdown 内のバッククォートやエスケープ文字が JSON を壊す心配がなく、後続処理がシンプルになります。

機械的 QA: 4 項目の品質チェック

翻訳結果に対して、以下の 4 項目を自動チェックしています。

チェック ロジック pass 条件
見出し数 原文と翻訳の # 行数を比較 一致
コードブロック保持 ``` の数を比較 一致
行数比率 翻訳/原文の行数比率 0.8〜1.5
URL 整合性 原文と翻訳の URL セットを比較 完全一致

前処理として改行コードを正規化(\r\n\n)しています。

これに加えて、前述の confidence スコア(0-100)を組み合わせて異常検知に使います。confidence が低い記事は人間レビューの対象とする運用です。

パイロット記事では全項目 pass、confidence 93 でした。

LLM-as-a-Judge: 3 モデルブラインド多数決で品質検証

なぜ LLM-as-a-Judge か

機械的 QA は「見出しが消えた」「URL が変わった」といった構造的な問題は検出できますが、「翻訳が自然か」「技術用語の選択が適切か」は測れません。かといって人間評価は 50 件規模でもコストと時間がかかります。

そこで、複数の LLM に翻訳品質を採点させ、多数決で判定する LLM-as-a-Judge を採用しました。

評価モデルの選定

3 つのモデルを評価者として使用しました。Nova Pro と gpt-oss-120b は Amazon Bedrock 上で利用可能で、Gemini 3.1 Pro は Bedrock 外で手動実行しました。各モデルの特性は評価結果のセクションで詳しく紹介します。

バイアス排除の設計

LLM-as-a-Judge には 2 つの強いバイアスがあります。

バージョン番号バイアス(アンカリング): プロンプトに「Sonnet 3.7」「Sonnet 4.6」と書くと、LLM は「新しいバージョンの方が優れているはず」という事前知識に引きずられる可能性があります。

位置バイアス: 翻訳の提示順序(A/B)が判定に影響する傾向が報告されています。

これらを排除するため、以下の対策を実施しました。

  1. モデル名マスキング: プロンプトには「Translation A」「Translation B」とだけ記載し、モデル名・バージョン情報は一切含めない
  2. A/B 順序ランダム化: 記事ごとに A/B の割り当てをランダムに入れ替え、評価後にスクリプト側で結果を自動反転

評価プロンプト

評価プロンプトは英語で記述しました。評価モデルは英語をより得意とする傾向にあるため、評価の精度と安定性を優先しています。

以下が実際に使用したプロンプトの全文です。

You are an expert bilingual (Japanese-English) technical translation evaluator.
Compare two machine translations of the same Japanese technical blog article.
You MUST choose a winner — ties are NOT allowed.

## Evaluation Criteria (1-10 scale)
1. Accuracy — faithful meaning, correct technical terms, preserved numbers/data
2. Naturalness — reads like native English engineer writing, not "translated Japanese"
3. Technical Precision — AWS/API/code terms handled correctly
4. Structural Fidelity — Markdown structure (headings, tables, code blocks) preserved
5. Readability — easy to follow, logical flow

## Response Format
Return ONLY valid JSON (no markdown fences):
{
  "accuracy_a": <int>, "accuracy_b": <int>,
  "naturalness_a": <int>, "naturalness_b": <int>,
  "technical_a": <int>, "technical_b": <int>,
  "structural_a": <int>, "structural_b": <int>,
  "readability_a": <int>, "readability_b": <int>,
  "winner": "A_much_better" | "A_slightly_better" | "B_slightly_better" | "B_much_better",
  "summary": "<one paragraph explaining the key differences that determined the winner>"
}

---
## Original Japanese

### Title
{ja_title}

### Excerpt
{ja_excerpt}

### Body
{ja_content}

---
## Translation A

### Title
{a_title}

### Excerpt
{a_excerpt}

### Body
{a_content}

---
## Translation B

### Title
{b_title}

### Excerpt
{b_excerpt}

### Body
{b_content}

5 軸(Accuracy, Naturalness, Technical Precision, Structural Fidelity, Readability)で各 1-10 のスコアを付けさせ、総合勝者と差分の要約を JSON で返させています。

評価結果

品質検証のため、Sonnet 4.6 による翻訳と既存の翻訳パイプラインによる翻訳結果を A/B 比較しました。

Nova Pro + gpt-oss-120b 評価

最初の評価では Tie(引き分け)を許容するスキーマで実施しましたが、Nova Pro が 72% の記事で Tie と判定し、評価として機能しませんでした。LLM は差が僅差の場合、最も安全な選択肢である Tie を選ぶバイアスがあるようでした。

そこで Tie を排除した Forced Choice(強制二択)に切り替え、4 段階評価(A_much_better / A_slightly_better / B_slightly_better / B_much_better)で再評価しました。

旧翻訳 勝利 Sonnet 4.6 勝利 Split(意見分裂)
総合判定 2 30 19

モデル別の内訳です。

旧翻訳 勝利 Sonnet 4.6 勝利
Nova Pro (51 件) 2 49
gpt-oss-120b (50 件) 21 29

Nova Pro は Forced Choice にしたことで全件に明確な判定を出すようになり、Sonnet 4.6 を圧倒的に支持しました。gpt-oss-120b も Sonnet 4.6 優勢ですが、旧翻訳を選んだ記事が 21 件ありました。

gpt-oss-120b が旧翻訳を選んだ理由の分析

gpt-oss-120b が旧翻訳を選んだ 21 件の summary を分析したところ、明確なパターンがありました。

理由 件数 対策
空 Excerpt のハルシネーション(元が空なのに本文をコピー) 7 プロンプトに「空なら空文字を返す」を明記 / 前処理で除外
構造忠実性(見出し階層の微差) 9 プロンプトで見出し構造の保持を強化
原文への忠実性(3.7 の方が直訳に近い) 4 意訳と忠実性のバランス調整

特に空だった Excerpt のハルシネーションは、プロンプトに 1 行追加するだけで 7 件が改善する可能性が高く、具体的な改善ポイントとして有用な発見でした。

Gemini 3.1 Pro 詳細評価

AIアシスタントのKiro (Opus 4.6) に以下の方針でサンプルを8件選定させ、出力された判定用プロンプトをWebブラウザ版の Gemini に入力して評価しました。

  • 最長記事(33,330 文字)と最短記事(415 文字)を含める
  • 機械的 QA が fail した記事を含める
  • 技術記事だけでなく非技術記事(入社ブログ)も含める
  • Nova と gpt-oss で判定が割れた争点記事を含める
結果 件数
Sonnet 4.6 勝利 6
Tie 1
旧翻訳 勝利 1

gemini

Gemini が指摘した Sonnet 4.6 の強み

意訳力: 日本語の略語や口語表現を、英語圏で通じる表現に変換していました。

原文 Sonnet 4.6 旧翻訳
LTの資料 lightning talk slides ✅ LT materials ❌
ポン出しのたたき台 rough first draft ✅ a starting point △
差分として検出され detected as a diff ✅ unintended changes being detected △
突然ですが、クイズです Let me start with a quick quiz ✅ Suddenly, here's a quiz ❌

「LT」は日本の技術コミュニティでは一般的な略語ですが、英語圏では通じません。Sonnet 4.6 は "lightning talk slides" と展開しており、Gemini はこれを高く評価しました。「差分として検出され」を "detected as a diff" と訳した点については「Terraform を実際に書く人が翻訳したように読める」とコメントしています。

構造保持: Sonnet 4.6 は :::message:::details といったカスタム Markdown ブロックを正確に保持していました。旧翻訳では :::message ブロックが丸ごと削除されるケースがありました。

文章の再構成: 日本語の長い一文を、英語圏の慣習に合わせて "First... Second... Third..." と分割するなど、単なる翻訳を超えた編集を行っていました。

改善が必要なケース

Gemini 3.1 Pro の詳細評価で旧翻訳が勝利した NocoDB の記事(1,589 文字)から、具体的な改善ポイントが見つかりました。

  • 空フィールドのハルシネーション: 原文の Excerpt が空だったにもかかわらず、Sonnet 4.6 は本文の冒頭をコピーして Excerpt を埋めてしまいました
  • 全角括弧の未変換: () を半角 () に変換しなかった

空フィールドのハルシネーションは前述のバッチ評価でも 7 件で確認されており、プロンプトに「空なら空文字を返す」を明記するか、コード側の前処理で対処できます。全角括弧の変換は後処理の str.replace で機械的に解決すべき問題であり、LLM に任せるべきではありません。

各評価モデルの特性比較

Nova Pro: 高速(2-5 秒)で低コストです。Tie を許容するスキーマでは 72% が Tie に逃げましたが、Forced Choice に切り替えたところ全件で明確な判定を出しました。ただし slightly_better がほとんどで、差の程度は控えめです。大量記事の一次スクリーニングに向いていると思われます。

gpt-oss-120b: reasoning(思考過程)付きで、1 セクションずつ丁寧に比較します。空 Excerpt のハルシネーションや構造の微差など、具体的な改善ポイントを summary から読み取れるのが強みです。一方、reasoning モデル特有の出力形式により JSON パースに失敗するケースがあり(初回 15/51 件、リトライで 1/51 件に改善)、出力の安定性には注意が必要でした。

Gemini 3.1 Pro: 最も詳細な評価を返しました。具体的なフレーズを引用し、「なぜその訳が良いのか」を説明してくれます。typo の検出、ハルシネーションの指摘、さらには「Terraform を実際に書く人が翻訳したように読める」といった文脈を踏まえたコメントまで含まれていました。判断に迷うケースでは Gemini の評価が最も参考になりました。

まとめ

構築中の Sonnet 4.6 の翻訳パイプラインについて、従来版の品質を上回る目処をつけることができました。特に意訳力、カスタム Markdown ブロックの保持、英語圏の文章慣習への適応において優れた結果を示しています。

一方で、gpt-oss-120b や Gemini の評価から、空フィールドに起因するハルシネーションなど、前処理やプロンプトチューニングで対処すべき具体的な課題も明らかになりました。今回導入した LLM-as-a-Judge は、単なる品質の判定にとどまらず、こうした次の改善サイクルへの具体的なインプットとしても強力に機能します。

Sonnet 4.6 へのアップデートと併せて、LLM を活用した評価・改善の仕組みの基盤を整えることができました。今後も翻訳品質の継続的な向上を通じて、より価値ある技術情報を世界へ届けていきたいと考えています。

この記事をシェアする

FacebookHatena blogX

関連記事