LangGraph Tutorial (Python): handling long documents for beginners

By Cyprian AaronsUpdated 2026-04-22
langgraphhandling-long-documents-for-beginnerspython

This tutorial shows you how to build a LangGraph workflow that takes a long document, splits it into chunks, summarizes each chunk, and combines the results into one final answer. You need this when a single prompt is too large for your model context window or when you want more reliable processing over long PDFs, reports, policies, or contracts.

What You'll Need

  • Python 3.10+
  • langgraph
  • langchain-core
  • langchain-openai
  • An OpenAI API key set as OPENAI_API_KEY
  • A long text file to test with, or any large string you want to process

Install the packages:

pip install langgraph langchain-core langchain-openai

Step-by-Step

  1. Start by loading your document and splitting it into manageable chunks. For beginners, fixed-size character chunks are good enough to understand the pattern before moving to token-based splitting.
from pathlib import Path

def load_document(path: str) -> str:
    return Path(path).read_text(encoding="utf-8")

def chunk_text(text: str, chunk_size: int = 2000) -> list[str]:
    return [text[i : i + chunk_size] for i in range(0, len(text), chunk_size)]

text = load_document("long_document.txt")
chunks = chunk_text(text)

print(f"Loaded {len(text)} characters")
print(f"Created {len(chunks)} chunks")
  1. Define the graph state and the functions that will process each chunk. The state holds the original chunks, per-chunk summaries, and the final summary.
from typing import TypedDict

class DocumentState(TypedDict):
    chunks: list[str]
    summaries: list[str]
    final_summary: str

def initialize_state(chunks: list[str]) -> DocumentState:
    return {
        "chunks": chunks,
        "summaries": [],
        "final_summary": "",
    }
  1. Create a summarizer node using a real LangChain chat model. This node will summarize one chunk at a time, which keeps each model call within context limits.
import os
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage

llm = ChatOpenAI(model="gpt-4o-mini", api_key=os.environ["OPENAI_API_KEY"])

def summarize_chunk(chunk: str) -> str:
    prompt = (
        "Summarize this document chunk in 5 bullet points. "
        "Focus on facts, decisions, risks, and actions.\n\n"
        f"{chunk}"
    )
    response = llm.invoke([HumanMessage(content=prompt)])
    return response.content
  1. Build the LangGraph workflow with two nodes: one for map-style chunk summarization and one for reducing those summaries into a final result. This is the core pattern for long-document handling.
from langgraph.graph import StateGraph, START, END

def map_summaries(state: DocumentState) -> dict:
    summaries = [summarize_chunk(chunk) for chunk in state["chunks"]]
    return {"summaries": summaries}

def reduce_summaries(state: DocumentState) -> dict:
    combined = "\n\n".join(state["summaries"])
    prompt = (
        "Combine these chunk summaries into one concise document summary. "
        "Preserve important details and remove duplicates.\n\n"
        f"{combined}"
    )
    response = llm.invoke([HumanMessage(content=prompt)])
    return {"final_summary": response.content}

graph = StateGraph(DocumentState)
graph.add_node("map_summaries", map_summaries)
graph.add_node("reduce_summaries", reduce_summaries)
graph.add_edge(START, "map_summaries")
graph.add_edge("map_summaries", "reduce_summaries")
graph.add_edge("reduce_summaries", END)

app = graph.compile()
  1. Run the graph on your document and print the final output. If your source text is large enough, you now have a repeatable pipeline that works around context limits without manual prompt trimming.
if __name__ == "__main__":
    sample_chunks = chunks[:5] if len(chunks) > 5 else chunks
    result = app.invoke(initialize_state(sample_chunks))

    print("\n=== FINAL SUMMARY ===\n")
    print(result["final_summary"])

Testing It

Use a real long text file so you can see multiple chunks being created. A good test is a policy document, annual report, or product spec with at least several thousand characters.

Run the script and confirm that it prints both the number of chunks and a final summary. If the model call fails, check that OPENAI_API_KEY is set correctly and that langchain-openai is installed.

If the output feels too verbose or too short, adjust the summarization prompt in summarize_chunk. For better quality on very large documents, reduce chunk_size or switch from character splitting to token-aware splitting later.

Next Steps

  • Replace fixed-size chunking with RecursiveCharacterTextSplitter from LangChain
  • Add parallel chunk processing with LangGraph fan-out/fan-in patterns
  • Store intermediate summaries in a database or vector store for auditability

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides