【ITニュース解説】Translating 300-Page Books with Claude: Taming Token Limits and Context Windows
2026年09月09日に「Dev.to」が公開したITニュース「Translating 300-Page Books with Claude: Taming Token Limits and Context Windows」について初心者にもわかりやすく解説しています。
ITニュース概要
大規模言語モデル(LLM)で長文を翻訳する際、出力トークン制限が課題となる。この記事では、本のような長文を翻訳するため、文章を細かく分割し、前の文脈や専門用語リストを次の翻訳に渡し続けるシステムを開発した。これにより、一貫した高品質な翻訳を効率的に行えるようになった。
ITニュース解説
大規模言語モデル(LLM)の進化により、様々な分野で革新的な技術が生まれている。特に、長い文書の翻訳は非常に魅力的だ。例えば、300ページもの分厚い本を一瞬で別の言語に翻訳できるとしたら、それは素晴らしいことだろう。しかし、このような大規模な翻訳を実現するには、単に「本全体をモデルに渡して翻訳して」とお願いするだけではうまくいかない。そこには、「トークン制限」という技術的な壁が立ちはだかる。
トークンとは、LLMが言語を理解・生成する際に用いる最小単位のことだ。単語の一部や記号、空白などもトークンとして数えられる。例えば、「apple」は1トークン、「apples」も1トークンかもしれないし、「ap」「ple」「s」のように複数に分割されることもある。LLMには、一度に入力できる情報量(入力トークン、これを「コンテキストウィンドウ」と呼ぶ)と、一度に出力できる情報量(出力トークン)にそれぞれ上限が設けられている。今回の翻訳に使われるClaude 3 Sonnetというモデルは、20万トークンという非常に大きな入力コンテキストウィンドウを持っているため、300ページの本(約12万トークン)を丸ごと入力することは技術的には可能に見える。しかし、問題は出力側にある。このモデルの最大出力トークン数はわずか4096トークンなのだ。つまり、入力はできても、その数十倍にもなる本全体の翻訳を一気に出力することはできない。APIは途中で出力が途切れるか、エラーを返すだろう。
もし仮に、無理にでも長い翻訳を出力させようとすると、モデルの性能が著しく低下する。翻訳の品質が落ちるだけでなく、モデルが集中力を失って同じ内容を繰り返したり、存在しない詳細をでっち上げたり(これを「幻覚」と呼ぶ)する可能性もある。このような課題を解決し、長文コンテンツを信頼性高く、かつコスト効率良く翻訳するためのシステムを構築する必要があった。しかも、翻訳全体を通して物語の一貫性を失わないようにしなければならない。
このシステムが満たすべき要件は主に四つだった。一つ目は、ソーステキスト(翻訳元の文章)を、入力と出力の両方のトークン制限に収まるような、扱いやすい小さな固まり(これを「チャンク」と呼ぶ)に分割すること。二つ目は、チャンクを一つずつ翻訳していく際に、前後の文脈を維持し、用語や文体が統一されるようにすること。三つ目は、ユーザーの待ち時間が長くなりすぎないよう、チャンクの処理を並行して行い、効率を上げること。そして四つ目は、PDFやEPUBといった異なるファイル形式からテキストを抽出する際に生じる、ヘッダー、フッター、ページ番号などの余計な情報や、章の構造などに対応することだった。
チャンク分割の戦略は、試行錯誤の結果たどり着いたものだ。最初は、単純に文字数でテキストを切り分ける方法を試した。しかし、これでは文の途中でチャンクが分かれてしまい、翻訳が不自然になったり、代名詞が何を指すのか分からなくなったりする問題が発生した。そこで、段落や文の区切りを意識した分割方法に切り替えた。この際に、tiktokenというツールを使ってトークン数を高速に概算した。これはClaudeの実際のトークンカウントと完全に一致するわけではないが、チャンクのサイズを決める上では十分な精度を持っている。
私たちのシステムでは、ソースチャンクの最大サイズを8000トークンに設定した。これは、翻訳の指示(システムプロンプト)や後述する用語集を含めても、モデルの最大出力である4096トークンに翻訳結果が収まるようにするためだ。さらに重要な工夫として、「オーバーラップ」(重複)を設けた。各チャンクは、前のチャンクの最後の200トークン(約150英単語)を含んで始まるようにしたのだ。これにより、次のチャンクが翻訳される際に、前の文脈の一部をすでに知っている状態になるため、チャンクの境界で発生しがちな不自然な翻訳やエラーを減らす効果があった。また、一つの段落が非常に長く、8000トークンの制限を超えてしまう可能性がある場合は、nltk.sent_tokenizeというツールを使ってその段落をさらに文単位で分割し、確実にチャンクサイズに収まるようにした。
翻訳の品質は、いかに一貫性を保つかに大きく左右される。特に、登場人物の名前、地名、専門用語などが翻訳の途中で変わってしまうと、読者は混乱してしまうだろう。この問題を解決するため、私たちは各チャンクの翻訳を依頼するプロンプトに「実行中の文脈」を含める方法を採用した。この文脈は三つの要素から構成される。一つは、前のソースチャンクの最後の約500文字。二つ目は、その部分がすでに翻訳されたテキスト。そして三つ目は、本全体から事前に抽出した固有名詞のリスト、つまり「用語集」だ。この用語集は、spaCyという自然言語処理ライブラリを使って、本全体のテキストを分析し、人名、組織名、地名などを自動的に抽出して作成した。
この二つの文脈(用語集と前の翻訳の断片)をプロンプトに含めることで、名前の不一致などの翻訳エラーを劇的に減らすことができた。開発当初は、登場人物の名前が後半の章で異なる形で翻訳されるケースが見られたが、用語集を追加してからは、そのようなエラーはほぼゼロになった。
翻訳処理を効率的に進める上で、大規模言語モデルのAPIには「レート制限」という問題がある。これは、短時間のうちにあまりにも多くのリクエストを送ると、API側から一時的に処理を拒否される仕組みのことだ。この制限を遵守しつつ、翻訳速度を上げるため、asyncio.Semaphoreという非同期処理の仕組みを利用した。これにより、複数の翻訳リクエストを並行して実行しながらも、同時に送るリクエスト数を管理し、APIのレート制限に引っかからないように調整できる。例えば、Claude Sonnetの場合、通常は4つのリクエストを同時に実行する設定で運用している。万が一、レート制限によるエラーが発生した場合は、すぐに諦めるのではなく、少し時間を置いてから再度試行する「リトライ処理」も組み込んでいるため、システム全体の安定性が向上する。
現在のシステムでは、前のチャンクの翻訳が次のチャンクの文脈に影響を与えるため、基本的にチャンクは順序通りに一つずつ翻訳している。これにより、物語の連続性を確実に保つことができる。この方法でも、300ページの本であれば約2〜3分で翻訳が完了し、ユーザーの待ち時間も十分に許容範囲だ。
実際の性能とコストについて、具体的な数値を見てみよう。約12万トークンを含む300ページの本を翻訳する場合、システムは約16〜20個のチャンクを生成する。Claude 3 Sonnetを使ってスペイン語に翻訳すると、入力として送られるトークン総数(オーバーラップやプロンプトの指示を含む)は約13万5000トークン、出力される翻訳のトークン総数はおよそ11万トークンとなる。この翻訳にかかるコストは、入力トークンが約0.45ドル、出力トークンが約1.65ドルで、合計で1冊あたり約2.10ドル(日本円で約300円前後)だ。翻訳にかかる時間は、先に述べたように2〜3分だった。
より安価なClaude 3 Haikuモデルも試したが、こちらは1冊あたり約0.35ドルと大幅に安くなるものの、文学作品のような比喩表現が多い文章では翻訳品質が著しく低下した。技術書やノンフィクションであればHaikuでも許容範囲だが、小説の翻訳にはSonnetの利用が適しているという結論に至った。
PDFのようなファイル形式からのテキスト抽出には特有の問題がある。PDFは、ヘッダー、フッター、ページ番号、さらには二段組といったレイアウト情報が、テキストデータの中に混じり込んでしまうことがよくある。これらが翻訳の邪魔をしないよう、私たちはPyMuPDF(またはfitz)というライブラリを利用した。このライブラリを使うと、テキストの各ブロックがPDF上のどこに配置されているかという位置情報(バウンディングボックス)を取得できるため、縦方向の位置に基づいてヘッダーやフッター、ページ番号などの不要な要素を効果的にフィルタリングして除去できる。EPUB形式の場合には、ebooklibを使ってHTML形式のテキストを抽出し、BeautifulSoupで不要なHTMLタグを取り除いた。この方法で、章の区切りを自然なチャンクの境界として利用できた。
このプロジェクトを通じて得た重要な教訓はいくつかある。まず、文字ベースの単純なテキスト分割はうまくいかなかった。文や段落の構造を考慮したチャンク分割と、前後の文脈を補完するオーバーラップが効果的だった。次に、用語集と前の翻訳の断片をプロンプトに含めることで、翻訳の一貫性を保つことができた。非同期処理とリトライ機能は、APIのレート制限に対応し、システムを安定させる上で不可欠だった。また、PDFファイル特有の問題には、PyMuPDFのようなツールで位置情報に基づいたフィルタリングを行うのが有効だった。
一方で、並行処理を追求しすぎてチャンク間の文脈を共有しない翻訳は、かえって品質を低下させることがわかった。さらに、出力トークンの制限を見積もる際、単純なトークン数だけでなく、翻訳先の言語によっては原文よりも20〜30%もトークン数が増える場合がある(特にドイツ語のような言語)。そのため、ソースチャンクのサイズをさらに小さくする必要があることも判明した。詩やコード、表といった特殊なコンテンツを、物語の流れを壊さずに翻訳する最適な方法については、まだ未解決の課題として残っている。
最終的に、大規模言語モデルを使った長文の翻訳は、モデル自体の翻訳能力だけでなく、「文脈管理」がいかに重要であるかを痛感したプロジェクトだった。堅牢なチャンク分割と文脈の伝達をしっかり設計すれば、モデルは残りの翻訳作業を適切にこなしてくれるだろう。