TL;DR
-
Chunking splits documents into retrievable passages — chunk quality directly determines retrieval recall and answer accuracy in RAG.
-
Wrong chunk size is the silent killer — too small loses context, too large adds noise and dilutes embedding signal.
-
Start with recursive splitting at 512 tokens with 50-token overlap — measure recall@k before optimizing.
-
Structure-aware chunking (by heading, section, page) outperforms blind fixed-size splitting for technical docs and manuals.
-
Parent-child and semantic chunking address advanced cases but add complexity — use only when eval shows basic chunking fails.
Why This Matters
Chunking is the most underestimated step in a RAG pipeline. Teams spend weeks tuning LLM prompts and evaluating embedding models while their retriever returns fragments of answers split across chunk boundaries.
Consider a refund policy where the eligibility criteria are in paragraph 2 and the exceptions are in paragraph 3. Fixed-size chunking at 256 tokens might put each in a separate chunk. A user asking "Can I get a refund after 45 days?" retrieves the eligibility chunk (which says "30 days") but misses the exception chunk (which says "45 days for premium members"). The LLM gives a wrong answer from incomplete context.
Across deployed RAG systems, failures often start with chunking — roughly 40% of retrieval issues originate here. Getting chunking right before investing in rerankers, hybrid search, or agentic RAG saves months of iteration.
The Problem Chunking Solves
Documents are too large to embed and retrieve as single units. A 50-page PDF might be 30,000 tokens — far beyond what a single embedding vector can represent faithfully, and too large to pass as context to an LLM alongside other retrieved chunks.
Chunking solves the granularity problem: it determines the unit of retrieval. The chunk is both the atom of search (what the retriever finds) and the atom of context (what the LLM reads). Its size and boundaries affect both retrieval precision and generation quality.
Bad chunking creates three failure modes:
-
Context loss — critical information split across chunks, none retrievable alone.
-
Signal dilution — chunks too large, embedding represents a vague average of multiple topics.
-
Noise injection — chunks contain irrelevant content alongside the answer, confusing the LLM.
How We Got Here
Chunking for RAG evolved from naive character splits to structure-aware and semantic pipelines:
Diagram: Evolution of document chunking
flowchart LR
A[Fixed char split] --> B[Recursive splitter]
B --> C[Heading-aware MD]
C --> D[Semantic boundaries]
D --> E[Parent-child + GraphRAG]
Splitting moved from blind token counts to respecting document structure, then to embedding-based topic boundaries and hierarchical indexes.
| Era | Approach | Limitation |
|---|---|---|
| Early RAG (2020–2021) | Fixed 512-char splits | Split mid-sentence; lost structure |
| Framework defaults (2022) | LangChain RecursiveCharacterTextSplitter |
Better boundaries; still topic-blind |
| Structure-aware (2023) | Markdown headers, PDF layout parsers | Parser quality varies by format |
| Semantic chunking (2024) | Embedding similarity between sentences | Index-time cost; threshold tuning |
| Hierarchical (2025+) | Parent-child, GraphRAG communities | Higher complexity; stronger eval required |
Frameworks such as LangChain text splitters and LlamaIndex node parsers standardised splitter APIs — but chunk parameters remain domain-specific. A stable starting pattern: start recursive at 512/50, prepend headings, measure retrieval evaluation metrics, then escalate strategy only when eval fails.
What Is Document Chunking?
Document chunking (text splitting) is the process of dividing documents into smaller passages optimized for embedding, storage, and retrieval. Each chunk becomes an independent unit in the vector database with its own embedding, metadata, and text payload.
The core parameters:
| Parameter | Description | Typical Range |
|---|---|---|
| Chunk size | Maximum tokens/chars per chunk | 256–1024 tokens |
| Overlap | Shared tokens between adjacent chunks | 10–15% of chunk size |
| Separators | Boundaries where splits are preferred | Paragraph, sentence, word |
| Metadata | Context preserved per chunk | Source, section, page, heading |
# Chunking transforms this document:
document = """
# Refund Policy
## Eligibility
Customers may request refunds within 30 days...
## Exceptions
Premium members have 45 days...
## Process
Submit via the support portal...
"""
# Into these retrievable chunks:
chunks = [
{"text": "Refund Policy > Eligibility\nCustomers may request refunds within 30 days...",
"metadata": {"section": "Eligibility"}},
{"text": "Refund Policy > Exceptions\nPremium members have 45 days...",
"metadata": {"section": "Exceptions"}},
{"text": "Refund Policy > Process\nSubmit via the support portal...",
"metadata": {"section": "Process"}},
]
How Chunking Works
Different strategies make different trade-offs between simplicity, context preservation, and retrieval quality.
Fixed-size chunking
Split every N tokens/characters regardless of content structure.
def fixed_chunk(text: str, size: int = 512, overlap: int = 50) -> list[str]:
tokens = text.split() # use tiktoken in production
chunks = []
for i in range(0, len(tokens), size - overlap):
chunks.append(" ".join(tokens[i:i + size]))
return chunks
Pros: Simple, predictable chunk count, fast. Cons: Ignores document structure, splits mid-sentence and mid-paragraph.
Recursive character splitting
Try splitting by the largest separator first, then fall back to smaller ones.
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=50,
separators=["\n\n", "\n", ". ", " ", ""],
)
chunks = splitter.split_text(document)
Pros: Respects paragraph and sentence boundaries. Good default for most text. Cons: Still ignores semantic topic boundaries within paragraphs.
Semantic chunking
Group sentences by embedding similarity — split when the topic shifts.
def semantic_chunk(sentences: list[str], embed_fn, threshold: float = 0.5) -> list[str]:
chunks, current = [], [sentences[0]]
for i in range(1, len(sentences)):
sim = cosine_similarity(embed_fn(sentences[i-1]), embed_fn(sentences[i]))
if sim < threshold:
chunks.append(" ".join(current))
current = [sentences[i]]
else:
current.append(sentences[i])
chunks.append(" ".join(current))
return chunks
Pros: Chunks align with topic boundaries. Better retrieval for multi-subject documents. Cons: Requires embedding during indexing (slower, costlier). Threshold tuning needed.
Document-aware chunking
Split by document structure — headings, sections, pages, code functions.
def heading_aware_chunk(markdown: str, max_size: int = 512) -> list[dict]:
sections = markdown.split("\n## ")
chunks = []
for section in sections:
heading = section.split("\n")[0]
body = "\n".join(section.split("\n")[1:])
if len(body.split()) <= max_size:
chunks.append({"text": f"{heading}\n{body}", "metadata": {"heading": heading}})
else:
sub = RecursiveCharacterTextSplitter(
chunk_size=max_size, chunk_overlap=50
).split_text(body)
for sc in sub:
chunks.append({"text": f"{heading}\n{sc}", "metadata": {"heading": heading}})
return chunks
Pros: Preserves document hierarchy. Headings provide context in every chunk. Cons: Requires structured input (markdown, HTML). Parser-dependent.
Parent-child chunking
Index small chunks for retrieval but return larger parent chunks for LLM context.
Small chunks embed precisely (better retrieval). Large parent provides full context (better generation). Store parent_id in child metadata and resolve at query time.
Diagram: Parent-child chunk retrieval sequence
sequenceDiagram
participant Q as Query
participant VS as Vector store
participant P as Parent store
participant L as LLM
Q->>VS: ANN on child chunks
VS-->>Q: top child IDs + scores
Q->>P: fetch parent by parent_id
P-->>L: full section context
L-->>Q: grounded answer
Retrieve small for precision; generate from large parent for completeness.
Architecture
Chunking sits in the indexing pipeline between document loading and embedding:
Diagram: Chunking in the RAG indexing pipeline
flowchart TB
subgraph ingest [Ingestion]
PDF[PDF / HTML / MD] --> Parse[Layout parser]
Parse --> Clean[Clean + normalize]
end
subgraph chunk [Chunking layer]
Clean --> Router{Content type?}
Router -->|Docs| Rec[Recursive splitter]
Router -->|MD| Head[Heading-aware]
Router -->|Code| AST[AST splitter]
Rec --> Meta[Enrich metadata]
Head --> Meta
AST --> Meta
end
subgraph index [Indexing]
Meta --> Embed[Embedding model]
Embed --> VDB[(Vector DB)]
end
Route by content type; unify metadata schema before embedding.

