LightRAG — Dual-Level Graph Retrieval¶
What problem does this solve?¶
GraphRAG (Recipe 31) is powerful but expensive: triple extraction, full graph construction, community detection, and per-community summaries are all paid up-front. For large or incrementally-updated corpora, those costs compound. LightRAG (HKUDS, Oct 2024) keeps the same knowledge-graph idea but rearranges it to be roughly 10x cheaper. LightRAG's trick: build the graph once, but expose two indexed views over it — one over entity descriptions, one over relation descriptions. Queries retrieve from both views. Low-level (entity) retrieval handles factual queries; high-level (relation) retrieval handles synthesis. No community detection, no community summaries, no per-question synthesis call.
Where it came from¶
LightRAG was published by the HKU DS lab in October 2024. The paper showed comparable quality to GraphRAG at roughly 10x lower indexing cost and 5-10x lower query-time cost. The dual-level abstraction was the key innovation: two views over the same graph, retrieved independently, concatenated at query time. The paper also showed strong incremental-update performance — adding new documents touches only the affected entities, not the whole graph. By 2026 LightRAG has become the practical default for graph-RAG deployments where cost matters. The cookbook implementation follows the paper's structure but uses simpler retrieval (cosine over indexed descriptions) instead of the paper's custom dual-cross-attention setup.
Where it fits in the RAG landscape¶
Within the graph-RAG family:
- GraphRAG (Recipe 31). Full community detection + summaries. Best quality on global questions, highest cost.
- LightRAG (this recipe). Dual-level views, no communities. ~10x cheaper, comparable quality.
- HippoRAG (Recipe 33). PageRank over the KG. Best for multi-hop chains.
Pick by cost budget: GraphRAG when quality matters more than cost; LightRAG for most production cases; HippoRAG for multi-hop-heavy workloads.
When to use it (and when not to)¶
Use LightRAG when you want graph-RAG quality without GraphRAG cost. Most production deployments fit here — the dual-level retrieval handles a wide mix of query types competently. Skip it when global synthesis quality matters more than cost. Use GraphRAG for that. Skip it when multi-hop reasoning dominates. Use HippoRAG (Recipe 33) for that. Skip it for purely factoid queries. Vanilla RAG is faster and the graph machinery adds no value.
The intuition¶
Five intuitions to carry:
Two views from one graph. The graph is built once; two text-view indexes (entity descriptions and relation descriptions) are derived from it. Both index the same underlying knowledge in different shapes.
Low-level vs high-level. Low-level retrieval (entity descriptions) catches factual queries — "What is YBCO?". High-level retrieval (relation descriptions) catches synthesis queries — "How are these things connected?".
Both retrievals run per query. Each query embeds and searches against both views. Results are concatenated, not fused — both kinds of context inform the answer simultaneously.
No per-question synthesis call. Unlike GraphRAG's global path, LightRAG doesn't synthesise community summaries on every query. Cost stays low because the expensive work happens at index time, not at query time.
Incremental updates are cheap. Adding new documents only adds new entity and relation views to the indexes; no community detection to redo. This is the structural advantage over GraphRAG.
Architecture¶
flowchart LR D[Documents] --> T[Extract triples] T --> G[(Knowledge Graph)] G --> EV[Entity views
description per node] G --> RV[Relation views
description per edge] EV --> ES[(Entity index)] RV --> RS[(Relation index)] Q[Query] --> R1[Search entity index] Q --> R2[Search relation index] ES --> R1 RS --> R2 R1 --> G2[LLM answer] R2 --> G2
References¶
- 📄 LightRAG — Simple and Fast Retrieval-Augmented Generation — The HKUDS paper.
- 💻 HKUDS/LightRAG official repository — Reference implementation.
- 📄 GraphRAG (Recipe 31) — The full-cost cousin.
- 📄 HippoRAG (Recipe 33) — PageRank-based variant.
- 📚 NetworkX documentation — Our graph library.
- 💻 HKU Data Science Lab blog — More from the LightRAG authors.
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 + chunk + extract triples¶
Same opening as GraphRAG (Recipe 31). The graph construction is shared; the divergence is what we do with it.
from cookbook.corpora import load_wikipedia_superconductors
from cookbook.chunkers import sentence_window
from cookbook.graphs import extract_triples, build_graph
docs = list(load_wikipedia_superconductors())[:14]
chunks = sentence_window(docs, sentences_per_chunk=4)[:80]
triples = extract_triples([(c.chunk_id, c.text) for c in chunks], client.chat)
g = build_graph(triples)
print(f'Graph: {g.number_of_nodes()} nodes, {g.number_of_edges()} edges.')
Graph: 171 nodes, 134 edges.
Step 2 — Build entity-level views¶
For each node, describe it by listing its top neighbours. This is the low-level retrieval surface.
entity_views = {
n: f'Entity: {n}. Connected to: ' + ', '.join(sorted(set(g.successors(n)))[:8])
for n in g.nodes()
}
print(f'Built {len(entity_views)} entity views.')
print()
print('Sample entity views:')
for n, v in list(entity_views.items())[:3]:
print(f' {v}')
Built 171 entity views. Sample entity views: Entity: bcs theory. Connected to: electromagnetic properties of superconductors, thermodynamic properties of superconductors Entity: thermodynamic properties of superconductors. Connected to: Entity: electromagnetic properties of superconductors. Connected to:
Step 3 — Build relation-level views¶
For each edge, describe it as a single sentence "subject predicate object". This is the high-level retrieval surface.
edge_views = []
for u, v, data in g.edges(data=True):
edge_views.append(f'{u} {data.get("predicate", "relates to")} {v}')
print(f'Built {len(edge_views)} edge views.')
print()
print('Sample edge views:')
for ev in edge_views[:6]:
print(f' {ev}')
Built 134 edge views. Sample edge views: bcs theory explains thermodynamic properties of superconductors bcs theory explains electromagnetic properties of superconductors superconductivity is caused by condensation of cooper pairs cooper pairs move through lattice cooper pairs have no resistance bose–einstein condensate is a state of matter
Step 4 — Index both view types¶
Standard Qdrant indexes, one per view.
from cookbook.stores import QdrantBackend
ent_v = client.embed(list(entity_views.values()))
ent_store = QdrantBackend('lr-ent', dim=len(ent_v[0]))
ent_store.add(list(entity_views.values()), ent_v, ids=list(entity_views.keys()))
edge_v = client.embed(edge_views) if edge_views else []
edge_store = QdrantBackend('lr-edge', dim=len(edge_v[0]) if edge_v else 384)
if edge_v:
edge_store.add(edge_views, edge_v, ids=[f'e{i}' for i in range(len(edge_views))])
print('Both stores indexed.')
17:57:45 - LiteLLM:WARNING: common_utils.py:979 - litellm: could not pre-load bedrock-runtime response stream shape — Bedrock event-stream decoding will be unavailable. Error: No module named 'botocore'
17:57:46 - LiteLLM:WARNING: common_utils.py:24 - litellm: could not pre-load sagemaker-runtime response stream shape — SageMaker event-stream decoding will be unavailable. Error: No module named 'botocore'
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
Both stores indexed.
Step 5 — The dual-level retrieve function¶
For each query: hit both indexes, take top-k from each, format as context for the LLM.
def light_rag(question: str, top_k: int = 4) -> tuple[str, list[str]]:
qv = client.embed([question])[0]
low = ent_store.search(qv, top_k=top_k)
high = edge_store.search(qv, top_k=top_k) if edge_views else []
rendered = (
'Entity neighbourhoods:\n' + '\n'.join(h.text for h in low)
+ '\n\nKey relations:\n' + '\n'.join(h.text for h in high)
)
answer = client.chat(rendered + f'\n\nQuestion: {question}\nAnswer:')
contexts = [h.text for h in low] + [h.text for h in high]
return answer, contexts
ans, _ = light_rag('Which materials are connected to high-temperature superconductivity?')
print(ans[:400])
High-temperature superconductivity is connected to superconductivity in materials with a critical temperature above 77 k, and high-tc materials (which are type-ii superconductors) are connected to highest temperature superconductors. Therefore, the materials connected to high-temperature superconductivity are high-tc materials, specifically type-ii superconductors, and cuprate superconductors (as
Step 6 — Wrap as answer_question¶
Standard contract.
def answer_question(question: str) -> tuple[str, list[str]]:
return light_rag(question)
ans, _ = answer_question('How are Cooper pairs related to BCS theory?')
print(ans[:400])
Cooper pairs are a fundamental concept in BCS (Bardeen-Cooper-Schrieffer) theory, which is a theoretical framework that explains the phenomenon of superconductivity. In BCS theory, Cooper pairs are formed when two electrons, typically with opposite spins and momentum, pair up and condense into a single quantum state. This condensation of Cooper pairs is responsible for the superconducting state, w
Look Inside¶
Inspect — when do entity vs relation views win?¶
On factual queries, entity views should dominate. On relational queries, relation views.
for q in [
'What is YBCO?', # factual
'How are Cooper pairs related to BCS theory?', # relational
'When was superconductivity discovered?', # factual
'How does flux pinning enable levitation?', # relational
]:
qv = client.embed([q])[0]
ent_top = ent_store.search(qv, top_k=1)[0].score
edge_top = edge_store.search(qv, top_k=1)[0].score if edge_views else 0.0
label = 'entity' if ent_top > edge_top else 'relation'
print(f' {q[:55]:55s} entity={ent_top:.3f} relation={edge_top:.3f} winner={label}')
What is YBCO? entity=0.760 relation=0.861 winner=relation How are Cooper pairs related to BCS theory? entity=0.764 relation=0.820 winner=relation
When was superconductivity discovered? entity=0.646 relation=0.761 winner=relation
How does flux pinning enable levitation? entity=0.747 relation=0.826 winner=relation
Inspect — top entity views for a synthesis query¶
Look at the entity neighbourhoods that get retrieved. Quality of the neighbourhood description directly determines retrieval quality.
q = 'Which materials connect high-Tc superconductivity to applications in MRI?'
qv = client.embed([q])[0]
for h in ent_store.search(qv, top_k=5):
print(f' {h.score:.3f} {h.text[:120]}')
0.793 Entity: high-tc materials. Connected to: type-ii superconductors 0.726 Entity: highest temperature superconductors. Connected to: 0.696 Entity: type-i superconductors. Connected to: magnetic fields 0.689 Entity: superconductivity in materials with a critical temperature above 77 k. Connected to: 0.684 Entity: high-temperature superconductivity. Connected to: above 77 k, superconductivity in materials with a critical tem
Inspect — cost vs GraphRAG¶
LightRAG skips community detection and per-community summaries. We confirm by counting LLM calls.
print(f'LightRAG indexing LLM calls: ~{len(chunks)} (triple extraction only)')
print(f'LightRAG query-time LLM calls: 1 (just the answer)')
print()
print('GraphRAG (Recipe 31) by comparison:')
print(f' Indexing: ~{len(chunks)} triple-extraction + ~6 community-summary calls')
print(f' Query-time: 1 (similar)')
print()
print('Indexing savings: ~6 LLM calls (modest at this scale; large at production scale).')
LightRAG indexing LLM calls: ~25 (triple extraction only) LightRAG query-time LLM calls: 1 (just the answer) GraphRAG (Recipe 31) by comparison: Indexing: ~25 triple-extraction + ~6 community-summary calls Query-time: 1 (similar) Indexing savings: ~6 LLM calls (modest at this scale; large at production scale).
Inspect — incremental updates¶
Adding a new chunk requires re-extracting triples for that chunk and updating entity views. We show the pattern.
new_chunk_text = 'Magnesium diboride (MgB2) is an inexpensive superconductor with Tc around 39 K.'
new_triples = extract_triples([('new-chunk', new_chunk_text)], client.chat)
for t in new_triples:
g.add_node(t.subject)
g.add_node(t.object)
g.add_edge(t.subject, t.object, predicate=t.predicate, source=t.source_id)
print(f'Graph after update: {g.number_of_nodes()} nodes, {g.number_of_edges()} edges.')
print('Incremental update touched only the new chunk; full graph rebuild not required.')
Graph after update: 173 nodes, 136 edges. Incremental update touched only the new chunk; full graph rebuild not required.
Run It¶
End-to-end on a synthesis query.
ans, _ = answer_question('Which experimental phenomena connect Cooper pairs to applications like MRI and quantum computing?')
print('=== LightRAG answer ===')
print(ans)
=== LightRAG answer === The experimental phenomena that connect Cooper pairs to applications like MRI and quantum computing are the unique properties of superconducting materials, such as zero electrical resistance and the Meissner effect. In particular, the connection to applications like MRI (Magnetic Resonance Imaging) is through the use of superconducting magnets, which are made possible by the condensation of Cooper pairs. These magnets can produce extremely strong magnetic fields, which are essential for MRI machines to generate high-resolution images of the body. The connection to quantum computing is through the use of superconducting qubits, which rely on the properties of Cooper pairs to store and manipulate quantum information. The condensation of Cooper pairs enables the creation of quantum circuits that can process quantum information with low error rates, making them suitable for quantum computing applications. Overall, the connection between Cooper pairs and these applications is through the phenomenon of superconductivity, which enables the creation of materials and devices with unique properties that are essential for these technologies.
Side by Side: Vanilla Baseline vs This Technique¶
Vanilla vs LightRAG on a synthesis query.
from cookbook.baselines import vanilla_pipeline
q = 'Which experimental phenomena connect Cooper pairs to applications in MRI?'
base = vanilla_pipeline(q, corpus='wikipedia-superconductors', top_k=5)
ours_a, _ = answer_question(q)
import pandas as pd
pd.DataFrame([
{'pipeline': 'vanilla', 'preview': base.answer[:160]},
{'pipeline': 'lightrag', 'preview': ours_a[:160]},
])
| pipeline | preview | |
|---|---|---|
| 0 | vanilla | The passages do not contain a direct answer to... |
| 1 | lightrag | To connect Cooper pairs to applications in MRI... |
Knobs to Turn¶
Six knobs in priority order:
- Entity view template. "Entity: X. Connected to: Y, Z" is the cookbook default. Richer templates (top-k neighbours by degree) improve retrieval.
- Edge view template. "subject predicate object" is minimal. Adding source-chunk context can help retrieval quality on long edges.
- Top-k per view. Cookbook uses 4 each. Higher catches more context, longer prompts.
- Triple-extraction model. Same lever as GraphRAG — quality of triples sets the ceiling for everything.
- Embedder. Same lever as everywhere; LightRAG benefits from a strong embedder because retrieval is the only quality signal.
- Incremental update cadence. Run extraction on new documents on a schedule. The graph can incrementally absorb new triples without rebuild.
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 information does not mention who ... | 8 |
| 1 | What is the Meissner effect? | The complete expulsion of magnetic flux from a... | The Meissner effect is a phenomenon where a su... | 8 |
| 2 | Distinguish Type-I from Type-II superconductors. | Type-I has a single critical field above which... | Type-I and Type-II superconductors can be dist... | 8 |
| 3 | What does BCS theory explain? | It explains conventional superconductivity thr... | BCS theory explains the thermodynamic properti... | 8 |
| 4 | What is a Cooper pair? | Two electrons bound together by phonon exchang... | A Cooper pair is a pair of electrons that are ... | 8 |
Closing Thoughts¶
Three failure modes:
- Sparse graphs. A graph with few edges produces few relation views, which means high-level retrieval gives up. Build a richer extraction prompt.
- Vague entity descriptions. "Entity: X. Connected to: Y" is sometimes too thin. Enrich.
- No-graph fallback. When the graph is empty or wrong, LightRAG silently degrades to entity-only search. Always test on a labelled slice.
Compose with semantic chunking (Recipe 5) and reranking (Recipe 22). For multi-hop questions, route to HippoRAG (Recipe 33) instead.