Map-Reduce Summarization Pattern
Summarize each chunk independently then synthesize the summaries.
Map-Reduce Summarization Pattern is a free AI Prompt Engineering lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the AI Prompt Engineering learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Map-Reduce Pattern
When a document exceeds the LLM context window, you cannot pass it all at once. The map-reduce pattern solves this:
- Map: summarize each chunk independently
- Reduce: synthesize all chunk summaries into one final summary
This mirrors the classic MapReduce from distributed systems — the same divide-and-conquer logic applied to language tasks.
Step 1: The Map Phase
In the map phase, each chunk is sent to the LLM with a summarization prompt. The model returns a short summary of that chunk only. These summaries are collected into a list.
Each summary should be much shorter than the original chunk — typically 10–20% of the original length. This compression is what makes the reduce step feasible.
import openai
client = openai.OpenAI(api_key='sk-...')
def summarize_chunk(chunk, model='gpt-4o'):
resp = client.chat.completions.create(
model=model,
messages=[
{'role': 'system', 'content': 'Summarize the following text concisely in 3-5 sentences.'},
{'role': 'user', 'content': chunk}
]
)
return resp.choices[0].message.content
def map_phase(chunks):
return [summarize_chunk(c) for c in chunks]Step 2: The Reduce Phase
In the reduce phase, all chunk summaries are concatenated and sent to the LLM with a synthesis prompt. The model produces a single coherent final summary.
If the chunk summaries are still too long to fit in one context window, apply reduce recursively — summarize groups of summaries first, then synthesize those.
def reduce_phase(chunk_summaries, model='gpt-4o'):
combined = '\n\n'.join(
f'Section {i+1}:\n{s}'
for i, s in enumerate(chunk_summaries)
)
resp = client.chat.completions.create(
model=model,
messages=[
{'role': 'system', 'content': 'You are given summaries of consecutive sections of a document. Write a single coherent summary of the entire document.'},
{'role': 'user', 'content': combined}
]
)
return resp.choices[0].message.contentPutting It Together: Raw API
Here is the complete map-reduce pipeline using raw OpenAI API calls — no framework required. This gives you full control over prompts and parameters at each phase.
def map_reduce_summarize(document, chunk_size=1000):
chunks = fixed_chunk(document, max_tokens=chunk_size)
print(f'Chunks: {len(chunks)}')
chunk_summaries = map_phase(chunks)
print(f'Map phase complete. Summaries: {len(chunk_summaries)}')
final_summary = reduce_phase(chunk_summaries)
return final_summary
with open('long_report.txt') as f:
doc = f.read()
result = map_reduce_summarize(doc)
print(result)LangChain MapReduceDocumentsChain
LangChain provides a ready-made MapReduceDocumentsChain that handles chunking, parallel map calls, and the reduce step. It is convenient but less flexible than raw API calls.
from langchain_openai import ChatOpenAI
from langchain.chains.summarize import load_summarize_chain
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.docstore.document import Document
llm = ChatOpenAI(model='gpt-4o', openai_api_key='sk-...')
splitter = RecursiveCharacterTextSplitter(chunk_size=3000, chunk_overlap=200)
with open('long_report.txt') as f:
text = f.read()
docs = splitter.create_documents([text])
chain = load_summarize_chain(llm, chain_type='map_reduce')
result = chain.invoke(docs)
print(result['output_text'])Parallelizing the Map Phase
Each chunk summary is independent, so the map phase can be parallelized. Using Python's ThreadPoolExecutor, all chunk API calls are sent concurrently, dramatically reducing wall-clock time.
from concurrent.futures import ThreadPoolExecutor, as_completed
def map_phase_parallel(chunks, max_workers=10):
summaries = [None] * len(chunks)
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {
executor.submit(summarize_chunk, chunk): i
for i, chunk in enumerate(chunks)
}
for future in as_completed(futures):
idx = futures[future]
summaries[idx] = future.result()
return summariesRecursive Reduce
When a document is very long, the chunk summaries themselves may exceed the context window. Apply reduce recursively: group summaries into batches, reduce each batch, then reduce the batch summaries.
def recursive_reduce(summaries, batch_size=10):
while len(summaries) > 1:
batches = [
summaries[i:i + batch_size]
for i in range(0, len(summaries), batch_size)
]
summaries = [reduce_phase(batch) for batch in batches]
print(f'Reduced to {len(summaries)} summaries')
return summaries[0]Preserving Key Details
A common failure of naive map-reduce: important details are lost during compression. Mitigations:
- Prompt the map step to preserve names, numbers, dates
- Ask the reduce step to check for contradictions between sections
- Use a higher chunk size so the map context is richer
- Run a verification pass: ask the model if key entities from the original appear in the final summary
MAP_PROMPT = '''Summarize the following section in 5 sentences.
Preserve all key names, numbers, dates, and conclusions.
Section:
{chunk}'''Refine Chain: An Alternative Pattern
The refine chain is an alternative to map-reduce. It processes chunks sequentially: the summary of chunk N is passed alongside chunk N+1, and the model updates the running summary. This produces more coherent output but cannot be parallelized and is slower.
Use refine when narrative coherence matters (e.g., legal contracts). Use map-reduce when speed matters (e.g., news article batches).
def refine_summarize(chunks):
current_summary = summarize_chunk(chunks[0])
for chunk in chunks[1:]:
prompt = (
f'Existing summary:\n{current_summary}\n\n'
f'New section:\n{chunk}\n\n'
'Update the summary to incorporate the new section.'
)
resp = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}]
)
current_summary = resp.choices[0].message.content
return current_summaryCost and Token Management
Map-reduce makes many API calls. For a 100-chunk document with gpt-4o at $5/1M input tokens:
- Map: 100 chunks × 1000 tokens = 100k input tokens ≈ $0.50
- Reduce: ~10k tokens (summaries) ≈ $0.05
- Total: ~$0.55 per document
To reduce cost: use gpt-4o-mini for the map phase ($0.15/1M) and gpt-4o only for reduce. This hybrid approach cuts costs by 70% with minimal quality loss.
def map_phase_cheap(chunks):
# Use mini model for map — cheaper, sufficient for chunk summaries
return [
summarize_chunk(c, model='gpt-4o-mini')
for c in chunks
]
def reduce_phase_quality(summaries):
# Use full model for final synthesis
return reduce_phase(summaries, model='gpt-4o')When to Use Map-Reduce
Map-reduce summarization is best for:
- Documents longer than the model context window
- Batch summarization of many documents (parallelize at document level too)
- Situations where you need control over prompt at each step
It is less suited for: extracting a specific fact (use retrieval instead), or when the document is short enough to fit in context (just summarize directly).
Knowledge Check
In the map-reduce summarization pattern, what happens during the reduce phase?
Recap: Map-Reduce Summarization
The map-reduce pattern handles documents too long for a single LLM call:
- Map: summarize each chunk independently — can be parallelized
- Reduce: synthesize chunk summaries into one final summary
- Recursive reduce: apply when summaries themselves are too long
- Cost tip: use a cheap model for map, quality model for reduce
LangChain's MapReduceDocumentsChain provides a ready-made implementation. Next lesson covers hierarchical summarization for books and research papers.
Frequently asked questions
Is the “Map-Reduce Summarization Pattern” lesson free?
Yes — the full text of “Map-Reduce Summarization Pattern” is free to read here on the web, and the AI Prompt Engineering course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the AI Prompt Engineering course, upgrade to CoddyKit PRO.
What will I learn in “Map-Reduce Summarization Pattern”?
Summarize each chunk independently then synthesize the summaries. You practise AI Prompt Engineering with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start AI Prompt Engineering?
No prior experience is required. AI Prompt Engineering on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Map-Reduce Summarization Pattern” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this AI Prompt Engineering lesson?
Yes. Every AI Prompt Engineering lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Chunking Strategies for Long Texts
- Map-Reduce Summarization Pattern
- Hierarchical Summarization
- Maintaining Context Across Chunks