DocETL: Agentic Complex Document Processing Guide

The Problem: The Scalability & Accuracy Limits of Naive Document Pipelines
In modern enterprise automation, automated research systems, and web data extraction engines like AiFetchly, data teams are tasked with processing massive corpora of heterogeneous, unstructured documents. Whether analyzing thousands of SEC financial disclosures, clinical trial protocols, customer incident post-mortems, or scraped regulatory filings, organizations need to extract structured, actionable facts from raw text.
Historically, software engineering teams turned to two standard architectures to parse complex document collections with Large Language Models (LLMs):
- Retrieval-Augmented Generation (RAG): Indexing text chunks into a vector database and performing top-$k$ semantic search.
- Naive Map-Reduce Pipelines: Writing manual prompt loops that process each document individually (
map), concatenate intermediate answers, and summarize the combined outputs (reduce).
While functional for elementary tasks, both approaches collapse when confronted with complex document processing tasks—such as multi-hop reasoning, cross-document entity alignment, and corpus-wide thematic synthesis.
The Naive LLM Document Processing Breakdown:
Corpus: 500 Unstructured Multi-Page Incident Reports
│
├─► Approach 1: Monolithic Stuffing (1M+ Tokens into Long-Context LLM)
│ ❌ Catastrophic "Lost-in-the-Middle" attention dilution
│ ❌ Silent hallucination of missing causal links
│ ❌ $50-$100+ API cost per single query run!
│
├─► Approach 2: Standard Vector RAG (Top-K Chunks)
│ ❌ Tunnel vision: Only finds local keyword matches
│ ❌ Cannot answer: "What recurring root causes span 80% of outages?"
│ ❌ Ignores cross-document temporal sequences
│
└─► Approach 3: Heuristic Map-Reduce Script
❌ Token limit overflow during the Reduce phase
❌ Entity mismatch: "Corp X", "Company-X", and "X Inc" treated as 3 entities
❌ Brittle prompt chains that fail silently on schema drift 1. The Context Dilution and “Lost in the Middle” Failure in Monolithic Prompts
Even with 1M+ token context windows in models like Gemini 1.5 Pro and Claude 3.5 Sonnet, stuffing hundreds of multi-page documents into a single prompt produces severe cognitive dilution:
- Attention Degradation: LLM attention mechanisms suffer from the well-documented “Lost in the Middle” phenomenon, reliably prioritizing facts placed near the beginning or end of the prompt while missing subtle details embedded in intermediate documents.
- Economic Inefficiency: Passing 500k tokens per query to answer a single analytical question is economically unsustainable in high-throughput data extraction workflows.
2. The Fragility of Naive Map-Reduce Over Heterogeneous Corpora
When developers build custom Map-Reduce scripts:
- The Reduce Overflow Wall: If each of 500 documents generates a 200-word summary, the intermediate output totals 100,000 words. Attempting to feed this intermediate stream into a single
reduceLLM prompt overflows context limits or degrades output quality. - Context Bleed and Boundary Splitting: Important domain concepts, acronyms, or party definitions introduced on page 1 of a contract are missing when page 15 is processed in isolation during a parallel
mapstep.
3. Cross-Document Entity Disconnect and Quadratic Cost Explosion
Real-world document collections reference the same real-world entities under slightly different names, abbreviations, or typos:
- For example, an incident report corpus may refer to the same database outage as “Aurora Prod US-East”, “AWS RDS Primary”, or “Cluster 04”.
- Without explicit entity resolution, downstream aggregation splits metrics across fragmented buckets.
- However, attempting to perform pairwise entity matching with an LLM incurs a quadratic cost of $O(N^2)$, resulting in tens of thousands of redundant LLM calls.
Engineering teams need a declarative, semantics-aware data processing system that models document workflows as composable primitives and autonomously optimizes execution plans for cost and accuracy.
The Solution: DocETL Declarative Operators and Agentic Optimization
Developed by the EPIC Data Lab at UC Berkeley (VLDB 2025), DocETL is a breakthrough system designed specifically for complex document processing powered by Large Language Models.
DocETL introduces two transformative architectural pillars:
- Declarative Semantic Operators: A rich set of database-inspired operators—including
map,reduce,filter,resolve,gather,unnest, andequijoin—that express complex extraction, cleaning, and aggregation logic in a concise YAML configuration. - The Agentic Query Optimizer: An intelligent LLM-driven query planner that analyzes the user’s initial pipeline, generates semantically equivalent execution rewrites (using 13 specialized rewrite directives), benchmarks them on sample data, and selects the optimal cost-accuracy frontier.
The DocETL Architectural Workflow:
User Specification (High-Level Declarative Pipeline YAML)
│
▼
┌────────────────────────────────────────────────────────┐
│ DocETL Agentic Query Optimizer │
│ • Inspects document schemas and prompt semantics │
│ • Applies 13 Rewrite Directives: │
│ - Map-Decomposition (Splits complex prompts) │
│ - Hierarchical Reduce (Clusters before aggregation) │
│ - Semantic Blocking for Entity Resolution │
│ • Benchmarks candidate plans on synthetic validation │
└────────────────────────────────────────────────────────┘
│ (Optimal Compiled Execution Plan)
▼
┌────────────────────────────────────────────────────────┐
│ Parallel Execution Engine │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Map Worker 1 │ │ Map Worker 2 │ │ Map Worker N │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────┐ │
│ │ Semantic Resolve & Clustering │ │
│ └──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────┐ │
│ │ Hierarchical Multi-Tier Reduce │ │
│ └──────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘
│
▼
Structured Analytical Dataset (Parquet / DuckDB / SQL) The Core Semantic Operators of DocETL
DocETL moves beyond simple map-reduce scripts by providing specialized semantic primitives:
1. Map: Granular Per-Document Extraction
The map operator applies an LLM prompt to each document or chunk independently. In DocETL, map tasks output strictly typed JSON schemas (e.g., extracting dates, participants, severity levels, and specific financial figures) rather than arbitrary prose.
2. Reduce: Keyed and Global Semantic Aggregation
The reduce operator aggregates multiple inputs into a consolidated output. DocETL supports:
- Keyed Reduce: Groups items sharing an exact attribute (e.g., grouping by
departmentorvendor_name) before executing the aggregation prompt. - Global Reduce: Aggregates the entire corpus when computing high-level thematic trends across all documents.
3. Resolve: Automated Cross-Document Entity Disambiguation
One of DocETL’s most powerful native operators is resolve:
- Identifies and clusters heterogeneous text mentions that refer to the same underlying entity (e.g., resolving “Anthropic PBC”, “Anthropic”, and “Anthropic AI”).
- Uses smart semantic blocking (embeddings or rule-based hashing) to eliminate $O(N^2)$ comparisons, evaluating only plausible matches with targeted LLM comparison prompts.
4. Gather and Filter: Scoped Grouping and Semantic Pruning
filter: Discards irrelevant documents early in the pipeline using lightweight LLM classification or exact metadata predicates.gather: Re-assembles fragmented document chunks (e.g., pages or paragraphs) belonging to the same document into a unified context before downstream extraction.
Deep Dive: How the Agentic Query Optimizer Rewrites Pipelines
In classical relational databases (like PostgreSQL or DuckDB), cost-based optimizers rewrite SQL queries using relational algebra (such as pushing down filters or reordering joins).
DocETL pioneers Agentic Query Optimization for LLM Pipelines. The optimizer is an autonomous agent that understands the semantic failure modes of LLMs and restructures naive operator sequences into resilient execution plans.
DocETL Agentic Rewrite Example: Transforming a Naive Map-Reduce
Naive User Plan:
[Raw Documents] ──► [Complex Map Prompt] ──► [Massive Monolithic Reduce]
DocETL Optimized Plan:
[Raw Documents]
│
▼
[Decomposed Map 1: Fact Extraction] (Low-cost fast model)
│
▼
[Decomposed Map 2: Entity Classification & Validation]
│
▼
[Semantic Resolve: Entity Disambiguation & Canonicalization]
│
▼
[Clustering Step: Group into Thematic Sub-Clusters]
│
▼
[Hierarchical Reduce: Reduce Clusters Independently]
│
▼
[Final Meta-Synthesis: Combine Clean Cluster Summaries]
Result: 40% higher accuracy, 65% lower token cost, zero context overflow! 1. The 13 Rewrite Directives: From Map-Decomposition to Hierarchical Reduction
DocETL implements 13 formal rewrite directives that systematically address LLM bottlenecks:
- Map-Decomposition: When an extraction task is overly complex (e.g., “Extract all medical symptoms, dosages, adverse reactions, and pre-existing conditions”), the LLM frequently suffers from cognitive fatigue. DocETL decomposes the prompt into sequential, focused sub-maps, significantly boosting recall.
- Hierarchical Reduce (Cluster-then-Reduce): Rather than passing all items directly into a single massive reduce prompt, DocETL clusters items into semantically coherent groups using embeddings, runs an intermediate reduce on each group, and synthesizes the final meta-output.
- Map-Before-Reduce: If a reduce task requires synthesizing information from long documents, DocETL inserts an intermediate
mapoperator that filters out irrelevant paragraphs first, drastically reducing the token volume passed into the reduce stage. - Semantic Blocking for Resolve: Breaks entity resolution candidates into small, high-probability buckets before running LLM pairwise verifications, transforming an intractable $O(N^2)$ operation into scalable $O(N)$ execution.
- Validation and Retry Injection: Automatically inserts synthetic evaluation assertions to detect when an LLM hallucinated empty arrays or violated formatting constraints.
2. Plan Generation, Validation Benchmarking, and Cost-Accuracy Frontier Selection
The optimization process operates in three phases:
- Candidate Plan Generation: The optimizer inspects the input data schema and user goals, proposing several candidate rewritten pipelines.
- Empirical Validation on Subsets: DocETL samples a small fraction of the dataset (e.g., 10-20 documents) and executes each candidate plan.
- Pareto-Optimal Selection: It scores each candidate based on output accuracy (using an LLM evaluator) and token cost, presenting the engineer with the optimal cost-accuracy trade-off.
Architecture Comparison: DocETL vs. Naive Map-Reduce vs. LangChain vs. Vector RAG
To understand where DocETL fits into the modern enterprise AI stack, the table below compares it against conventional document processing paradigms:
| Capability Dimension | Standard Vector RAG | Naive Python / LangChain Scripts | LlamaIndex Workflows | UC Berkeley DocETL |
|---|---|---|---|---|
| Primary Workload | Point-fact query lookup | Linear sequential prompt chains | DAG-based agent routing | Complex analytical document processing (ETL) |
| Query Paradigm | Semantic similarity ($k$-NN) | Procedural Python code | Graph/Event-driven state | Declarative semantic operators (YAML) |
| Pipeline Optimization | Manual chunk size tuning | None (Manual prompt edits) | Heuristic query planning | Agentic autonomous rewrite optimizer |
| Entity Disambiguation | None (Splits across chunks) | Manual regex / fuzzy matching | Custom prompt agents | Native resolve with semantic blocking |
| Scalability (1,000s of Docs) | High (Vector search) | Low (Context window overflow) | Moderate (Memory-bound) | High (Parallel hierarchical reduction) |
| Token Cost Efficiency | High per query | Poor (Massive redundant tokens) | Moderate | Optimal (Benchmark-guided Pareto selection) |
| Hallucination Resilience | Fragile on corpus-wide queries | High hallucination rate | Moderate | High (Decomposed sub-tasks & validation) |
Practical Implementation: Building an Optimized Document Pipeline with DocETL
Let us construct a complete, production-grade DocETL pipeline designed to process complex software post-mortem reports scraped from engineering blogs and status pages.
Step 1: Install DocETL and Configure the Environment
Install DocETL and initialize your API credentials:
pip install docetl openai
export OPENAI_API_KEY="your-api-key" Step 2: Define a Declarative Pipeline Specification (YAML)
Create a configuration file named incident_pipeline.yaml. This pipeline ingests raw incident documents, extracts root causes, disambiguates affected infrastructure services via resolve, and summarizes systemic failure modes per department:
datasets:
incident_reports:
type: file
path: 'incident_reports.json'
operations:
# Step 1: Decomposed Map - Extract structured failure facts
- name: extract_incident_facts
type: map
prompt: |
Analyze the following infrastructure incident report and extract structured failure details.
Document Content:
{{ input.text }}
Extract:
- root_cause: A concise technical summary of what triggered the outage.
- service_name: The primary affected cloud service or internal component.
- severity: Outage tier (P0, P1, P2, P3).
- downtime_minutes: Duration of customer impact in minutes.
output:
schema:
root_cause: string
service_name: string
severity: string
downtime_minutes: integer
# Step 2: Resolve - Canonicalize service names across different naming conventions
- name: canonicalize_services
type: resolve
blocking_keys:
- service_name
comparison_prompt: |
Determine whether the following two service names refer to the same underlying infrastructure component:
Service A: {{ input.service_name_1 }}
Service B: {{ input.service_name_2 }}
Answer YES if they represent the same system, otherwise NO.
output:
schema:
canonical_service_name: string
# Step 3: Keyed Reduce - Aggregate recurring root causes per canonical service
- name: summarize_systemic_risks
type: reduce
reduce_key:
- canonical_service_name
prompt: |
Synthesize the recurring failure patterns for the service: {{ input.canonical_service_name }}.
Incident Records:
{% for item in input.items %}
- Severity: {{ item.severity }} | Downtime: {{ item.downtime_minutes }}m | Root Cause: {{ item.root_cause }}
{% endfor %}
Provide a bulleted synthesis of:
1. Primary technical vulnerabilities.
2. Recommended architectural hardening steps.
output:
schema:
vulnerabilities: list[string]
hardening_recommendations: list[string]
pipeline:
steps:
- extract_incident_facts
- canonicalize_services
- summarize_systemic_risks Step 3: Run the Agentic Optimizer and Execute the Compiled Plan
Save and execute the following Python script (run_docetl.py):
import json
import time
from docetl import Dataset, Pipeline
def main():
print("Initializing UC Berkeley DocETL Engine...")
start_time = time.perf_counter()
# Load declarative pipeline specification
with open("incident_pipeline.yaml", "r") as f:
pipeline_config = f.read()
pipeline = Pipeline.from_yaml(pipeline_config)
print("Running DocETL Agentic Query Optimizer...")
# The optimizer evaluates sample documents and selects optimal rewrites
optimized_pipeline = pipeline.optimize(
max_cost_budget=5.00, # Cap optimization spend to $5.00
sample_size=10 # Test plans on 10 representative documents
)
print(f"Optimal Plan Generated in {(time.perf_counter() - start_time):.2f}s!")
print("Executing Optimized Document Processing Pipeline...")
execution_start = time.perf_counter()
results = optimized_pipeline.run()
elapsed = time.perf_counter() - execution_start
print(f"\n--- Execution Completed in {elapsed:.2f}s ---")
print(f"Successfully processed {len(results)} service clusters.")
# Export clean structured data for analytical SQL engines
with open("structured_incident_insights.json", "w") as out:
json.dump(results, out, indent=2)
print("Saved clean structured insights to 'structured_incident_insights.json'.")
if __name__ == "__main__":
main() Production Best Practices: Integrating DocETL with Web Scraping and RAG
When pairing DocETL with desktop web scraping and automated extraction engines in AiFetchly, following these enterprise patterns ensures high-throughput reliability:
1. Synergistic Web Ingestion with aiFetchly Scraped Corpora
Autonomous web crawlers and scraping agents frequently extract messy, nested web pages (such as e-commerce catalog reviews, forum discussions, or regulatory bulletins):
- Use AiFetchly to capture raw HTML, tables, and document links from protected client web sessions.
- Pipe the raw harvested JSON directly into DocETL pipelines. DocETL’s
resolveandfilteroperators clean tracking artifacts, resolve duplicate product names, and structure the data into high-value relational tables.
2. Automated Semantic Validation with Synthetic Ground Truth Samples
To prevent schema drift in continuous ETL pipelines:
- Utilize DocETL’s built-in validation generator to maintain a golden dataset of 20 verified documents.
- Run automated regression evaluations whenever you update foundational LLM model versions (e.g., transitioning from GPT-4o-mini to Claude 3.5 Haiku) to guarantee zero loss in extraction precision.
3. Cold-Start Caching and Parallel Execution Topologies
Executing LLM pipelines across thousands of documents requires robust infrastructure failure handling:
- Enable Local SQLite Caching: DocETL natively supports operation-level response caching. If an API rate limit or network partition occurs at step 3, subsequent runs resume instantly without re-billing for completed map tasks.
- Asynchronous Batching: Configure worker concurrency (
max_threads: 16) to saturate enterprise LLM tier limits without triggering429 Too Many RequestsHTTP errors.