LLMを使った要約は、「長い文章を短くまとめる」という一見単純なタスクに見えますが、実装の現場ではコンテキスト長、精度、コスト、速度の4つが絡み合う奥深い世界です。本記事では、Stuff(一括)・Map-Reduce(分割統治)・Refine(逐次更新)の3パターンを使い分けることが要約システム設計の基本である、という指針を示します。コンテキスト長が128kや200kに伸びた2026年でも、それぞれのパターンには明確な使い所があります。
LLM要約の3つのパターン
LLM要約は処理の構造によって、Stuff、Map-Reduce、Refineの3パターンに大別できます。それぞれの処理フローは下図の通りです。
【Stuff方式】
[全文書] --> [LLM 1回呼び出し] --> [要約]
※ 文書全体が一度にプロンプトに入る場合の最もシンプルな方法
【Map-Reduce方式】
[全文書]
|
+--> [チャンク1] --> [LLM] --> [部分要約1]
+--> [チャンク2] --> [LLM] --> [部分要約2] --> [LLM統合] --> [最終要約]
+--> [チャンクN] --> [LLM] --> [部分要約N]
※ 部分要約は並列実行可能、コンテキスト長を超える文書に適する
【Refine方式】
[チャンク1] --> [LLM] --> [暫定要約1]
|
[チャンク2] --> [LLM] --> [暫定要約2]
|
[チャンクN] --> [LLM] --> [最終要約]
※ 逐次更新、並列化できないが文脈保持が強い
長文要約の実装
コンテキスト長(128k、200k等)を超える文書を要約する場合、Map-Reduceが第一選択です。文書をチャンクに分割し、各チャンクを並列で要約してから、要約の要約を作ります。LangChainを使った実装例を示します。
from langchain_openai import ChatOpenAI
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.chains.summarize import load_summarize_chain
from langchain_core.documents import Document
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
def summarize_long_document(text: str, chunk_size: int = 4000) -> str:
splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=200,
separators=["\n\n", "\n", "。", " ", ""],
)
chunks = splitter.split_text(text)
docs = [Document(page_content=c) for c in chunks]
chain = load_summarize_chain(
llm,
chain_type="map_reduce",
verbose=False,
)
result = chain.invoke({"input_documents": docs})
return result["output_text"]
| パターン | 精度 | 速度 | コスト | 対応文書長 | 適した場面 |
|---|---|---|---|---|---|
| Stuff | 高 | 速い | 低 | コンテキスト長以内 | 短文、固定長文書 |
| Map-Reduce | 中〜高 | 速い(並列) | 中 | 制限なし | 長文、時間優先 |
| Refine | 非常に高 | 遅い(直列) | 高 | 制限なし | 文脈保持が重要 |
| ハイブリッド(階層Map-Reduce) | 高 | 中 | 中〜高 | 制限なし | 超長文(書籍等) |
多文書要約の設計
多文書要約は、複数の独立した文書から1つの要約を作るタスクです。例えば「今週のニュース記事100件を1ページにまとめる」「10件の顧客レビューを分析する」といったケースです。単純な連結だと重複や冗長な表現が多くなるため、段階的な集約が効果的です。
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI()
async def summarize_one(doc: str) -> str:
resp = await client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": f"3行で要約してください:\n{doc}"}],
)
return resp.choices[0].message.content
async def multi_document_summary(docs: list[str], theme: str) -> str:
partials = await asyncio.gather(*[summarize_one(d) for d in docs])
joined = "\n---\n".join(f"[記事{i+1}] {p}" for i, p in enumerate(partials))
prompt = f"以下の複数要約から「{theme}」の観点で統合要約を作成してください:\n{joined}"
final = await client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
)
return final.choices[0].message.content
多文書要約では、統合時に「テーマ」や「観点」を明示すると、出力の軸がブレにくくなります。「共通点」「相違点」「時系列変化」といった軸を指定するだけで、同じ入力から全く異なる有用な要約が得られます。
要約の品質制御
要約品質の評価は、自由文生成タスクの中でも特に難しい部類です。単一の指標では不十分なため、複数の指標を組み合わせる必要があります。
| 指標 | 定義 | 計測方法 | 目標値 |
|---|---|---|---|
| 事実性(Faithfulness) | 要約中の情報が原文に存在するか | LLM-as-Judge または NLI モデル | 95%以上 |
| 網羅性(Coverage) | 原文の重要情報をどれだけ含むか | ゴールド要約とのROUGE | ROUGE-L 0.3以上 |
| 簡潔性(Conciseness) | 冗長表現・重複の少なさ | 文字数比率・重複率 | 元の10〜20% |
| 一貫性(Coherence) | 文章の流れ・読みやすさ | LLM-as-Judge | 4.0/5.0以上 |
| 幻覚率(Hallucination) | 原文にない情報を追加していないか | 事実性の裏返し指標 | 5%以下 |
特に業務利用では事実性が最優先です。要約が多少読みにくくても、事実誤認があると業務判断を誤らせるため、リリース基準に組み込んでください。
ユースケース別の実装例
代表的なユースケースごとに設計のポイントを整理します。
- 議事録要約――発言者・決定事項・アクションアイテムを構造化して出力します。Structured Outputと組み合わせて、「誰が何を担当するか」を明示するのが必須です。音声文字起こしをそのまま渡すとノイズが多いため、前処理でフィラーを除去するとよいでしょう
- レポート要約――数値情報の正確性が重要です。「具体的な数値は原文から引用し、変更しないこと」をプロンプトで強調してください。事実性チェックを別のLLMで行うと安心です
- メール要約――受信トレイ表示用の短要約(1行)と、本文表示前の中要約(3行)の2段階で設計するとUXが良くなります。軽量モデルで十分な品質が出やすいタスクです
- 顧客レビュー要約――センチメント、頻出トピック、代表的な意見を抽出します。多文書要約のパターンを使い、テーマ別にグルーピングすると経営判断に役立つ情報になります
まとめ
要約はシンプルに見えて奥深いタスクです。Stuff・Map-Reduce・Refineの3パターンを使い分け、事実性を最優先に品質制御を行うのが基本設計です。関連記事としてプロンプトエンジニアリング入門、構造化出力、トークンとは、レイテンシ最適化もあわせてご参照ください。
よくある質問(FAQ)
Q1. LLMでコンテキスト長を超える文書を要約するには?
A. Map-Reduce方式(文書を分割→各部分を要約→要約を統合)が一般的です。Refine方式(順番に読みながら要約を更新)は精度が高いですがコストも高くなります。文書の性質に応じて選択してください。文脈の連続性が重要な小説や論文ではRefine、独立した章が多い報告書ではMap-Reduceが適しています。
Q2. LLMの要約精度はどのくらいですか?
A. 一般的なビジネス文書では人間の要約と80〜90%程度の一致度が期待できます。ただし、専門用語が多い文書や数値情報の正確性が求められる場合は、人間レビューの併用が推奨されます。特に法務・医療・金融ドメインでは、要約を最終成果物として使わず、原文参照の導線付きで活用する設計が安全です。
Q3. 要約のコストを抑える方法は?
A. 軽量モデル(GPT-4o mini、Claude Haiku等)の活用、不要な部分の事前フィルタリング、キャッシュの導入が効果的です。単純な要約タスクでは軽量モデルでも十分な品質が得られます。バッチAPIを使えばさらに50%程度のコスト削減が可能です。