Global search (default)

GraphRAG diagramCorpus, Extractor, Question, Entity graph, Clusterer, Summarizer, Community reports, Map, Reduce, Answer. Step captions follow the diagram.CorpusExtractorextract entitiesQuestionEntity graphClustererLeidenSummarizercommunity reportsCommunity reportsMapone call per batchReduceAnswerGraphRAG diagramCorpus, Extractor, Question, Entity graph, Clusterer, Summarizer, Community reports, Map, Reduce, Answer. Step captions follow the diagram.CorpusExtractorextractentitiesQuestionEntitygraphClustererLeidenSummarizercommunityreportsCommunityreportsMapone callper batchReduceAnswer

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).

← → neighboursesc atlas

Knowledge & Memory

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

Entity extraction prompt
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
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
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
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.

Local search

Local search answer prompt
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.

Related patterns

Composes well with:

Sources

  1. From Local to Global: A Graph RAG Approach to Query-Focused Summarization (Edge et al., 2024)
  2. GraphRAG global search (Microsoft GraphRAG documentation)
  3. GraphRAG local search (Microsoft GraphRAG documentation)

From the Agentic Atlas by Joran Kikke · Edit on GitHub · Suggest a correction