Source: Survey on RAG (arXiv:2312.10997)
Key design choices at this layer:
-
One chunker or many? Different document types (PDF, code, markdown) often need different strategies.
-
Where to store chunk metadata? Section headings, page numbers, and parent IDs must travel with the chunk to the vector DB for metadata filtering.
-
Re-chunking trigger? When chunk parameters change, the entire corpus must be re-chunked and re-embedded with the same embedding model.
| Component | Responsibility |
|---|---|
| Parser | Extract clean text + structure from PDF/HTML |
| Chunker | Split into embeddable units with overlap |
| Metadata enricher | Attach tenant, ACL, heading, parent_id |
| Embedder | Convert chunk text to vectors |
| Vector store | Persist for vector search |
Step-by-Step Flow
Step 1: Analyze your corpus. What document types? Average length? Structure (headings, tables, code)? Query types (factoid vs explanatory)?
Step 2: Choose a strategy. Recursive for general text. Document-aware for structured docs. Semantic for multi-topic documents.
Step 3: Set chunk size and overlap. Start 512/50. Align max size with embedding model token limit.
Step 4: Enrich chunks with metadata. Prepend section headings. Attach source file, page number, section ID, and parent chunk ID.
Step 5: Index and evaluate. Embed chunks, run retrieval evaluation. Measure recall@k on your golden test set.
Step 6: Iterate. Adjust size, overlap, or strategy based on failure analysis. Re-chunk and re-embed.
Chunk size guide
| Use Case | Chunk Size | Overlap | Rationale |
|---|---|---|---|
| Factoid Q&A ("What is X?") | 256 tokens | 25 tokens | Small, precise chunks for direct answers |
| General documentation | 512 tokens | 50 tokens | Balanced context and precision |
| Long-form analysis | 768–1024 tokens | 75–100 tokens | Answers need surrounding context |
| Code search | By function/class | N/A | Semantic units are functions, not tokens |
| Legal/regulatory | By clause/section | 0–25 tokens | Structure is legally meaningful |
Diagram: Chunk lifecycle in production
stateDiagram-v2
[*] --> Parsed: document ingested
Parsed --> Chunked: splitter applied
Chunked --> Embedded: vectors stored
Embedded --> Indexed: ANN ready
Indexed --> Retrieved: query match
Retrieved --> [*]
Chunked --> Rechunk: param change
Rechunk --> Embedded
Parameter changes force re-chunk and re-embed — version chunk config in metadata.
Real Production Example
A developer documentation site with 3,000 markdown pages — document-aware chunking with heading injection and tenant metadata:
import hashlib
import tiktoken
from dataclasses import dataclass, field
from pathlib import Path
enc = tiktoken.get_encoding("cl100k_base")
@dataclass
class Chunk:
id: str
text: str
metadata: dict = field(default_factory=dict)
class DocAwareChunker:
def __init__(self, max_tokens: int = 512, overlap: int = 50):
self.max_tokens = max_tokens
self.overlap = overlap
def count_tokens(self, text: str) -> int:
return len(enc.encode(text))
def chunk_markdown(self, content: str, source: str, tenant_id: str) -> list[Chunk]:
chunks = []
current_heading = ""
current_section: list[str] = []
section_tokens = 0
for line in content.split("\n"):
if line.startswith("#"):
if current_section:
chunks.extend(self._flush_section(
current_heading, current_section, source, tenant_id
))
current_heading = line.lstrip("#").strip()
current_section = []
section_tokens = 0
else:
current_section.append(line)
section_tokens += self.count_tokens(line)
if section_tokens >= self.max_tokens:
chunks.extend(self._flush_section(
current_heading, current_section, source, tenant_id
))
overlap_lines = self._tail_overlap_lines(current_section)
current_section = overlap_lines
section_tokens = sum(self.count_tokens(l) for l in current_section)
if current_section:
chunks.extend(self._flush_section(
current_heading, current_section, source, tenant_id
))
return chunks
def _tail_overlap_lines(self, lines: list[str]) -> list[str]:
target, acc = [], 0
for line in reversed(lines):
acc += self.count_tokens(line)
target.insert(0, line)
if acc >= self.overlap:
break
return target
def _flush_section(
self, heading: str, lines: list[str], source: str, tenant_id: str
) -> list[Chunk]:
body = "\n".join(lines).strip()
if not body:
return []
text = f"## {heading}\n{body}" if heading else body
chunk_id = hashlib.sha256(f"{source}:{heading}:{body[:80]}".encode()).hexdigest()[:16]
return [Chunk(
id=chunk_id,
text=text,
metadata={
"source": source,
"heading": heading,
"tenant_id": tenant_id,
"chunk_strategy": "heading-aware-v1",
"chunk_max_tokens": self.max_tokens,
},
)]
# Usage
chunker = DocAwareChunker(max_tokens=512, overlap=50)
for doc_path in Path("docs").rglob("*.md"):
content = doc_path.read_text(encoding="utf-8")
chunks = chunker.chunk_markdown(content, source=str(doc_path), tenant_id="acme")
vector_store.upsert_batch(chunks, embedding_model="text-embedding-3-small")
Every chunk includes its section heading, so a query about "authentication middleware" retrieves chunks prefixed with ## Authentication Middleware — even if the exact phrase is not in the chunk body.
Design Decisions
| Decision | Option A | Option B | When to choose |
|---|---|---|---|
| Strategy | Recursive | Document-aware | Document-aware for structured docs; recursive for everything else |
| Chunk size | 256 tokens | 512 tokens | 256 for factoid Q&A; 512 as general default |
| Overlap | 0% | 10–15% | Always use overlap unless chunks are self-contained sections |
| Heading injection | Prepend heading to chunk | Heading as metadata only | Prepend — improves embedding quality and LLM context |
| Parent-child | Flat chunks | Parent-child index | Parent-child when eval shows retrieval finds right area but chunk lacks context |
| Code chunking | Token-based | AST-based (by function) | AST-based always for code — functions are natural semantic units |
Common patterns
-
Heading prepend — One of the highest-ROI changes for structured docs (+10–15% recall@k).
-
Chunking router — Route PDF → layout parser, MD → heading-aware, code → AST, chat → time windows.
-
Table preservation — Keep tables intact; duplicate headers when splitting long tables.
-
Golden-set driven tuning — Change one parameter at a time; log chunk config version in metadata.
Comparisons
Fixed-size vs recursive vs semantic
| Dimension | Fixed-size | Recursive | Semantic |
|---|---|---|---|
| Structure respect | None | Paragraph/sentence | Topic boundaries |
| Index cost | Lowest | Low | High (embed per sentence) |
| Best for | Prototypes | General text | Multi-topic prose |
| Tuning | Size + overlap | Size + overlap + separators | Similarity threshold |
Chunking vs whole-document indexing
| Dimension | Chunked index | Whole document |
|---|---|---|
| Corpus | Long docs, mixed topics | Short pages (<512 tokens) |
| Retrieval precision | Higher for specific questions | Lower — noise in embedding |
| Context completeness | Risk of fragmentation | Full doc in one vector |
| When to choose | Default for RAG | FAQs, small wiki pages |
Chunking vs GraphRAG community summaries
| Dimension | Text chunking | GraphRAG communities |
|---|---|---|
| Query type | Passage similarity | Global / multi-doc synthesis |
| Index unit | Chunk embeddings | Community summaries + graph |
| Complexity | Low | High |
| When to choose | Standard doc Q&A | "Themes across corpus" questions |
Decision tree: chunking strategy
Decision tree: Choosing a chunking strategy
flowchart TD
A[New RAG corpus] --> B{Avg doc length > 512 tokens?}
B -->|No| C[Index whole documents]
B -->|Yes| D{Structured headings?}
D -->|Yes| E[Heading-aware + recursive fallback]
D -->|No| F{Multi-topic paragraphs?}
F -->|Yes| G[Semantic chunking]
F -->|No| H[Recursive 512/50]
E --> I[Prepend headings]
G --> I
H --> I
I --> J[Eval recall@k]
J --> K{Retrieval OK, context thin?}
K -->|Yes| L[Parent-child index]
K -->|No| M[Ship + monitor]
L --> M
Escalate complexity only when baseline recursive + heading-aware fails retrieval evaluation.
Compare vector stores for chunk metadata support in Best Vector Databases: Qdrant vs Pinecone · Pinecone vs Weaviate · pgvector vs Pinecone.
Common Mistakes
-
Using default chunk size without evaluation. 512 tokens is a starting point, not an answer. Measure recall@k on your data.
-
Zero overlap. Without overlap, information at chunk boundaries is lost. Always use 10–15% overlap unless chunks are naturally self-contained.
-
Splitting tables across chunks. A table header in one chunk and rows in another makes both chunks useless. Keep tables intact or duplicate headers.
-
Ignoring document structure. Blind fixed-size splitting on markdown, HTML, or code destroys the semantic units users query against.
-
Not prepending context. A chunk saying "It supports OAuth 2.0 and SAML" is unretrievable without knowing "It" refers to the authentication system. Include headings and preceding context.
-
Chunking before cleaning. Headers, footers, page numbers, and navigation elements from PDFs pollute chunks. Clean before chunking.
-
Same strategy for all document types. PDFs, code, markdown, and chat logs need different approaches. Build a chunking router by content type.
-
Mismatch with embedding model token limit. Chunks longer than embedding model max tokens truncate silently — the retriever never sees the full passage.
Where It Breaks Down
Highly structured short documents — If most documents are under 512 tokens, chunking adds complexity without benefit. Index whole documents instead.
Cross-reference heavy content — Chunks that say "see Section 4.2" lose meaning without the referenced section. Consider GraphRAG or parent-child chunking.
Real-time content — Chat logs and streaming data need window-based chunking with time boundaries, not static document splitting.
Multimodal content — Images, charts, and diagrams within documents lose meaning when only surrounding text is chunked. Multimodal embeddings or caption extraction are needed.
Non-text content — Audio transcripts, spreadsheets, and JSON documents require domain-specific chunking logic that general text splitters do not provide.
Highly redundant corpora — Duplicate chunks across versions inflate index size and confuse ranking; deduplicate by content hash before embedding.
When NOT to Use Advanced Chunking
Skip semantic or parent-child chunking when:
-
Baseline recursive passes eval — recall@5 ≥ 0.8 on golden set; do not add complexity without measured gain.
-
Documents are uniformly short — Wiki pages, ticket titles, FAQ entries under 256 tokens index whole.
-
Latency budget forbids semantic indexing — Semantic chunking doubles index-time embedding cost.
-
Structure is unavailable — Raw OCR garbage without headings; fix parsing before investing in heading-aware splitters.
-
Graph queries dominate — Relationship traversal needs GraphRAG, not finer text chunks.
Prefer hybrid search when failures are exact-token misses, not boundary fragmentation — chunking will not fix SKU lookup.
Running in Production
Best Practice
✅ Best Practices — Version chunk config in metadata, parallelize chunking offline, deduplicate by hash, and A/B test size changes on a golden set before full re-index.
| Dimension | Consideration |
|---|---|
| Scaling | Chunking is CPU-bound, not GPU. Parallelize across documents. A 100K-document corpus chunks in minutes with recursive splitters. |
| Latency | Chunking happens offline during indexing — not on the query path. Re-chunking the full corpus takes 10–60 minutes depending on strategy. |
| Cost | Semantic chunking requires embedding during indexing (API cost). Recursive/fixed chunking is free (CPU only). |
| Monitoring | Track average chunk size, chunks per document, empty chunks, chunks exceeding max size. Alert on distribution shifts after parser changes. |
| Evaluation | A/B test chunk sizes on recall@k. Compare strategies on a 100-query golden set before full re-index. Benchmark on your own corpus — chunking advice from other domains is useful for comparison but should not replace evaluation on production-like workloads. |
| Security | Chunks inherit document access permissions. Ensure metadata includes permission fields for downstream metadata filtering. |
Tip
Prepend section headings to chunk text before embedding. This single change often improves recall@k by 10–15% on structured documentation.
Important
Store
chunk_strategy,chunk_max_tokens, andchunk_versionin vector metadata. Debugging retrieval failures without knowing how text was split is nearly impossible.
Related Guides
-
Foundations: RAG · Embeddings · Embedding Models
-
Retrieval stack: Vector Search · Hybrid Search · Metadata Filtering · ANN Indexes · Re-ranking
-
Quality & ops: Retrieval Evaluation · Vector Databases
-
Advanced: GraphRAG · Agentic RAG · Late Interaction Retrieval
-
Frameworks: LangChain · LlamaIndex
-
Vector stores: Qdrant · Pinecone · Weaviate · Chroma · pgvector — Best Vector Databases.
-
Head-to-heads: Qdrant vs Pinecone · Pinecone vs Weaviate · pgvector vs Pinecone
If you understood this topic, read next:
Diagram: Learning path for chunking
flowchart LR
A[RAG] --> B[Embeddings]
B --> C[Chunking]
C --> D[Embed Models]
D --> E[Eval]
Prerequisites: RAG · Embeddings
Next topics: Embedding Models · Retrieval Evaluation · Re-ranking
Estimated time: 40 min · Difficulty: Intermediate
Interview Questions
-
Why is chunk size the ceiling on RAG answer quality?
- Expected: chunk is both retrieval unit and LLM context; wrong boundaries → missing or noisy evidence.
-
What overlap percentage do you start with and why?
- Expected: 10–15% of chunk size to preserve boundary information; 50 tokens at 512 default.
-
When does parent-child chunking beat flat chunks?
- Expected: retrieval finds correct region but child too small for generation; fetch parent for LLM context.
-
How do chunk size and embedding model max tokens interact?
- Expected: chunks exceeding model limit truncate silently; align size with embedding model cap.
-
Recursive vs semantic chunking — trade-offs?
- Expected: recursive cheap and good default; semantic aligns topics but adds index-time embed cost.
-
How do you chunk code differently from prose?
- Expected: AST/function boundaries, include imports, not token-based splits mid-function.
-
What metadata must every chunk carry in multi-tenant SaaS?
- Expected: tenant_id, ACL, source URL, heading, chunk_version, parent_id if hierarchical.
-
How do you evaluate a chunking change before full re-index?
- Expected: sample corpus slice, golden queries, recall@k comparison, then staged rollout.
Key Takeaways
- Chunking determines the unit of retrieval — its quality is the foundation of RAG performance.
- Start with recursive splitting at 512 tokens with 50-token overlap.
- Prepend section headings to chunks for better embedding and retrieval.
- Use document-aware chunking for structured content; semantic chunking for multi-topic documents.
- Always evaluate chunking choices with retrieval evaluation — do not guess.
- Different document types need different chunking strategies — build a router.
- Compare vector infrastructure in Best Vector Databases after chunking and embed choices stabilize.
FAQs
What chunk size should I use?
Start with 512 tokens and 50-token overlap. Evaluate recall@k. Decrease to 256 for factoid Q&A; increase to 768–1024 for analytical questions needing context.
How much overlap do I need?
10–15% of chunk size. For 512-token chunks, use 50–75 token overlap. Overlap prevents information loss at boundaries.
Should I chunk by tokens or characters?
Tokens — because embedding models and LLMs operate on tokens. Use tiktoken or the model's tokenizer for accurate counts.
Does chunk size affect embedding quality?
Yes. Very long chunks produce vague embeddings averaging multiple topics. Very short chunks may lack enough signal. Match chunk size to the granularity of your expected queries.
When should I use semantic chunking?
When documents cover multiple topics within paragraphs and recursive splitting creates mixed-topic chunks. Test on your data — semantic chunking adds indexing cost.
How do I chunk PDFs?
Use layout-aware parsers (Unstructured, Docling) that detect headings, tables, and columns. Chunk by section after parsing. Never chunk raw PDF text without parsing.
How do I chunk code?
Split by AST nodes — functions, classes, methods. Each chunk should be a compilable unit with its imports. LlamaIndex CodeSplitter and tree-sitter-based tools handle this.
What is parent-child chunking?
Index small child chunks (256 tokens) for precise retrieval. Store a link to a larger parent chunk (1024 tokens). When a child matches, return the parent to the LLM for full context.
How often should I re-chunk?
Re-chunk when changing chunk size, overlap, or strategy. Re-chunking requires re-embedding. Plan for a full re-index pipeline, not ad-hoc changes.
Can I use different chunk sizes for different document types?
Yes — and you should. Policies might use section-based chunking; chat logs might use time-window chunking; code uses function-based splitting. Route by content type.
How do I handle tables in documents?
Keep tables as single chunks. If a table exceeds max chunk size, split by rows but repeat column headers in each sub-chunk.
Does chunking strategy affect hybrid search?
Indirectly. Better chunks improve both vector and keyword retrieval. Chunk boundaries affect which terms appear together in BM25-indexed text — see hybrid search.
How does chunking relate to reranking?
Chunking affects what candidates reach the reranker. Good chunks improve bi-encoder recall; reranking fixes ordering within retrieved sets — neither compensates for missing chunks.
References
- Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (Lewis et al., 2020)
- LangChain Text Splitters Documentation
- LlamaIndex Node Parser Guide
- Survey on RAG (Gao et al., 2023)