Proposition Decomposition — Atomic Facts as Chunks¶
What problem does this solve?¶
A paragraph contains five facts. Embed it, retrieve it, and the embedding represents some average of those five facts. A query about fact 3 may not land at the top because facts 1, 2, 4, 5 dilute the signal. Single-vector embeddings give every chunk one slot in semantic space, regardless of how much actual information it carries. Proposition decomposition cuts each chunk into atomic factual claims using an LLM. Each claim becomes its own retrieval unit with its own vector. Retrieval precision improves because each unit represents one idea. The cost is real — one LLM call per chunk to extract claims — but for factual-recall workloads it is often the cheapest big lift after picking the right embedder.
Where it came from¶
Proposition decomposition was named in the Dense X Retrieval paper (Chen et al., 2023). The idea has older roots in information extraction and open-IE; the contribution was framing it as a chunking strategy for RAG and showing recall improvements on TREC, PopQA, and natural-questions benchmarks. The headline number was 5–9 point gains depending on the base retriever. By 2025 the technique had spread under multiple names — claim extraction, atomic facts, factoid chunking. The cookbook uses Dense X's prompt structure as the reference; all variants converge on the same idea: one fact per retrieval unit, with pronouns resolved to entities. Most production systems pair propositions with a faithfulness check downstream because the extraction step can occasionally invent facts.
Where it fits in the RAG landscape¶
Proposition chunking sits in tension with parent-child (Recipe 9). Both fragment the chunk into smaller retrieval units; they differ on what the smaller units mean.
- Proposition. Atomic factual claims, possibly rewritten to resolve pronouns. Retrieval-optimal at the unit level; generation reads the propositions directly.
- Parent-child. Small chunks (sentences or 100-token windows) for search; the parent (original chunk) is returned for generation context.
Propositions are sharper for factoid recall; parent-child is friendlier for narrative generation. Pick by query shape.
When to use it (and when not to)¶
Use proposition decomposition on factual corpora where queries ask specific questions: encyclopedia, biomedical literature, knowledge-base articles. Each proposition becomes a near-perfect match for a fact-seeking query. Skip it on narrative corpora where the value lives in the flow of ideas, not isolated facts. Books, blog posts, policy documents — propositions reduce them to flat lists and lose the connective tissue the model needs to write a good answer. Skip it when LLM call costs are prohibitive. The decomposition step is one LLM call per chunk; at billions of chunks the bill is real.
The intuition¶
Three intuitions:
Atomicity is the technique. A proposition that says "X is Y because Z" still bundles two facts; split into two. The cleaner the atomicity, the sharper the retrieval signal.
Pronoun resolution is the secret sauce. A proposition that says "It was discovered in 1911" is useless without context. The prompt must instruct the LLM to resolve every pronoun. "Superconductivity was discovered in 1911 by Heike Kamerlingh Onnes" is the kind of proposition that retrieves well.
Storage explodes. A 384-token chunk decomposes to 5–10 propositions, so the index is 5–10x bigger. At small scale, free. At 100M chunks, a serious capacity-planning conversation.
Architecture¶
flowchart LR D[Document] --> C[Chunks] C --> L[LLM:
decompose to atomic
self-contained claims] L --> P[Propositions] P --> E[Embed each
proposition] E --> S[(Vector store)]
References¶
- 📄 Dense X Retrieval — What Retrieval Granularity Should We Use? (Chen et al., 2023) — The paper that framed propositions as a chunking strategy.
- 📚 LlamaIndex Dense X reference implementation — One-click implementation following the paper.
- 📚 Open Information Extraction overview — The information extraction tradition that propositions descend from.
- 📚 Parent-child retrieval (Recipe 9) — Alternative answer to the same problem.
- 📝 Contextual Retrieval (Recipe 7) — Cousin technique — different way to enrich chunks.
- 💻 Semantic chunking (Recipe 5) — Often paired with propositions: semantic boundaries first, then propositions within.
Setup¶
Pick a provider via the PROVIDER env var; everything below is provider-agnostic. The default is Nebius. Tracing is off by default in published notebooks so the outputs are clean — flip COOKBOOK_TRACING=phoenix to send spans to a local Phoenix UI.
import os
os.environ.setdefault('PROVIDER', 'nebius')
os.environ.setdefault('COOKBOOK_TRACING', 'off')
from cookbook.providers import LLMClient
from cookbook.tracing import init_tracing
client = LLMClient()
print(f'Provider: {client.provider} | Chat model: {client.chat_model}')
print(init_tracing())
Provider: nebius | Chat model: meta-llama/Llama-3.3-70B-Instruct Tracing disabled.
Build the Pipeline, Step by Step¶
Step 1 — Load a small corpus slice¶
Proposition decomposition is LLM-heavy. We use six Wikipedia articles to keep the bill modest while still showing the technique.
from cookbook.corpora import load_wikipedia_superconductors
docs = list(load_wikipedia_superconductors())[:6]
print(f'Working with {len(docs)} articles.')
Working with 6 articles.
Step 2 — Run the proposition extractor¶
We use cookbook.chunkers.proposition_split with its default prompt. It walks each document in 600-token windows, asks the LLM for a numbered list of atomic claims with all pronouns resolved, then parses the output.
from cookbook.chunkers import proposition_split
props = proposition_split(docs, chat=client.chat, window_tokens=600)
print(f'Extracted {len(props)} propositions.')
print()
print('First five propositions:')
for p in props[:5]:
print(f' - {p.text}')
Extracted 42 propositions. First five propositions: - Here is the numbered list of atomic, self-contained factual statements: - The Bardeen–Cooper–Schrieffer (BCS) theory is a microscopic theory of superconductivity. - The BCS theory explains many thermodynamic properties of superconductors. - The BCS theory explains many electromagnetic properties of superconductors. - Superconductivity is a microscopic effect caused by a condensation of pairs of electrons known as Cooper pairs.
Step 3 — Index the propositions¶
Standard. Each proposition is one entry in the store.
from cookbook.stores import QdrantBackend
vectors = client.embed([p.text for p in props])
store = QdrantBackend('props', dim=len(vectors[0]))
store.add([p.text for p in props], vectors, ids=[p.chunk_id for p in props])
print(f'Indexed {len(props)} propositions.')
C:\Users\faree\Desktop\rag\rag-cookbook-2026\.venv\Lib\site-packages\tqdm\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html from .autonotebook import tqdm as notebook_tqdm
Indexed 42 propositions.
Step 4 — Compare with classical chunks¶
Build a fixed-window baseline over the same corpus and run the same query against both.
from cookbook.chunkers import fixed_window
chunks = fixed_window(docs, target_tokens=320, overlap_tokens=32)
chunk_v = client.embed([c.text for c in chunks])
chunk_store = QdrantBackend('classic', dim=len(chunk_v[0]))
chunk_store.add([c.text for c in chunks], chunk_v, ids=[c.chunk_id for c in chunks])
q = 'Who first observed superconductivity and in what material?'
qv = client.embed([q])[0]
print('--- Propositions top-3 ---')
for h in store.search(qv, top_k=3):
print(f' {h.score:.3f} {h.text}')
print()
print('--- Classical chunks top-3 ---')
for h in chunk_store.search(qv, top_k=3):
print(f' {h.score:.3f} {h.text[:160]}')
--- Propositions top-3 ---
0.581 The Cooper pairing of electrons in certain materials at low temperatures is responsible for the phenomenon of superconductivity. 0.578 Superconductivity is a microscopic effect caused by a condensation of pairs of electrons known as Cooper pairs. 0.554 The BCS theory explains many electromagnetic properties of superconductors. --- Classical chunks top-3 --- 0.546 # BCS theory _Source: Wikipedia, CC BY-SA 4.0_ In physics, the Bardeen–Cooper–Schrieffer (BCS) theory is a microscopic theory of superconductivity which explain 0.521 # Cooper pair _Source: Wikipedia, CC BY-SA 4.0_ In condensed matter physics, a Cooper pair or BCS pair is a pair of electrons bound together at low temperatures 0.503 # Cuprate superconductor _Source: Wikipedia, CC BY-SA 4.0_ Cuprate superconductors are a family of high-temperature superconducting materials made of layers of
Step 5 — Wrap as answer_question¶
Standard contract. The retrieved propositions go straight to the LLM as context. We retrieve more propositions (k=8) than chunks (k=5) because each unit is smaller.
def answer_question(question: str, k: int = 8) -> tuple[str, list[str]]:
qv = client.embed([question])[0]
hits = store.search(qv, top_k=k)
contexts = [h.text for h in hits]
answer = client.chat(
'Use these atomic facts.\n' + '\n'.join(contexts) + f'\nQ: {question}\nA:'
)
return answer, contexts
ans, _ = answer_question('Who first observed superconductivity and when?')
print(ans)
The provided atomic facts do not mention who first observed superconductivity or when. They provide information about the nature of superconductivity, the BCS theory, and properties of superconductors, but do not include historical details about the discovery of superconductivity.
Look Inside¶
Inspect — quality of the extracted propositions¶
Sample five propositions and judge whether they are atomic and self-contained. Bad propositions are unresolved pronouns or compound claims.
import random
for p in random.sample(props, 5):
print(f' - {p.text}')
- The BCS theory explains many thermodynamic properties of superconductors. - In thermodynamics, a critical point is the end point of a phase equilibrium curve. - Superconductivity is a microscopic effect caused by a condensation of pairs of electrons known as Cooper pairs. - A ferromagnet–paramagnet transition occurs in the absence of an external magnetic field. - A gas in a supercritical phase cannot be liquefied by pressure alone.
Inspect — propositions per original chunk¶
How much does the index inflate? We grouped propositions by their source document; divide by the number of source chunks the document had.
from collections import Counter
by_doc = Counter(p.doc_id for p in props)
for doc_id, n in by_doc.most_common(5):
print(f' {doc_id}: {n} propositions')
wiki:Bose–Einstein_condensate: 9 propositions wiki:Critical_temperature: 9 propositions wiki:BCS_theory: 7 propositions wiki:Cooper_pair: 6 propositions wiki:Cuprate: 6 propositions
Inspect — does a factoid query retrieve sharper hits?¶
Compare scores: with propositions, the top hit's score is usually higher than the top hit's score with classical chunks. That sharper score means downstream rerankers and confidence-thresholding work better.
for q in [
'In what year was YBCO discovered?',
'What does Cooper pair mean?',
'Who proposed BCS theory?',
]:
qv = client.embed([q])[0]
p_top = store.search(qv, top_k=1)[0]
c_top = chunk_store.search(qv, top_k=1)[0]
print(f' {q}')
print(f' prop top score = {p_top.score:.3f}')
print(f' chunk top score = {c_top.score:.3f}')
In what year was YBCO discovered?
prop top score = 0.464
chunk top score = 0.439
What does Cooper pair mean?
prop top score = 0.793
chunk top score = 0.772
Who proposed BCS theory?
prop top score = 0.773
chunk top score = 0.683
Inspect — cost in cached embeddings + LLM calls¶
Measure how many LLM calls and embeddings the proposition extraction consumed. Useful for cost projection on a real corpus.
from cookbook import _cache
stats = _cache.stats()
print(f'Total cache entries (chat + embed): {stats["entries"]}')
print()
print(f'For this notebook the extractor processed roughly {len(docs)} docs')
print(f'and produced {len(props)} propositions.')
print(f'Estimated cost: ~{len(docs) * 3} LLM calls (one per window per doc) + {len(props)} embeddings.')
Total cache entries (chat + embed): 3508 For this notebook the extractor processed roughly 6 docs and produced 42 propositions. Estimated cost: ~18 LLM calls (one per window per doc) + 42 embeddings.
Run It¶
End-to-end on a factual query.
q = 'What is the Meissner effect, and why does it distinguish a superconductor from a perfect conductor?'
ans, ctxs = answer_question(q)
print('=== Proposition answer ===')
print(ans)
=== Proposition answer === The provided atomic facts do not contain information about the Meissner effect or how it distinguishes a superconductor from a perfect conductor. The facts provided are about the BCS theory, superconductivity, and Cooper pairs, but they do not address the Meissner effect specifically. However, based on general knowledge outside of the provided facts, the Meissner effect is the expulsion of a magnetic field from a superconductor during its transition to the superconducting state, which is a key characteristic that distinguishes superconductors from perfect conductors. Unlike perfect conductors, which can retain magnetic fields, superconductors exhibit the Meissner effect, making them unique in their ability to completely expel magnetic fields when they become superconducting. This effect is a fundamental aspect of superconductivity and is not explained by the provided atomic facts.
Side by Side: Vanilla Baseline vs This Technique¶
Vanilla baseline vs proposition chunking on a factual query. Vanilla retrieves prose chunks; propositions retrieve resolved facts.
from cookbook.baselines import vanilla_pipeline
q = 'What is the Meissner effect, and why does it distinguish a superconductor from a perfect conductor?'
base = vanilla_pipeline(q, corpus='wikipedia-superconductors', top_k=5)
ours_a, ours_c = answer_question(q)
import pandas as pd
pd.DataFrame([
{'pipeline': 'vanilla (chunks)', 'top_unit': base.contexts[0][:120]},
{'pipeline': 'propositions', 'top_unit': ours_c[0][:120]},
])
| pipeline | top_unit | |
|---|---|---|
| 0 | vanilla (chunks) | # Meissner effect _Source: Wikipedia, CC BY-SA... |
| 1 | propositions | The BCS theory explains many electromagnetic p... |
Knobs to Turn¶
Five knobs:
- Window size for extraction. Default 600 tokens. Smaller windows produce more propositions per document and may miss cross-paragraph context. Larger windows are cheaper but produce coarser propositions that mix multiple claims.
- Extraction prompt. The default prompt asks for atomic and self-contained claims. Strengthen the self-containment requirement ("every entity named in full, no pronouns") and quality improves visibly.
- Extractor model. Smaller models often extract worse propositions. A Llama-3.3-70B or GPT-4o is typically the right tier; smaller models miss entities or under-decompose.
- Retrieval
k. Bump to 8–12 since each unit is smaller. The prompt is still small even at k=10 because propositions are one sentence each. - Verification pass. For factual workloads, run a separate LLM call per proposition asking "is this claim supported by the source?" before indexing. Drops invented propositions cheaply.
Evaluate on a Slice¶
Run the recipe's answer_question over a small slice of the hand-curated eval set. Full RAGAS metrics are exercised in recipes/09-evaluation-and-production/ragas-triad-eval.ipynb; here we just print a quick spot-check table so you can eyeball whether the technique is on track.
from cookbook.corpora import load_eval_questions
from cookbook.eval import EvalSample
qs = load_eval_questions()
qs = [q for q in qs if q['corpus'] == 'wikipedia-superconductors']
samples = []
for row in qs[:5]:
answer, contexts = answer_question(row['question'])
samples.append({
'question': row['question'],
'expected': row['answer'],
'actual': answer[:200],
'contexts_retrieved': len(list(contexts)),
})
import pandas as pd
pd.DataFrame(samples)
| question | expected | actual | contexts_retrieved | |
|---|---|---|---|---|
| 0 | Who first observed superconductivity, and in w... | Heike Kamerlingh Onnes observed it in mercury ... | The provided atomic facts do not mention who f... | 8 |
| 1 | What is the Meissner effect? | The complete expulsion of magnetic flux from a... | The provided atomic facts do not mention the M... | 8 |
| 2 | Distinguish Type-I from Type-II superconductors. | Type-I has a single critical field above which... | The provided atomic facts do not contain infor... | 8 |
| 3 | What does BCS theory explain? | It explains conventional superconductivity thr... | BCS theory explains many thermodynamic and ele... | 8 |
| 4 | What is a Cooper pair? | Two electrons bound together by phonon exchang... | A Cooper pair is a pair of electrons bound tog... | 8 |
Closing Thoughts¶
Three failure modes:
- Hallucination during extraction. A model that over-summarises will invent facts. Always pair propositions with a faithfulness check (Recipe 37 or 40).
- Numerical drift. Propositions about quantities (years, currencies, measurements) sometimes lose precision. Hand-spot-check 50 propositions before going to production.
- Index explosion. A 1M-chunk corpus becomes 5–10M propositions. Storage and embedding cost scale linearly with the multiplier. Plan capacity before deploying.
Compose with semantic boundary splitting (Recipe 5) — semantic chunks first to find coherent topical regions, then propositions within each. Compose with reranking (Recipe 22) — the sharper retrieval signals reward reranker stages.