「Gemini 2.5 Pro はコンテキストが長いから、長い文書もそのまま投げればいい」というのは、半分は正しく、半分は業務品質には届きません。100 ページを超える契約書や技術仕様書を相手にすると、モデルに全文を渡すだけでは、読み落とし、ハルシネーション、参照先のズレといった問題が顔を出します。
私が実際に長文読解の業務用途で試行錯誤した中から、効果が大きかった 5 つの設計上の工夫を順番にご紹介します。コードと、実ドキュメントで測った精度の感触もあわせて共有します。
問題設定:200 ページを「要約」だけで終わらせない
業務で長文を読ませる用途は、ほぼこの 3 種類に収束します。
- 条件の抽出:契約書から解約条件・料金改定条項・違約金ルールを洗い出す
- 整合性の検証:同じ契約内で矛盾する記述がないかを検出する
- 変更点の検出:旧版と新版で、内容として変わった箇所を特定する
単なる要約とは違い、どれも「どこに書かれているか」を正確に指せるかが品質を決めます。Gemini 2.5 Pro をただ長いコンテキストとして扱うだけでは、この「指す」能力が安定しないのが実感です。
工夫1:事前セグメンテーション — 全文投入と分割投入を組み合わせる
最初に効くのが、全文を渡す前にドキュメントを構造単位で分割しておく前処理です。単純な固定長分割ではなく、章・節・条項といった意味のあるブロックで切ります。契約書なら「第N条」、議事録なら議題単位、技術仕様書なら見出しレベルで切るのが自然です。
分割したうえで、私は次の 2 パスに分けて処理しています。
パス1:全文スキャン。全文を 1 コンテキストに入れ、「どの章にどんな条件が書かれているか」の目次を Gemini 2.5 Pro に作ってもらいます。出力は短くて構いません。大事なのは、モデルに全体像を把握させることです。
パス2:セグメント精査。パス1 で作った目次をヒントに、該当する章だけを抜き出して再度プロンプトに投げます。このときは「この章に絞って、次の項目を抽出してください」と範囲を明示的に狭めます。
2 パス化することで、1 パスで全文に投げた時に比べて、抽出項目の見落としが目に見えて減りました。私が扱った 180 ページの契約書では、「違約金」関連の条項の検出数が 1 パスで 7 件、2 パスで 11 件と、実に 4 件の見落としが発見されました。どちらも同じモデルを使っています。
Python での骨格はこうです。
from google import genai
from google.genai import types
client = genai.Client()
def pass1_table_of_contents(full_text: str) -> dict:
"""全文を渡して、抽出観点ごとの位置情報を返す目次を作る"""
response = client.models.generate_content(
model="gemini-2.5-pro",
contents=[
"次の契約書について、以下の観点で関連する章番号・節番号を列挙してください。",
"観点: 1) 解約条件 2) 料金改定 3) 違約金 4) 秘密保持",
"出力は JSON で、各観点について関連章のリストを返してください。",
full_text,
],
config=types.GenerateContentConfig(
response_mime_type="application/json",
temperature=0.0,
),
)
return response.parsed
def pass2_extract(segment: str, aspect: str) -> dict:
"""パス1の結果で絞り込まれた章だけを精査する"""
response = client.models.generate_content(
model="gemini-2.5-pro",
contents=[
f"次の契約書の抜粋から、{aspect} に関する条件をすべて列挙してください。",
"出力: JSON 配列。各要素に condition (条件本文), section (条項番号), source_span (原文抜粋 120字以内) を含める。",
segment,
],
config=types.GenerateContentConfig(
response_mime_type="application/json",
temperature=0.0,
),
)
return response.parsed目次 → 精査の 2 段階構造にするだけで、体感で 2 割以上の精度向上が得られます。
工夫2:引用付き回答スキーマで「どこに書いてあったか」を強制する
Gemini 2.5 Pro は長文を前にすると、もっともらしい要約を作ることに得意すぎるという性質があります。指示を工夫しないと「それっぽいが原文にない内容」を返してくることがあります。
これを抑える一番確実な方法は、「原文のどこから拾ったか」を必ず併記させるスキーマを強制することです。response_schema を使うか、JSON モードで厳密にフォーマットを決めます。
from pydantic import BaseModel
from typing import Literal
class Finding(BaseModel):
aspect: Literal["termination", "price_change", "penalty", "nda"]
condition: str # 条件の要約
section_id: str # "第12条 第2項" のような参照
source_quote: str # 原文からの直接引用(120字まで)
confidence: Literal["high", "medium", "low"]
class FindingsResponse(BaseModel):
findings: list[Finding]
response = client.models.generate_content(
model="gemini-2.5-pro",
contents=[instruction, document],
config=types.GenerateContentConfig(
response_mime_type="application/json",
response_schema=FindingsResponse,
temperature=0.0,
),
)source_quote を必須フィールドにするのがポイントです。出力後にこの引用文字列で原文を全文検索し、一致しないものは「ハルシネーション疑い」として弾きます。
def validate_findings(findings, document):
validated = []
for f in findings:
if f.source_quote in document:
validated.append(f)
else:
log.warning(f"uncited: section={f.section_id} quote={f.source_quote[:50]}")
return validated実務で使った感触では、この検証を入れた後の精度は、私の用途で 90 〜 95% 程度まで上がります。残り 5 〜 10% は「意訳」で原文と完全一致しない部分ですが、これは人間が目視確認する前提にすれば許容できます。
工夫3:temperature=0 と思考モードの使い分け
長文読解では temperature=0 が基本です。同じ文書から同じ質問で違う答えが返ってくるのは、業務では受け入れがたい挙動だからです。ただし、0 にすれば安心というわけでもありません。
Gemini 2.5 Pro には内部的な推論の深さがあり、長文に対して「考える余地」を多めに取った方が精度が上がります。API 経由でこれを活かすには、次の 2 点を意識します。
- 出力トークン上限を多めに取る:
max_output_tokensが小さいと、抽出数を自ら絞って出してきます。 - プロンプトで推論順序を指定する:「まず関連条項を列挙し、次に条件を抽出し、最後に整合性を検証する」のように段階を明示します。
instruction = """
次の手順に従って長文を分析してください。
Step 1: 対象観点に関連する可能性のある条項番号をまず列挙します。
Step 2: 列挙した各条項について、関連する条件を抽出します。
Step 3: 抽出した条件同士に矛盾がないか確認し、矛盾があれば明示します。
出力は JSON のみで返してください。
"""このように明示的に手順を指示することで、内部の推論が安定します。思考の過程自体を出力に含めさせる必要はありません。指示としての順序付けが効いているだけで、出力は最終結果の JSON だけで構いません。
工夫4:差分検出は「旧版を先に、新版を後に」がコツ
新旧ドキュメントの差分検出は、長文読解の応用としてよく使われます。ここで効くのが、2 つの文書を渡す順序です。
試した結果、「旧版を先に、新版を後に」という順序の方が、「変更された箇所」の検出精度が高くなります。逆の順序だと、新版を基準に読んでしまい、旧版にあって新版にない条項の検出が弱くなる傾向があります。
contents = [
"旧版(2025年10月版):\n" + old_document,
"新版(2026年4月版):\n" + new_document,
"""
上記の旧版と新版を比較し、次の観点で変更箇所を列挙してください。
1. 削除された条項(旧版にあり、新版にない)
2. 追加された条項(新版にあり、旧版にない)
3. 文言が変更された条項(両版に存在するが内容が変わっている)
各項目に、旧版・新版双方からの該当箇所の引用を必ず含めてください。
""",
]余談ですが、diff ツールが出すテキスト差分を一緒に渡すと、モデルの作業量が減って精度が安定します。行単位の diff を事前に計算し、「機械的に差分がある行のリスト」と「原文全体」を両方渡すのが、私が今落ち着いているやり方です。
工夫5:出力を必ず「検算可能」な形式にする
最後は、出力の形式に関する工夫です。長文読解の結果は、何らかの方法で検算できる形式にしておかないと、運用が続きません。私が好むのは、出力の中に「チェック可能な事実」を埋め込むやり方です。
例えば契約書の条項抽出なら、抽出した各条件に次の 3 つを必ず含めます。
section_id:条項番号(ドキュメント内で一意)source_quote:原文からの直接引用page_hint:何ページ付近にある記述かの目安
このうち source_quote は先ほど述べた全文検索で検算し、section_id は存在する条項番号かどうかを照合し、page_hint は人間が目視確認するときの道しるべに使います。
検算ロジックは短いコードで済みます。
import re
def check_findings(findings, document):
section_ids = set(re.findall(r"第\d+条(?:\s*第\d+項)?", document))
issues = []
for f in findings:
if f.section_id not in section_ids:
issues.append(f"unknown section: {f.section_id}")
if f.source_quote not in document:
issues.append(f"uncited quote in {f.section_id}")
return issuesこのチェックを CI に組み込んでおくと、モデルの出力品質が劣化した時にすぐ気付けます。長文読解を業務に組み込む時、精度の「観測」を持たないままだと、品質が緩やかに下がっても見逃します。
200 ページ級ドキュメントで測った感触
実際に私が社内で試した印象を共有します。モデルは Gemini 2.5 Pro、ドキュメントは 180 ページ前後の日本語契約書です。
- 1 パス全文投入:見落としが 2 〜 3 割。同じ条項を複数回引く傾向あり。
- 2 パス(目次 + 精査):見落とし 5% 以下、重複もほぼなし。処理時間は約 1.7 倍。
- スキーマ強制 + 引用検証あり:ハルシネーション率が 10% 以上 → 2% 以下。処理時間はほぼ変わらず。
- 旧新順序の差分検出:削除検出の再現率が 60% → 90% 近くまで向上。
処理時間は増えますが、人間がレビューに費やす時間はそれ以上に減るため、業務観点では十分ペイします。特に引用検証の効果は大きく、これがないと「モデルの出力を信じていいか」の判断に毎回コストが発生します。
落ちやすい罠 3 つ
最後に、長文読解で私が過去にハマった罠を共有します。
罠1:同じ文書を複数回渡してキャッシュのつもりになる。Gemini にはコンテキストキャッシュの仕組みがありますが、キャッシュが効く条件は細かいので、何も設定せずに毎回全文を渡すと毎回フルの課金になります。長文を繰り返し使うなら、明示的にキャッシュ API を使うことを検討してください。
罠2:PDF を解析せずに渡す。PDF をそのまま添付できる API もありますが、社内文書の場合は事前にテキスト化してから渡す方が、抽出精度が高いケースが多いです。特に表組みを含む契約書はテキスト抽出時に崩れやすいので、事前変換のロジックを作り込む価値があります。
罠3:temperature=0 に過信する。temperature=0 でも、プロンプトを少し変えるだけで結果が変わることはあります。評価用のプロンプトセットを固定し、モデルやプロンプトを変更した時の差分を測れるようにしておくのが安全です。
業務品質のための最後のピース
ここまで述べた 5 つの工夫は、どれも派手な技法ではありません。事前セグメント、引用強制、思考順序の指示、差分順序、検算可能性。地味ですが、これらを重ねていくと、200 ページ級のドキュメントでも安心して業務に組み込める精度に届きます。
最初に仕込むべきは、恐らく「引用付きスキーマ」と「引用検証」です。この 2 つが入るだけで、出力を人間がレビューする時間が大きく減ります。そこから他の工夫を積み上げていくと、長文読解の業務化が現実になります。