GraphRAG tables¶
Workflow
At a glance
The infomap.tl.graphrag adapter reads the entity and relationship Parquet
tables produced by a GraphRAG pipeline, runs Infomap on the resulting weighted
graph, and returns GraphRAG-style community tables ready to drop into a
retrieval pipeline.
Install the GraphRAG support with pip install "infomap[graphrag]".
Communities as retrieval units¶
GraphRAG pipelines turn a document corpus into a knowledge graph: an entities table of named concepts and a relationships table of weighted co-occurrences. The communities detected over this graph become the unit of retrieval: an LLM summarises each community, and those summaries are indexed for question-answering.
The default community detector in most GraphRAG implementations is Leiden, run
with a modularity objective. Infomap optimises a different quality function: it
finds the partition that minimises the description length of a random walk over
the weighted graph (see The map equation). Whether that flow
view groups your entities more usefully than modularity depends on the graph;
running both and comparing is reasonable. The infomap.tl.graphrag adapter maps
the columns, translates node ids, extracts the hierarchy, and writes Parquet, so
an Infomap partition drops into GraphRAG’s table schema and the downstream
summarisation and retrieval steps run unchanged.
What Infomap optimises here¶
Infomap minimises the map equation over partitions of the entity graph (see The map equation). Two things are specific to GraphRAG input. Infomap uses the relationship weights directly as flow volumes, so a heavy co-occurrence link between two entities makes them harder to separate. And the typical GraphRAG graph is undirected and symmetric, so no directed-flow or teleportation assumptions are needed; Infomap runs in undirected mode by default.
From entity tables to communities¶
Build a synthetic GraphRAG dataset¶
The infomap.tl.graphrag adapter expects two Parquet tables (or two DataFrames)
with specific column names:
Table |
Required columns |
Notes |
|---|---|---|
|
|
|
|
|
|
Here you build a minimal example: two tight triangles (Alpha–Beta–Gamma and Delta–Epsilon–Zeta) linked by one weak bridge edge. The two communities are obvious by design, so you can verify the result at a glance.
import pandas as pd
entities = pd.DataFrame({
"id": ["a", "b", "c", "d", "e", "f"],
"title": ["Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta"],
})
relationships = pd.DataFrame({
"id": ["ab", "bc", "ca", "de", "ef", "fd", "cd"],
"source": ["Alpha","Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Gamma"],
"target": ["Beta", "Gamma", "Alpha", "Epsilon","Zeta", "Delta", "Delta"],
"weight": [2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1.0],
})
print(entities.to_string(index=False))
print()
print(relationships.to_string(index=False))
id title
a Alpha
b Beta
c Gamma
d Delta
e Epsilon
f Zeta
id source target weight
ab Alpha Beta 2.0
bc Beta Gamma 2.0
ca Gamma Alpha 2.0
de Delta Epsilon 3.0
ef Epsilon Zeta 3.0
fd Zeta Delta 3.0
cd Gamma Delta 1.0
Write the tables to a temporary directory so run_graphrag_communities can read
them from disk, which mirrors real pipeline usage.
import tempfile
from pathlib import Path
work_dir = Path(tempfile.mkdtemp(prefix="infomap-graphrag-"))
input_dir = work_dir / "input"
input_dir.mkdir()
entities.to_parquet(input_dir / "entities.parquet")
relationships.to_parquet(input_dir / "relationships.parquet")
Inspect the node-id mapping¶
read_graphrag translates entity titles to the integer node ids that Infomap
expects. You can call it directly to preview the mapping before running the full
pipeline, which helps when debugging column-name mismatches.
from infomap.tl.graphrag import read_graphrag
graph = read_graphrag(entities, relationships)
relationships.assign(
source_node=graph.sources,
target_node=graph.targets,
)[["source", "target", "source_node", "target_node", "weight"]]
| source | target | source_node | target_node | weight | |
|---|---|---|---|---|---|
| 0 | Alpha | Beta | 1 | 2 | 2.0 |
| 1 | Beta | Gamma | 2 | 3 | 2.0 |
| 2 | Gamma | Alpha | 3 | 1 | 2.0 |
| 3 | Delta | Epsilon | 4 | 5 | 3.0 |
| 4 | Epsilon | Zeta | 5 | 6 | 3.0 |
| 5 | Zeta | Delta | 6 | 4 | 3.0 |
| 6 | Gamma | Delta | 3 | 4 | 1.0 |
Run Infomap¶
run_graphrag_communities reads the Parquet files from input_dir, builds the
weighted graph, runs Infomap, and returns a GraphRAGRunResult with two tables:
nodes (one row per entity) and communities (one row per detected community at
each hierarchy level).
from infomap.tl.graphrag import run_graphrag_communities
result = run_graphrag_communities(
input_dir=input_dir,
silent=True,
seed=123,
num_trials=5,
)
print(f"Map equation codelength: {result.infomap.codelength:.4f} bits/step")
print(f"Top-level communities: {result.infomap.num_top_modules}")
Map equation codelength: 1.9832 bits/step
Top-level communities: 2
Per-entity community assignments¶
The nodes table maps every entity to its module. The module_path column
encodes the full position in the hierarchy (a list of module ids from the root
to the leaf), and flow is the stationary probability of the random walk
visiting that entity, a natural measure of entity centrality within its
community.
result.nodes[["entity_title", "module_id", "module_path", "level", "flow"]]
| entity_title | module_id | module_path | level | flow | |
|---|---|---|---|---|---|
| 0 | Alpha | 1 | [1] | 1 | 0.12500 |
| 1 | Beta | 1 | [1] | 1 | 0.12500 |
| 2 | Gamma | 1 | [1] | 1 | 0.15625 |
| 3 | Delta | 2 | [2] | 1 | 0.21875 |
| 4 | Epsilon | 2 | [2] | 1 | 0.18750 |
| 5 | Zeta | 2 | [2] | 1 | 0.18750 |
GraphRAG-style community table¶
The communities table matches GraphRAG’s expected schema. Each row is one
community: a unique id, the level in the hierarchy (0 = top), size, the
list of entity_ids the community contains, and the list of relationship_ids
whose both endpoints fall within the community.
result.communities[[
"id", "level", "title", "size",
"entity_ids", "relationship_ids", "parent", "children",
]]
| id | level | title | size | entity_ids | relationship_ids | parent | children | |
|---|---|---|---|---|---|---|---|---|
| 0 | infomap-1 | 0 | Infomap community 1 | 3 | [a, b, c] | [ab, bc, ca] | -1 | [] |
| 1 | infomap-2 | 0 | Infomap community 2 | 3 | [d, e, f] | [de, ef, fd] | -1 | [] |
Infomap separates the two triangles into their own communities, {Alpha, Beta, Gamma} and {Delta, Epsilon, Zeta}. The weak bridge edge between Gamma and Delta carries too little flow to merge the groups.
Visualise the partition¶
Build a NetworkX graph from the relationship table and pass it to
draw_partition with the module assignments keyed by entity title.
import matplotlib.pyplot as plt
from myst_nb import glue
import networkx as nx
from docs_viz import draw_partition
g = nx.Graph()
for _, row in relationships.iterrows():
g.add_edge(row["source"], row["target"], weight=row["weight"])
title_to_module = dict(
zip(result.nodes["entity_title"], result.nodes["module_id"])
)
title_to_flow = dict(
zip(result.nodes["entity_title"], result.nodes["flow"])
)
fig = draw_partition(g, title_to_module, flow=title_to_flow)
glue("fig-graphrag", fig, display=False)
plt.close(fig)
Fig. 14 The GraphRAG entity graph coloured by community. Infomap separates the two tightly linked entity groups; the thin bridge between them carries too little flow to merge them.¶
Write output to disk¶
If you need the Parquet tables on disk (for downstream summarisation or
ingestion into a vector store), pass output_dir to run_graphrag_communities.
The function writes infomap_nodes.parquet, communities.parquet, and an
infomap_run.json summary to the output directory.
output_dir = work_dir / "output"
result_with_output = run_graphrag_communities(
input_dir=input_dir,
output_dir=output_dir,
silent=True,
seed=123,
num_trials=5,
)
list(output_dir.iterdir())
[PosixPath('/tmp/infomap-graphrag-85yeeot4/output/infomap_run.json'),
PosixPath('/tmp/infomap-graphrag-85yeeot4/output/infomap_nodes.parquet'),
PosixPath('/tmp/infomap-graphrag-85yeeot4/output/communities.parquet')]
You can also write the tables separately using write_graphrag_communities if
you have already run Infomap and just want to export:
from infomap.tl.graphrag import write_graphrag_communities
nodes, communities = write_graphrag_communities(
result_with_output.infomap,
graph=result_with_output.graph,
output=output_dir / "communities_alt.parquet",
)
communities[["id", "level", "size", "entity_ids"]]
| id | level | size | entity_ids | |
|---|---|---|---|---|
| 0 | infomap-1 | 0 | 3 | [a, b, c] |
| 1 | infomap-2 | 0 | 3 | [d, e, f] |
Pitfalls¶
The tables need specific columns. Entities need
idandtitle; relationships needsource,target,weight(matching entitytitleby default). Point the adapter elsewhere withentity_title_col/endpoint_col/weight_col.Community ids are labels, not an order.
infomap-1and the like identify groups; the numbering is arbitrary across runs.Omit
output_dirto stay in memory. Pass it only when you want the Parquet tables written to disk.
API pointers¶
infomap.tl.graphrag.read_graphrag()translates entity/relationship DataFrames or Parquet paths into aGraphRAGGraphwith mapped node ids. Key parameters:entity_id_col,entity_title_col,source_col,target_col,weight_col,endpoint_col("title"or"id").infomap.tl.graphrag.run_graphrag_communities()is the one-call pipeline: it reads tables, runs Infomap, and optionally writes outputs. It returns aGraphRAGRunResultwith.infomap,.graph,.nodes, and.communities.infomap.tl.graphrag.write_graphrag_communities()writes a pre-run Infomap result to disk as GraphRAG-compatible Parquet tables.infomap.tl.graphrag.GraphRAGGraphholds the entity/relationship tables, the edge arrays, and the bidirectional entity-id ↔ node-id mappings.infomap.tl.graphrag.GraphRAGRunResultbundles theInfomapobject, theGraphRAGGraph, and the two output DataFrames.infomap.Infomap.codelengthandinfomap.Infomap.num_top_modulesreport the quality and structure of the solution after a run.
Going deeper¶
Companion notebook:
examples/notebooks/run-infomap-on-graphrag-tables.ipynbextends this example with a Leiden comparison and a retrieval-pipeline walkthrough.Building a network covers all the ways to feed data into Infomap.
The map equation is the objective
run_graphrag_communitiesminimises.Edge et al. [2024] introduced the GraphRAG pipeline and its community-hierarchy approach.