Global search (default)
All steps
Global question
Build the index
Parts of this pattern
- Corpus Input / output
- The whole corpus, such as 1,000 podcast transcripts, split into chunks at index time.
- Extractor LLM call
- Reads every chunk and extracts entities and the relationships between them, with short descriptions.
- Question Input / output
- A whole-corpus question, such as 'What are the main themes about tech regulation?'.
- Entity graph Memory
- The merged entities and relationships: one node per entity, one weighted edge per relationship.
- Clusterer Tool
- A community-detection algorithm (Leiden) that groups closely linked entities into communities, at several levels of detail.
- Summarizer LLM call
- Writes a report for each community: what ties its entities together and its key findings.
- Community reports Memory
- The pre-written community reports, the units the query-time map step reads instead of raw chunks.
- Map LLM call
- Runs in parallel over batches of reports, each call returning partial answer points with helpfulness scores.
- Reduce Aggregator
- Drops unhelpful points, sorts the rest by score and writes one answer from the best of them.
- Answer Input / output
- A corpus-wide answer listing the main themes, each traced to the communities it came from.
- Corpus → Extractor
- Each chunk of the corpus goes to the extractor.
Ep. 212, 14:05: '...the FTC's case against the merger leaned on the EU's Digital Markets Act...'
- Extractor → Entity graph
- Entities and relationships are merged into the graph.
{"entities": ["FTC", "Digital Markets Act"], "relationships": [{"source": "FTC", "target": "Digital Markets Act", "description": "cited as precedent"}]}
- Entity graph → Clusterer
- The whole graph goes to the clusterer once extraction is done.
4,812 entities, 11,309 weighted relationships
- Clusterer → Summarizercommunities
- Each community's entities and relationships go to the summarizer.
Community 14: FTC, DOJ, Lina Khan, merger review, Digital Markets Act (23 relationships)
- Summarizer → Community reports
- Each community report is stored for query time.
Community 14, 'Antitrust enforcement': US regulators and EU rules on platform mergers. Findings: 1. The FTC cites the DMA as precedent...
- Question → Map
- A global question goes to the map step, which asks it of every batch of community reports, never of raw chunks.
Across these podcasts, what are the main themes about tech regulation?
- Community reports → Mapreport batches
- Shuffled batches of reports, each sized to fit one context window, go to parallel map calls.
Batch 3 of 12: reports 14, 31, 7, 52 (about 8,000 tokens)
- Map → Reducescored points
- Each map call returns partial answer points, each with a 0 to 100 helpfulness score.
{"points": [{"description": "Antitrust: regulators borrowing EU rules for US merger review", "score": 85}]}
- Reduce → Answer
- The reducer's final answer, built from the highest-scored points.
Three themes recur: antitrust enforcement against platform mergers (communities 14, 22), AI safety rules (31, 7) and child online safety (52).
Local search
For a question about a specific entity, match it in the graph, gather its neighbours, relationships, community reports and source chunks, and answer from that context.
All steps
Parts of this pattern
- Question Input / output
- A question about specific entities, such as 'What has the FTC said about the Digital Markets Act?'.
- Entity match Tool
- Embeds the question and finds the entities whose descriptions are nearest to it.
- Entity graph Memory
- The prebuilt graph: entities, relationships and the communities they belong to.
- Source chunks Memory
- The original text chunks, each linked to the entities extracted from it.
- Context builder Aggregator
- Ranks the neighbours, relationships, reports and chunks around the matched entities and fills a fixed context budget.
- Answerer LLM call
- Answers from the assembled context, citing entities and chunks.
- Answer Input / output
- An answer grounded in one neighbourhood of the graph.
- Question → Entity match
- The question is embedded and matched against entity descriptions.
What has the FTC said about the Digital Markets Act?
- Entity match → Entity graph
- The matched entities become entry points into the graph.
FTC (0.91), Digital Markets Act (0.88), Lina Khan (0.74)
- Entity graph → Context builder
- Neighbouring entities, relationships and community reports around the entry points.
FTC -cited as precedent-> Digital Markets Act; FTC -led by-> Lina Khan; report: community 14, 'Antitrust enforcement'
- Entity match → Source chunks
- The matched entities also look up the source chunks they were extracted from.
FTC -> chunks ep212-14, ep188-03, ep301-22
- Source chunks → Context builder
- The linked source chunks, for verbatim detail.
Ep. 212, 14:05: '...the FTC's case against the merger leaned on the EU's Digital Markets Act...'
- Context builder → Answerer
- One context window, filled by rank within each item type's share of the budget.
12 entities, 18 relationships, 2 community reports, 6 chunks (about 12,000 tokens)
- Answerer → Answer
- The answer, citing the entities and chunks it used.
The FTC has cited the DMA as precedent for reviewing platform mergers [ep212-14], though it has no US equivalent [community 14].
← → neighboursesc atlas
GraphRAG
Also known as Graph RAG · Knowledge-graph RAG · Community-summary RAG
Index a corpus as an LLM-built entity graph with pre-written community summaries, then map-reduce over those summaries to answer whole-corpus questions.
Introduced by Edge et al. (2024) · Microsoft Research, Microsoft Strategic Missions and Technologies and others
The paper evaluates on podcast transcripts and news articles, with global sensemaking questions that plain chunk retrieval cannot answer.
Measured over one run
Global search
- Nodes
- 10. Boxes in the diagram: models, tools, stores, people and plain code.
- LLM calls
- 1. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
- Tool calls
- 0. Messages sent to a tool node in the first scenario.
- Steps
- 3. Steps in the first scenario, with repeated steps counted every time they run.
- Scenarios
- 2. Distinct example runs you can switch between on the diagram.
- Loop
- no. Whether the flow cycles back on itself until a condition is met.
- Parallel
- no. Whether two or more messages are in flight at the same time.
- Branch
- no. Whether the flow takes one path out of several, chosen at run time.
- Human in the loop
- no. Whether a person appears as a node, to approve, correct or answer.
- Autonomy
- low. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
- Cost
- high. Relative token spend per request.
- Latency
- high. Relative wall-clock time per request.
Local search
- Nodes
- 7. Boxes in the diagram: models, tools, stores, people and plain code.
- LLM calls
- 1. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
- Tool calls
- 1. Messages sent to a tool node in the first scenario.
- Steps
- 3. Steps in the first scenario, with repeated steps counted every time they run.
- Scenarios
- 1. Distinct example runs you can switch between on the diagram.
- Loop
- no. Whether the flow cycles back on itself until a condition is met.
- Parallel
- yes. Whether two or more messages are in flight at the same time.
- Branch
- no. Whether the flow takes one path out of several, chosen at run time.
- Human in the loop
- no. Whether a person appears as a node, to approve, correct or answer.
- Autonomy
- low. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
- Cost
- high. Relative token spend per request.
- Latency
- high. Relative wall-clock time per request.
Counted from the first scenario's timeline when the site is built.
Problem
Some questions are about the whole corpus, not any part of it. Ask “across 1,000 podcast transcripts, what are the main themes about tech regulation?” and chunk retrieval returns the ten chunks most similar to the question, which are ten passages that happen to use the words “tech regulation”. The answer covers whatever those ten mention and misses every theme that never used the phrase. The question needs a summary of everything, and no top-k can hold everything.
How it works
GraphRAG does most of its work before any question arrives.
At index time, an extractor model reads every chunk of the corpus and pulls out entities and the relationships between them: the FTC, the Digital Markets Act, and the fact that one cited the other as precedent. These merge into an entity graph, and a clusterer running a community-detection algorithm (Leiden) splits it into communities of closely linked entities, at several levels of detail. A summarizer writes a report for each community, so “Antitrust enforcement” gets a page saying what ties the FTC, the DOJ and merger review together. The community reports are stored.
At query time, a global question goes to the reports, not to the raw chunks. They are shuffled into batches, and the map step asks the question of each batch in parallel; every call returns partial-answer points, each scored for helpfulness. The reducer drops the zero-scored points, keeps the best, and writes one answer. Because every community was summarized, every theme had a chance to be seen.
The Local search tab shows the other query mode, for questions about specific things (“what has the FTC said about the DMA?”). It matches the entities the question names and answers from their neighbourhood in the graph: related entities, relationships, community reports and the original chunks.
When to use
- People ask “sensemaking” questions about a whole corpus: main themes, recurring arguments, who is connected to whom.
- The corpus is fairly stable, so the indexing cost is paid rarely.
- Answers need to span many documents that never mention each other directly.
When to avoid
- Questions are pinpoint lookups. Plain retrieval, or retrieve-and-rerank, is far cheaper and just as good.
- The corpus changes constantly; re-extracting and re-summarizing is expensive.
- The indexing budget is small. Every chunk costs an extraction call, and every community a summary call.
Trade-offs
GraphRAG moves cost from query time to index time, and the index cost is large: model calls over the whole corpus, before the first question. A global question is also expensive, with one map call per batch of reports. In return, it can answer questions that no amount of chunk retrieval can, and the community hierarchy lets you trade detail for cost by choosing which level to map over.
Failure modes
- Entity sprawl: the same entity is extracted under several names (“FTC”, “Federal Trade Commission”) and the graph fragments. Ask for canonical names and merge aliases.
- Stale index: new documents are not in the graph, so global answers silently ignore them. Re-index on a schedule and show the index date.
- Generic answers: summaries of summaries lose the specifics. Keep chunk links so claims can be traced, and use local search for detail.
- Map noise: irrelevant batches still return low-value points that crowd the reduce. Drop zero-scored points and cap the reduce budget.
Build it with your AI
Global search
Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.
Implement the GraphRAG pattern in this codebase, using the LLM client and language we already use.
## Goal
Answer whole-corpus questions, such as 'what are the main themes?', by building an entity graph of the corpus offline, writing a summary of each community in it, and map-reducing over those summaries at query time.
## How it works
1. At index time, split the documents into chunks and call the extractor model with the Entity extraction prompt on each chunk, collecting entities and relationships with short descriptions.
2. Merge duplicate entities across chunks and build a graph: entities as nodes, relationships as weighted edges.
3. Cluster the graph into communities with a community-detection algorithm such as Leiden, keeping the hierarchy of levels.
4. For each community, call the summarizer model with the Community report prompt on its entities and relationships, and store the resulting community report.
5. At query time, shuffle the reports at the chosen level into batches that fit the context window, and call the map model with the Map prompt on each batch in parallel, collecting points with helpfulness scores from 0 to 100.
6. Drop points that scored 0, sort the rest by score, keep as many as fit in one context window, and call the reduce model with the Reduce prompt to write the final answer.
## Prompts
### Entity extraction prompt
```markdown
Extract the entities and relationships in the text below.
Entity types: {{entity_types}}
<text>{{chunk}}</text>
Return JSON:
{"entities": [{"name": "...", "type": "...", "description": "..."}],
"relationships": [{"source": "...", "target": "...", "description": "...", "strength": 1-10}]}
Use the full, canonical name for each entity, so the same entity in
another chunk can be merged with it.
```
### Community report prompt
```markdown
Write a report on the community of related entities below.
<entities>{{entities}}</entities>
<relationships>{{relationships}}</relationships>
Return a title, a one-paragraph summary of what ties these entities
together, and 3 to 6 key findings, each with the entities it rests on.
```
### Map prompt
```markdown
Answer the question as far as the community reports below allow.
<question>{{question}}</question>
<reports>{{report_batch}}</reports>
Return JSON: {"points": [{"description": "...", "score": 0-100}]}
Score each point by how helpful it is for answering the question.
If the reports are irrelevant, return one point with score 0.
```
### Reduce prompt
```markdown
Write a complete answer to the question from the analysts' points below,
which are sorted from most to least helpful.
<question>{{question}}</question>
<points>{{ranked_points}}</points>
Merge overlapping points, keep the most important themes first, and do
not add anything the points do not support.
```
## Stop rule
Stop after one map round and one reduce call. If every map call returns only zero-scored points, say the corpus does not cover the question.
## Requirements
- Persist the graph, communities and reports, and rebuild only the communities whose chunks changed, since full re-indexing is expensive.
- Make the community level, the map batch size, the maximum number of map calls per query (default 50) and the reduce token budget configurable, so query cost stays bounded at fine community levels.
- Run the map calls concurrently with a per-call timeout; a failed, timed-out or unparseable map reply drops out of the reduce instead of failing the request. If an extraction reply is not valid JSON, retry once, then skip that chunk and log it.
- Keep each point's source community IDs through the reduce, so the answer can cite the communities it drew on.
- Add a test with a stub LLM whose map calls return points scored 80, 0 and 40; assert the reduce prompt holds the 80 and 40 points in that order and not the zero-scored one.
Local search
Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.
Implement the GraphRAG pattern (Local search variant) in this codebase, using the LLM client and language we already use.
## Goal
Answer a question about specific entities by matching them in a prebuilt GraphRAG index and answering from the graph neighbourhood, community reports and source chunks around them.
## How it works
1. Embed the question and find the entities whose description embeddings are nearest to it and clear a configurable similarity floor (default top 10, floor 0.5).
2. From the graph, collect each matched entity's neighbours and relationships, the reports of the communities it belongs to, and the text chunks it was extracted from.
3. Rank every candidate item by its link to the matched entities, and fill a fixed context budget in proportions you configure (for example half chunks, a quarter relationships, a quarter community reports).
4. Call the answer model with the Local search answer prompt, passing the question and the assembled context, and return its answer.
## Prompts
### Local search answer prompt
```markdown
Answer the question using the knowledge-graph context below.
<question>{{question}}</question>
<entities>{{entities}}</entities>
<relationships>{{relationships}}</relationships>
<community_reports>{{reports}}</community_reports>
<source_chunks>{{chunks}}</source_chunks>
Prefer the source chunks for specific facts and the reports for the
bigger picture. Cite the entity or chunk ID after each claim.
```
## Stop rule
Stop after one context build and one generation. If no entity clears the similarity floor, say the index has nothing on the question.
## Requirements
- Reuse the global-search index: the same graph, communities, reports and chunk links.
- Make the matched-entity count, the context budget and the per-type proportions configurable.
- Truncate by rank, never mid-item, when the context budget is reached.
- Log the matched entities and every item placed in the context, with its type and source.
- Add a test with a small fixed graph and a stub LLM; assert that a question naming 'FTC' places the FTC entity, its neighbour 'Digital Markets Act' and the chunk it was extracted from in the context, and nothing from an unconnected community.
Prompt templates
Global search
Extract the entities and relationships in the text below.
Entity types: {{entity_types}}
<text>{{chunk}}</text>
Return JSON:{"entities": [{"name": "...", "type": "...", "description": "..."}], "relationships": [{"source": "...", "target": "...", "description": "...", "strength": 1-10}]}Use the full, canonical name for each entity, so the same entity inanother chunk can be merged with it.Write a report on the community of related entities below.
<entities>{{entities}}</entities><relationships>{{relationships}}</relationships>
Return a title, a one-paragraph summary of what ties these entitiestogether, and 3 to 6 key findings, each with the entities it rests on.Answer the question as far as the community reports below allow.
<question>{{question}}</question><reports>{{report_batch}}</reports>
Return JSON: {"points": [{"description": "...", "score": 0-100}]}Score each point by how helpful it is for answering the question.If the reports are irrelevant, return one point with score 0.Write a complete answer to the question from the analysts' points below,which are sorted from most to least helpful.
<question>{{question}}</question><points>{{ranked_points}}</points>
Merge overlapping points, keep the most important themes first, and donot add anything the points do not support.Local search
Answer the question using the knowledge-graph context below.
<question>{{question}}</question><entities>{{entities}}</entities><relationships>{{relationships}}</relationships><community_reports>{{reports}}</community_reports><source_chunks>{{chunks}}</source_chunks>
Prefer the source chunks for specific facts and the reports for thebigger picture. Cite the entity or chunk ID after each claim.Related patterns
Composes well with:
Sources
From the Agentic Atlas by Joran Kikke · Edit on GitHub · Suggest a correction