Pruners

Retrieval-Augmented Generation intermediate Building with AI 11 min read

Overview

Pruners are specialized models or heuristic systems that filter out irrelevant retrieved chunks before they reach the generator LLM. In a standard RAG pipeline, the retriever casts a wide net — returning the top-k most similar documents — but similarity doesn’t guarantee relevance. A pruner sits between the retriever and the generator, acting as a quality gate that evaluates each chunk against the user’s query and removes those that would waste context window space or introduce hallucination-inducing noise.

The distinction between pruners and rerankers is important. A reranker re-orders retrieved chunks by relevance but typically passes all of them forward. A pruner makes a binary decision: keep or discard. This is a fundamentally different operation — rerankers optimize ordering, while pruners optimize selection. In practice, the most effective pipelines use both: rerank first, then prune the bottom of the reranked list.

The impact of pruning on output quality is significant. Research on ChunkRAG and similar systems shows that chunk-level pruning can reduce context size by up to 80% while simultaneously improving factual accuracy — the model hallucinates less when it receives only high-signal content. This counter-intuitive result (less input → better output) directly reflects the context rot phenomenon, where overwhelming a model with marginally relevant text degrades its ability to synthesize accurate answers.

How It Works

The Pruning Pipeline Position

Pruners occupy a specific position in the RAG pipeline, after retrieval and reranking but before prompt assembly:

User Query
    ↓
[Retriever] → Top-K chunks (e.g., 20 chunks)
    ↓
[Reranker] → Reordered by relevance score
    ↓
[Pruner] → Filtered to only relevant chunks (e.g., 5-8 chunks)
    ↓
[Prompt Assembly] → System prompt + pruned chunks + query
    ↓
[Generator LLM] → Response
Why Not Just Retrieve Fewer Chunks?

Setting a low top-k (e.g., k=3) risks missing relevant documents entirely — recall drops. A high top-k (e.g., k=20) ensures good recall but includes noise. Pruners solve this tension: retrieve broadly for recall, then prune aggressively for precision. The retriever optimizes for recall; the pruner optimizes for precision.

Pruning Approaches

1. Threshold-Based Pruning

The simplest approach: discard any chunk whose relevance score (from the reranker or retriever) falls below a fixed threshold.

# Simple threshold pruner
def threshold_prune(chunks, scores, threshold=0.65):
    return [
        chunk for chunk, score in zip(chunks, scores)
        if score >= threshold
    ]

# Dynamic threshold based on score distribution
def adaptive_prune(chunks, scores, min_chunks=2, z_threshold=1.0):
    import numpy as np
    mean_score = np.mean(scores)
    std_score = np.std(scores)
    threshold = mean_score - z_threshold * std_score

    pruned = [
        (chunk, score) for chunk, score in zip(chunks, scores)
        if score >= threshold
    ]
    # Guarantee minimum chunks
    if len(pruned) < min_chunks:
        sorted_pairs = sorted(zip(chunks, scores), key=lambda x: -x[1])
        return [c for c, s in sorted_pairs[:min_chunks]]
    return [c for c, s in pruned]

Adaptive thresholds adjust based on the score distribution of each query’s results, handling the fact that some queries naturally produce lower-scoring but still relevant matches.

2. LLM-Based Relevance Pruning

A more sophisticated approach uses a small LLM to evaluate each chunk’s relevance to the query. This is the approach used by systems like CRAG (Corrective RAG) and ChunkRAG:

CRAG (Corrective Retrieval-Augmented Generation)

CRAG introduces a lightweight retrieval evaluator that classifies each retrieved document as “Correct,” “Incorrect,” or “Ambiguous.” Correct documents proceed to generation. Incorrect ones are discarded and may trigger a web search fallback. Ambiguous documents are decomposed into smaller chunks for finer-grained re-evaluation.

# LLM-based chunk relevance scoring (simplified CRAG pattern)
def llm_prune(query, chunks, evaluator_llm):
    pruned = []
    for chunk in chunks:
        prompt = f"""Rate the relevance of this passage to the query.
Query: {query}
Passage: {chunk.text}

Respond with exactly one word: RELEVANT or IRRELEVANT"""

        verdict = evaluator_llm.generate(prompt).strip()
        if verdict == "RELEVANT":
            pruned.append(chunk)
    return pruned

3. ChunkRAG: Fine-Grained Chunk Filtering

ChunkRAG operates at a finer granularity than document-level pruning. It first applies semantic chunking to break documents into coherent units, then evaluates each chunk individually against the query. The key innovation is that it examines chunks within documents rather than treating documents as atomic units — a single long document might have two highly relevant paragraphs buried among ten irrelevant ones.

The process:

  1. Semantic segmentation: Split retrieved documents into semantically coherent chunks using embedding similarity between adjacent sentences.
  2. Relevance scoring: Score each chunk independently against the query using an LLM evaluator.
  3. Filtering: Remove chunks below the relevance threshold.
  4. Reassembly: Reconstruct the pruned context from surviving chunks, maintaining document order for coherence.

4. Self-RAG: Reflection-Based Pruning

Self-RAG takes a different approach by training the generator LLM itself to decide whether retrieved information is useful. The model outputs special “reflection tokens” during generation:

This self-critiquing mechanism effectively makes the generator its own pruner — it can ignore chunks it deems irrelevant during generation rather than relying on a separate filtering stage.

Sentence-Level Pruning Within Chunks

The most aggressive pruning operates at the sentence level within chunks. After a chunk passes the relevance gate, a secondary pruner removes individual sentences that don’t contribute to answering the query. Research shows this can reduce context size by an additional 60-80% beyond chunk-level pruning, while maintaining or improving answer accuracy. The pruned chunk retains its key claims while shedding narrative filler, boilerplate, and tangential details.

Practical Applications

Reducing Hallucinations in Production RAG

The primary value of pruning in production systems is hallucination reduction. When a model receives 10 chunks and only 3 are relevant, it may “blend” information from irrelevant chunks into its answer, producing confident-sounding but factually incorrect responses. By pruning to only the 3 relevant chunks, the model has no irrelevant information to hallucinate from. Studies show that pruning reduces hallucination rates by 15-30% compared to unpruned retrieval.

Latency and Cost Impact

Pruning creates a counterintuitive performance profile: adding a processing step (the pruner) actually reduces end-to-end latency. A cross-encoder reranker + pruner adds 100-200ms of processing but removes 60-80% of context tokens. Since LLM generation time scales with input length, the saved generation time (3,000-7,000ms at typical rates) far exceeds the pruning overhead. The net latency improvement is typically 40-60%.

Multi-Stage Pipeline Design

A production-grade retrieval pipeline often chains multiple pruning stages with increasing precision and cost:

# Multi-stage pruning pipeline
def multi_stage_retrieve(query, vector_db, reranker, pruner_llm):
    # Stage 1: Broad retrieval (fast, high recall)
    candidates = vector_db.search(query, top_k=50)

    # Stage 2: Rerank (moderate cost, improves ordering)
    reranked = reranker.rerank(query, candidates, top_k=15)

    # Stage 3: Threshold prune (cheap, removes obvious misses)
    threshold_pruned = [c for c in reranked if c.score > 0.5]

    # Stage 4: LLM prune (expensive, high precision)
    final_chunks = pruner_llm.evaluate_relevance(query, threshold_pruned)

    return final_chunks  # Typically 3-8 high-signal chunks

Handling Edge Cases

Robust pruners handle several edge cases that naive implementations miss:

Key Takeaways

Further Reading