# https://github.com/gusye1234/nano-graphrag Project Manual

Generated at: 2026-06-23 23:32:25 UTC

## Table of Contents

- [Project Overview & System Architecture](#page-1)
- [Configuration, Query Modes & Prompt Customization](#page-2)
- [Storage Backends, LLM & Embedding Integrations](#page-3)
- [Benchmarks, Roadmap & Known Limitations](#page-4)

<a id='page-1'></a>

## Project Overview & System Architecture

### Related Pages

Related topics: [Configuration, Query Modes & Prompt Customization](#page-2), [Storage Backends, LLM & Embedding Integrations](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md)
- [nano_graphrag/__init__.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/__init__.py)
- [nano_graphrag/graphrag.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/graphrag.py)
- [nano_graphrag/base.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/base.py)
- [nano_graphrag/_op.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_op.py)
- [nano_graphrag/_llm.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_llm.py)
- [nano_graphrag/_utils.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_utils.py)
- [nano_graphrag/prompt.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/prompt.py)
- [docs/ROADMAP.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/ROADMAP.md)
</details>

# Project Overview & System Architecture

## Purpose and Scope

`nano-graphrag` is a compact, hackable GraphRAG implementation that re-implements the core ideas from Microsoft's [GraphRAG](https://arxiv.org/pdf/2404.16130) paper in roughly 1100 lines of code (excluding tests and prompts), as stated in [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md). The project explicitly targets developers who found the official implementation difficult to read or extend, and it positions itself as a "smaller, faster, cleaner" alternative that preserves the central graph-augmented retrieval behaviour.

The library exposes two primary entry points — `GraphRAG` and `QueryParam` — both defined as Python dataclasses and re-exported from [nano_graphrag/__init__.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/__init__.py). `GraphRAG` orchestrates the indexing pipeline and query answering, while `QueryParam` controls per-query behaviour such as retrieval mode and community budget.

## High-Level Architecture

The system follows a pluggable, storage-agnostic pipeline. The `GraphRAG` class in [nano_graphrag/graphrag.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/graphrag.py) wires together three abstract storage interfaces defined in [nano_graphrag/base.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/base.py):

- `BaseKVStorage` — key/json pairs (default: disk files)
- `BaseVectorStorage` — embedding indices (default: `nano-vectordb`)
- `BaseGraphStorage` — knowledge graph (default: `networkx`)

Each interface has built-in implementations and documented extension points, so users can swap Neo4j, Milvus, HNSWlib, or file-backed storage without modifying the pipeline.

```mermaid
flowchart LR
    A[Text Chunks] --> B[Entity & Relation Extraction<br/>via best_model_func]
    B --> C[Graph Storage<br/>networkx / neo4j]
    B --> D[Vector Storage<br/>nano-vectordb / hnswlib / milvus]
    C --> E[Community Detection<br/>& Report Summarization]
    E --> F[KV Storage<br/>community reports cache]
    Q[User Query] --> G{Query Mode}
    G -->|local| H[Entity lookup → neighborhood]
    G -->|global| I[Top-K community reports]
    G -->|naive| J[Vector similarity over chunks]
    H --> K[cheap_model_func response]
    I --> K
    J --> K
    K --> R[Answer]
```

The diagram mirrors the indexing/query flow described in [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md). During indexing, text chunks produced by [nano_graphrag/_op.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_op.py) are sent through entity extraction, graph and vector writes, and a community-report pass. During querying, the same orchestrator dispatches based on `QueryParam.mode` to local, global, or naive retrieval.

## Two-Model LLM Strategy

A distinctive design choice documented in [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md) and implemented in [nano_graphrag/_llm.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_llm.py) is the use of two LLM roles:

- **`best_model_func`** (default `gpt-4o`) — used for planning tasks that demand quality: entity/relation extraction, JSON-constrained parsing, and final answer generation.
- **`cheap_model_func`** (default `gpt-4o-mini`) — used for bulk summarisation, such as community-report generation.

Both functions share the same signature (`async def my_llm_complete(prompt, system_prompt=None, history_messages=[], **kwargs) -> str`) and may be overridden per `GraphRAG` instance. A `convert_response_to_json_func` hook lets users repair malformed JSON returned by open-source models, addressing a common stability problem noted in [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md) under the "Json Output" section.

## Pluggable Components

The following table summarises the supported components and their sources, as listed in [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md) under the "Components" section. Community issue [#2](https://github.com/gusye1234/nano-graphrag/issues/2) explicitly tracks requests for additional storages (e.g. MongoDB) and LLMs (e.g. Ollama), most of which already ship as examples under `examples/`.

| Type            | Options                                            | Status         |
|-----------------|----------------------------------------------------|----------------|
| LLM             | OpenAI, Azure OpenAI, Amazon Bedrock, DeepSeek, Ollama | Built-in / examples |
| Embedding       | OpenAI, Amazon Bedrock, sentence-transformers      | Built-in / examples |
| Vector DB       | nano-vectordb, hnswlib, milvus-lite, faiss        | Built-in / examples |
| Graph Storage   | networkx, neo4j                                    | Built-in       |
| Chunking        | by token size, by text splitter                    | Built-in       |
| Visualisation   | graphml export                                     | examples       |

Custom chunking functions are supported by passing `chunk_func=chunking_by_seperators` to `GraphRAG`, as shown in the `using_custom_chunking_method.py` example referenced in [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md).

## Query Modes and Prompts

`QueryParam.mode` selects among three retrieval strategies implemented in `graphrag.py`:

- **local** — seed entities are resolved from the query, and the surrounding graph neighborhood is fed to the model. Governed by `local_max_token` and `local_community_single_one`.
- **global** — uses the top-K most important community reports (controlled by `global_max_consider_community`, default 512). As noted in the "Issues" section of [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md), this differs from Microsoft's map-reduce style that fills the context with all communities.
- **naive** — a flat vector similarity search over chunks, enabled via `GraphRAG(enable_naive_rag=True)`.

All prompt templates live in [nano_graphrag/prompt.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/prompt.py) inside the `PROMPTS` dictionary. The most important keys, per [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md), are `entity_extraction`, `community_report`, `local_rag_response`, `global_reduce_rag_response`, and `fail_response`. Community issue [#56](https://github.com/gusye1234/nano-graphrag/issues/56) raised a question about repeated sections inside `local_rag_response`; the prompts are intentionally user-editable, so this can be modified by overriding the dictionary entry.

## Async, Persistence, and Known Limitations

Every synchronous method on `GraphRAG` has an `a`-prefixed async counterpart (e.g. `ainsert`, `aquery`), as described in [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md). Indexing state is persisted under `working_dir`; re-instantiating `GraphRAG` from the same directory reloads the graph, vectors, and community reports without recomputation.

Two functional gaps are explicitly acknowledged in the "Issues" section of [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md):

1. `nano-graphrag` does **not** implement the `covariates` feature of the original GraphRAG.
2. The **global search** uses top-K communities rather than Microsoft's map-reduce across all communities.

Community issue [#99](https://github.com/gusye1234/nano-graphrag/issues/99) also tracks a feature request to add Microsoft's DRIFT search variant, which is not yet present. Installation pain on Windows (encoding errors from `cp1252`) is tracked in issue [#125](https://github.com/gusye1234/nano-graphrag/issues/125); users on Windows may need to set `PYTHONIOENCODING=utf-8` before running `pip install`.

## See Also

- [Quick Start & Usage](quick-start.md)
- [Storage Components](storage-components.md)
- [LLM & Embedding Functions](llm-embedding.md)
- [Query Modes](query-modes.md)
- [FAQ](faq.md)

---

<a id='page-2'></a>

## Configuration, Query Modes & Prompt Customization

### Related Pages

Related topics: [Project Overview & System Architecture](#page-1), [Storage Backends, LLM & Embedding Integrations](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [nano_graphrag/graphrag.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/graphrag.py)
- [nano_graphrag/prompt.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/prompt.py)
- [nano_graphrag/_llm.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_llm.py)
- [nano_graphrag/_utils.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_utils.py)
- [nano_graphrag/base.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/base.py)
- [nano_graphrag/_op.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_op.py)
- [examples/using_custom_chunking_method.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/using_custom_chunking_method.py)
- [examples/using_amazon_bedrock.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/using_amazon_bedrock.py)
- [examples/using_ollama_as_llm.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/using_ollama_as_llm.py)
- [examples/using_local_embedding_model.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/using_local_embedding_model.py)
- [docs/use_neo4j_for_graphrag.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/use_neo4j_for_graphrag.md)
- [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md)
</details>

# Configuration, Query Modes & Prompt Customization

`nano-graphrag` exposes nearly all of its behavior through two Python `@dataclass`es — `GraphRAG` and `QueryParam` — plus a mutable prompt dictionary `nano_graphrag.prompt.PROMPTS`. This page documents how to wire those configuration surfaces together: the constructor parameters that select LLMs, embeddings, and storage backends; the `QueryParam` fields that choose between local, global, and naive retrieval; and the prompt templates that control entity extraction, community summarization, and answer generation.

## Configuration Surface: `GraphRAG` and `QueryParam`

Both `GraphRAG` and `QueryParam` are dataclasses, so every option is type-hinted and discoverable through `help(...)` (see the README "Available Parameters" section). `GraphRAG` is the long-lived object that owns the working directory, storage handles, and the insert/query pipeline; `QueryParam` is a lightweight per-call configuration passed to `query(...)` or `aquery(...)` ([readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md)).

### LLM and embedding slots

`nano-graphrag` requires two LLM tiers by design: a "great" model for planning and response generation, and a "cheap" model for summarization. The defaults are `gpt-4o` and `gpt-4o-mini` respectively, implemented in [nano_graphrag/_llm.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_llm.py). You replace them with `GraphRAG(best_model_func=..., cheap_model_func=...)`, together with `best_model_max_token_size`, `best_model_max_async`, and the analogous `cheap_model_*` knobs. The reference signature that any custom LLM must follow is:

```python
async def my_llm_complete(prompt, system_prompt=None, history_messages=[], **kwargs) -> str:
    hashing_kv: BaseKVStorage = kwargs.pop("hashing_kv", None)  # optional LLM cache
    response = await call_your_LLM(messages, **kwargs)
    return response
```

Cloud and local providers plug into this same slot: Azure OpenAI is enabled with `GraphRAG(..., using_azure_openai=True, ...)` (see [.env.example.azure](https://github.com/gusye1234/nano-graphrag/blob/main/.env.example.azure)); Amazon Bedrock with `using_amazon_bedrock=True` plus `best_model_id` / `cheap_model_id` ([examples/using_amazon_bedrock.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/using_amazon_bedrock.py)); `ollama` and DeepSeek via the examples in [examples/using_ollama_as_llm.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/using_ollama_as_llm.py) and [examples/using_deepseek_as_llm.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/using_deepseek_as_llm.py). Embeddings follow the same pattern through the `EmbeddingFunc` protocol decorated with `wrap_embedding_func_with_attrs(embedding_dim=..., max_token_size=...)` in [nano_graphrag/_utils.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_utils.py).

### Storage and chunking slots

Storage is injected through three abstract base classes defined in [nano_graphrag/base.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/base.py): `BaseKVStorage` (key→JSON), `BaseVectorStorage` (embeddings), and `BaseGraphStorage` (the knowledge graph). Defaults are disk JSON files, `nano-vectordb`, and `networkx`. Substitutes are wired in with `key_string_value_json_storage_cls=`, `vector_db_storage_cls=`, and `graph_storage_cls=`. The README lists hnswlib, milvus-lite, and faiss as vector alternatives, and Neo4j as a graph alternative with a dedicated tutorial at [docs/use_neo4j_for_graphrag.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/use_neo4j_for_graphrag.md).

Chunking is a callable parameter, not a class. The default is token-size chunking; switching to the text-splitter implementation is one constructor argument:

```python
from nano_graphrag._op import chunking_by_seperators
GraphRAG(..., chunk_func=chunking_by_seperators, ...)
```

User-defined chunkers follow the same pattern, demonstrated in [examples/using_custom_chunking_method.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/using_custom_chunking_method.py).

## Query Modes

`QueryParam.mode` selects between three retrieval strategies. The first two — `local` and `global` — are the two GraphRAG query modes described in the original Microsoft paper; `naive` is a vector-only baseline that is only active when `GraphRAG(..., enable_naive_rag=True, ...)` is set at construction time.

```mermaid
flowchart TD
    Q[User query] --> P{QueryParam.mode}
    P -->|local| L[Entity-centric neighborhood search<br/>+ community reports]
    P -->|global| G[Top-K important communities<br/>via global_max_consider_community]
    P -->|naive| N[Vector similarity over chunks<br/>requires enable_naive_rag=True]
    L --> R[best_model_func generates answer]
    G --> R
    N --> R
    R --> Out[Final response<br/>or only_need_context output]
```

Key `QueryParam` fields worth knowing:

- `mode` — `"local"`, `"global"`, or `"naive"`.
- `only_need_context=True` — returns just the assembled context (community reports for local; analyst reports for global) without calling the final answer model. This is the documented integration point for users who want to feed the context into their own prompt ([readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md)).
- `global_max_consider_community` — caps the number of top-importance communities that the global search fills into the prompt; the default is 512. The README explicitly notes that `nano-graphrag`'s global search differs from Microsoft's reference implementation, which uses a map-reduce to fill *all* communities.

A frequently-requested fourth mode, **DRIFT search** (added by Microsoft after local and global), is tracked in community issue #99 and is not yet implemented. For now, `QueryParam.mode` is limited to the three values above.

## Prompt Customization

All prompt templates live in a single mutable dictionary: `nano_graphrag.prompt.PROMPTS` ([nano_graphrag/prompt.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/prompt.py)). Mutating it in place is the supported way to override behavior — the README explicitly invites users to "play with it and replace any prompt inside." The most important keys are:

| Key | Role in the pipeline |
| --- | --- |
| `entity_extraction` | Used to extract entities and relations from each text chunk during indexing. |
| `community_report` | Used to summarize each detected graph cluster. |
| `local_rag_response` | System prompt template for local-search answer generation. |
| `global_reduce_rag_response` | System prompt template for global-search answer generation. |
| `fail_response` | Fallback returned when no community/context is relevant to the query. |

### JSON output and repair hooks

`nano-graphrag` instructs `best_model_func` to emit JSON via OpenAI's `"response_format": {"type": "json_object"}` argument. Open-source models (e.g., `ollama`) often produce unstable JSON, so the library exposes `convert_response_to_json_func` to post-process the raw string into a dict. A common third-party choice is [`json_repair`](https://github.com/mangiucugna/json_repair) ([readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md)).

### A note on prompt repetition

Community issue #56 observed that the `local_rag_response` template repeats its `Goal` and `Target response length and format` sections. This repetition is present in the source and is intentional within the current template, but it is exactly the kind of friction the in-place `PROMPTS` dictionary is designed to fix — users can rewrite the template to a non-repeated form without forking the project.

## Common Customization Patterns

Putting the three configuration surfaces together, the typical customization patterns are:

1. **Swap the LLM and embedding only** — leave storage and chunking at defaults. This is the path used by the DeepSeek, ollama, and Bedrock examples.
2. **Swap storage to a managed service** — keep the OpenAI defaults, but pass `vector_db_storage_cls=` or `graph_storage_cls=Neo4jStorage`. The Neo4j tutorial is the canonical walkthrough.
3. **Turn the library into a context provider** — call `graph_func.query(..., param=QueryParam(mode="local", only_need_context=True))` and pipe the returned CSV-style report into your own downstream prompt.
4. **Run a fully local stack with no API keys** — combine ollama for the LLM, `sentence-transformers` for embeddings ([examples/using_local_embedding_model.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/using_local_embedding_model.py)), and an in-memory vector store, as shown in [examples/no_openai_key_at_all.py](https://github.com/gusye1234/nano-graphrag/blob/main/examples/no_openai_key_at_all.py).

Together, the `GraphRAG` constructor, the `QueryParam` per-call object, and the `PROMPTS` dictionary cover every documented customization surface in `nano-graphrag`.

## See Also

- [README](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md) — installation, quick start, and the full component compatibility table.
- [docs/use_neo4j_for_graphrag.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/use_neo4j_for_graphrag.md) — graph storage substitution walkthrough.
- [docs/FAQ.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/FAQ.md) — frequently asked questions.
- [docs/ROADMAP.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/ROADMAP.md) — planned features, including community requests such as DRIFT search (issue #99) and additional storage/LLM providers (issue #2).

---

<a id='page-3'></a>

## Storage Backends, LLM & Embedding Integrations

### Related Pages

Related topics: [Project Overview & System Architecture](#page-1), [Configuration, Query Modes & Prompt Customization](#page-2), [Benchmarks, Roadmap & Known Limitations](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [nano_graphrag/base.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/base.py)
- [nano_graphrag/_storage/__init__.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_storage/__init__.py)
- [nano_graphrag/_storage/kv_json.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_storage/kv_json.py)
- [nano_graphrag/_storage/vdb_nanovectordb.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_storage/vdb_nanovectordb.py)
- [nano_graphrag/_storage/vdb_hnswlib.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_storage/vdb_hnswlib.py)
- [nano_graphrag/_storage/gdb_networkx.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_storage/gdb_networkx.py)
- [nano_graphrag/_llm.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_llm.py)
- [nano_graphrag/_utils.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_utils.py)
- [nano_graphrag/__init__.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/__init__.py)
- [README.md](https://github.com/gusye1234/nano-graphrag/blob/main/README.md)
</details>

# Storage Backends, LLM & Embedding Integrations

## Purpose and Scope

`nano-graphrag` is designed as a small, hackable GraphRAG implementation whose core value proposition is **portability**: every external dependency (LLM provider, embedding model, vector index, graph store, KV cache) is hidden behind a base class so it can be swapped at construction time without touching pipeline code. This page documents the extension points for those three categories of integrations and the defaults shipped with the library.

The high-level abstraction lives in `nano_graphrag/base.py`, which defines abstract `BaseKVStorage`, `BaseVectorStorage`, and `BaseGraphStorage` types; the `_storage/__init__.py` module wires the default concrete implementations into the `GraphRAG` dataclass declared in `nano_graphrag/__init__.py`. Source: [nano_graphrag/base.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/base.py).

```mermaid
flowchart LR
    A[GraphRAG dataclass] -->|best_model_func| L[(LLM Provider)]
    A -->|cheap_model_func| L
    A -->|embedding_func| E[(Embedding Model)]
    A -->|key_string_value_json_storage_cls| KV[(KV Storage)]
    A -->|vector_db_storage_cls| VDB[(Vector DB)]
    A -->|graph_storage_cls| GDB[(Graph DB)]
    L -.async .-> A
    E -.async .-> A
```

## Storage Backends

### KV Storage (`BaseKVStorage`)

The default implementation persists JSON values to disk under `working_dir` and is implemented in `nano_graphrag/_storage/kv_json.py` (`JsonKVStorage`). It is used internally for LLM response caching, chunk deduplication, full-document storage, and community reports. The base interface declares async `get_by_id`, `get_by_ids`, `filter_keys`, `upsert`, `drop`, and `is_empty` methods that any backend must implement. Source: [nano_graphrag/_storage/kv_json.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_storage/kv_json.py), [nano_graphrag/base.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/base.py).

To swap in an alternative backend (for example MongoDB or Redis), pass it via `GraphRAG(..., key_string_value_json_storage_cls=YOURS, ...)`. If every storage is replaced with a non-file backend, set `always_create_working_dir=False` to skip the directory-creation step.

### Vector Database Storage (`BaseVectorStorage`)

Two built-in implementations ship with the library and both implement the same interface from `nano_graphrag/base.py`:

| Backend | File | Notes |
|---|---|---|
| `nano-vectordb` (default) | `nano_graphrag/_storage/vdb_nanovectordb.py` | Pure-Python, in-memory + on-disk persistence under `working_dir` |
| `hnswlib` | `nano_graphrag/_storage/vdb_hnswlib.py` | Built-in C++ ANN index, recommended for larger corpora |

Additional examples in the repository demonstrate `milvus-lite` and `faiss`. Any subclass of `BaseVectorStorage` implementing `upsert`, `query`, `delete_entity`, and `is_empty` can be injected through `GraphRAG(..., vector_db_storage_cls=YOURS, ...)`. Sources: [nano_graphrag/_storage/vdb_nanovectordb.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_storage/vdb_nanovectordb.py), [nano_graphrag/_storage/vdb_hnswlib.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_storage/vdb_hnswlib.py).

### Graph Database Storage (`BaseGraphStorage`)

The default graph backend is `NetworkXStorage` in `nano_graphrag/_storage/gdb_networkx.py`, which exposes the abstract API: `has_node`, `has_edge`, `get_node`, `upsert_node`, `upsert_edge`, `get_all_edges`, `get_neighbors`, `get_edge`, `delete_node`, `remove_nodes`, `remove_edges`, `get_nodes_by_chunk_ids`, and community-detection helpers (`clustering`, `community_schema`). A `Neo4jStorage` implementation is also shipped and documented in `docs/use_neo4j_for_graphrag.md`. Source: [nano_graphrag/_storage/gdb_networkx.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_storage/gdb_networkx.py).

## LLM Integrations

`nano-graphrag` distinguishes two LLM roles passed to `GraphRAG`:

- **`best_model_func`** — used for entity extraction, community summarization planning, and final response generation.
- **`cheap_model_func`** — used for cheap summarization and intermediate rewriting.

Built-in providers live in `nano_graphrag/_llm.py` and include `gpt_4o_complete`, `gpt_4o_mini_complete`, Azure OpenAI (gated behind `using_azure_openai=True`), and Amazon Bedrock (gated behind `using_amazon_bedrock=True` plus `best_model_id` / `cheap_model_id`). By default the great model is `gpt-4o` and the cheap model is `gpt-4o-mini`.

The async signature that all LLM functions must satisfy is:

```python
async def my_llm_complete(
    prompt: str,
    system_prompt: str | None = None,
    history_messages: list = [],
    **kwargs,
) -> str:
    hashing_kv: BaseKVStorage = kwargs.pop("hashing_kv", None)  # for caching
    ...
```

Inject the function via `GraphRAG(best_model_func=..., best_model_max_token_size=..., best_model_max_async=...)` and similarly for the cheap model. Because the LLM call passes through the `hashing_kv` storage, swapping the KV backend also swaps the response cache. Sources: [nano_graphrag/_llm.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_llm.py), [README.md](https://github.com/gusye1234/nano-graphrag/blob/main/README.md).

For LLM providers that produce unstable JSON when using `response_format={"type": "json_object"}` (a common pain point raised in community discussion around open-source models), `GraphRAG` accepts `convert_response_to_json_func=YOUR_STRING_TO_JSON_FUNC` so callers can repair the output (e.g., via [`json_repair`](https://github.com/mangiucugna/json_repair)).

## Embedding Function Integration

Embeddings are an `EmbeddingFunc` instance decorated with `@wrap_embedding_func_with_attrs(embedding_dim=..., max_token_size=...)` from `nano_graphrag/_utils.py`. The decorated function must be async and accept a `list[str]`, returning a `numpy.ndarray` of shape `(len(texts), embedding_dim)`. The default uses OpenAI's `text-embedding-3-small` (1536 dimensions, 8192 token ceiling). Source: [nano_graphrag/_utils.py](https://github.com/gusye1234/nano-graphrag/blob/main/nano_graphrag/_utils.py).

Replacement is performed via `GraphRAG(embedding_func=your_embed_func, embedding_batch_num=..., embedding_func_max_async=...)`. The `examples/using_local_embedding_model.py` script demonstrates `sentence-transformers` as a fully offline backend. Because `embedding_dim` is captured by the decorator, changing the model automatically re-tunes the vector storage.

## Community Notes and Customization

The repository's most-discussed feature request (issue #2, "Add more Storages and LLMs") explicitly tracks community contributions for `MongoDB`, `ollama`, and other backends; the storage/embedding/LLM sections above map directly to the three extension points that contributors need to subclass. The README reiterates that any backend implementation must conform to the base interfaces in `nano_graphrag/base.py`, and the project maintains a benchmark suite under `examples/benchmarks` for comparing components.

A known operational caveat from the Windows installation issue (#125) is the platform encoding: `nano-graphrag` reads and writes JSON files using UTF-8 by default, but Windows terminals default to `cp1252`. Setting `PYTHONUTF8=1` (or running from a UTF-8 locale) before launching resolves the `UnicodeDecodeError` reported during installation and first run.

For visualization of the persisted graph, `nano-graphrag` can export the `NetworkXStorage` contents to GraphML; the `graphml_visualize.py` example was patched in v0.0.8 to handle long entity names that previously truncated the output.

## See Also

- [GraphRAG Concepts & Architecture (Upstream Paper)](https://arxiv.org/pdf/2404.16130)
- [Project README and Component Matrix](https://github.com/gusye1234/nano-graphrag/blob/main/README.md)
- [FAQ](./docs/FAQ.md)
- [Roadmap](./docs/ROADMAP.md)
- [Contributing Guide](./docs/CONTRIBUTING.md)
- [Neo4j Graph Storage Tutorial](./docs/use_neo4j_for_graphrag.md)

---

<a id='page-4'></a>

## Benchmarks, Roadmap & Known Limitations

### Related Pages

Related topics: [Project Overview & System Architecture](#page-1), [Configuration, Query Modes & Prompt Customization](#page-2)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [readme.md](https://github.com/gusye1234/nano-graphrag/blob/main/readme.md)
- [docs/benchmark-en.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/benchmark-en.md)
- [docs/benchmark-zh.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/benchmark-zh.md)
- [docs/benchmark-dspy-entity-extraction.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/benchmark-dspy-entity-extraction.md)
- [docs/ROADMAP.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/ROADMAP.md)
- [docs/FAQ.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/FAQ.md)
- [docs/CONTRIBUTING.md](https://github.com/gusye1234/nano-graphrag/blob/main/docs/CONTRIBUTING.md)
- [examples/benchmarks/eval_naive_graphrag_on_multi_hop.ipynb](https://github.com/gusye1234/nano-graphrag/blob/main/examples/benchmarks/eval_naive_graphrag_on_multi_hop.ipynb)
- [.env.example.azure](https://github.com/gusye1234/nano-graphrag/blob/main/.env.example.azure)
</details>

# Benchmarks, Roadmap & Known Limitations

## 1. Overview

`nano-graphrag` positions itself as a "simple, easy-to-hack GraphRAG implementation" — a smaller, faster, and cleaner alternative to Microsoft's official [GraphRAG](https://github.com/microsoft/graphrag/tree/main). The project is intentionally minimal: excluding tests and prompts, the entire library is about **1,100 lines of code** ([readme.md](readme.md)). The repository publishes benchmarks, a roadmap, and a transparent list of known limitations so users can evaluate fit-for-purpose before adopting it.

This page consolidates the publicly available benchmark results, planned enhancements, known constraints, and notable community-reported issues.

## 2. Benchmarks

The project publishes comparative benchmarks against the original GraphRAG implementation, plus a community-driven multi-hop evaluation.

### 2.1 English & Chinese Benchmarks

Two separate benchmark documents are maintained:

- [docs/benchmark-en.md](docs/benchmark-en.md) — English-language benchmark
- [docs/benchmark-zh.md](docs/benchmark-zh.md) — Chinese-language benchmark

These document comparative performance and quality metrics between `nano-graphrag` and the reference GraphRAG implementation, allowing users to verify that the simplified codebase preserves core functionality. Source: [readme.md](readme.md) section "## Benchmark".

### 2.2 Multi-Hop RAG Evaluation

A Jupyter notebook [examples/benchmarks/eval_naive_graphrag_on_multi_hop.ipynb](examples/benchmarks/eval_naive_graphrag_on_multi_hop.ipynb) evaluates the naive RAG mode against the [MultiHop-RAG](https://github.com/yixuantt/MultiHop-RAG) dataset. The naive RAG mode can be enabled with:

```python
graph_func = GraphRAG(working_dir="./dickens", enable_naive_rag=True)
print(rag.query("...", param=QueryParam(mode="naive")))
```

Source: [readme.md](readme.md) section "## Naive RAG".

### 2.3 Component-Level Comparisons

The README points users to [examples/benchmarks](./examples/benchmarks) for component-level comparisons (LLMs, vector DBs, graph stores, chunking strategies). As stated in the README: *"Check examples/benchmarks to see few comparisons between components. Always welcome to contribute more components."* Source: [readme.md](readme.md) section "## Components".

## 3. Roadmap

The canonical roadmap lives at [docs/ROADMAP.md](docs/ROADMAP.md). Source: [readme.md](readme.md) section "## Roadmap". The roadmap informs the project's forward direction and helps contributors prioritize work.

### 3.1 Recent Milestones (v0.0.8)

The v0.0.8 release incorporated community contributions ([readme.md](readme.md) section "### Latest Release: v0.0.8"):

| Change | Contributor | PR |
| --- | --- | --- |
| Add Azure OpenAI as an option in `_llm.py` | @SliverBulle | [#31](https://github.com/gusye1234/nano-graphrag/pull/31) |
| Add DSPy for entity extraction | @NumberChiffre | [#27](https://github.com/gusye1234/nano-graphrag/pull/27) |
| Fix `graphml_visualize.py` for long data | @akai-shuuichi | related PR |

### 3.2 Contribution Guidelines

Anyone can contribute; the project documents the workflow in [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md). Source: [readme.md](readme.md) section "## Contribute".

## 4. Known Limitations

The README transparently enumerates two functional limitations under its "Issues" section. Source: [readme.md](readme.md) section "## Issues".

### 4.1 `covariates` Feature Not Implemented

`nano-graphrag` does not implement the `covariates` feature of GraphRAG. This is a deliberate omission noted in the README.

### 4.2 Global Search Differs from Original

`nano-graphrag` implements global search differently from the original. The reference implementation uses a map-reduce-like style to fill all communities into context. In contrast, `nano-graphrag` selects only the top-K most important and central communities. This is controlled via `QueryParam.global_max_consider_community`, which defaults to **512 communities**. Source: [readme.md](readme.md) section "## Issues".

### 4.3 Windows Encoding Issue

Community issue [#125](https://github.com/gusye1234/nano-graphrag/issues/125) reports an installation error on Windows machines, surfacing as `cp1252.py` decode errors. This indicates non-UTF-8 default encodings on some Windows environments can interfere with package operations.

### 4.4 Repetitive Prompt Content

Community issue [#56](https://github.com/gusye1234/nano-graphrag/issues/56) notes that `PROMPTS["local_rag_response"]` contains duplicated "Goal" and "Target response length and format" sections. Users should verify whether this is intentional before editing prompts. Source: [readme.md](readme.md) section "Prompt" describes the relevant prompt variables.

### 4.5 Missing DRIFT Search

Community feature request [#99](https://github.com/gusye1234/nano-graphrag/issues/99) asks for Microsoft's DRIFT search (released after local and global search) to be ported to `nano-graphrag`.

### 4.6 Component Coverage

Community issue [#2](https://github.com/gusye1234/nano-graphrag/issues/2) ("Add more Storages and LLMs?") is the most-discussed enhancement request. The README's component table (Source: [readme.md](readme.md) section "## Components") shows which backends are built-in versus example-only:

| Type | Backend | Status |
| --- | --- | --- |
| LLM | OpenAI / Amazon Bedrock | Built-in |
| LLM | DeepSeek / Ollama | examples/ |
| Vector DB | nano-vectordb / hnswlib | Built-in |
| Vector DB | milvus-lite / faiss | examples/ |
| Graph | networkx | Built-in |
| Graph | neo4j | Built-in ([doc](docs/use_neo4j_for_graphrag.md)) |

## 5. See Also

- [Project README](../readme.md) — architecture, components, quick start
- [FAQ](../docs/FAQ.md) — frequently asked questions
- [Contributing Guide](../docs/CONTRIBUTING.md) — how to contribute
- [Roadmap](../docs/ROADMAP.md) — forward-looking plans
- [English Benchmark](../docs/benchmark-en.md), [Chinese Benchmark](../docs/benchmark-zh.md), [DSPy Entity Extraction Benchmark](../docs/benchmark-dspy-entity-extraction.md)

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: gusye1234/nano-graphrag

Summary: Found 13 structured pitfall item(s), including 1 high/blocking item(s). Top priority: Configuration risk - Configuration risk requires verification.

## 1. Configuration risk - Configuration risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/gusye1234/nano-graphrag/issues/75

## 2. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/gusye1234/nano-graphrag/issues/163

## 3. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/gusye1234/nano-graphrag/issues/166

## 4. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.host_targets | https://github.com/gusye1234/nano-graphrag

## 5. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/gusye1234/nano-graphrag/issues/167

## 6. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/gusye1234/nano-graphrag

## 7. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/gusye1234/nano-graphrag

## 8. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/gusye1234/nano-graphrag

## 9. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/gusye1234/nano-graphrag

## 10. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/gusye1234/nano-graphrag/issues/125

## 11. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/gusye1234/nano-graphrag/issues/173

## 12. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/gusye1234/nano-graphrag

## 13. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/gusye1234/nano-graphrag

<!-- canonical_name: gusye1234/nano-graphrag; human_manual_source: deepwiki_human_wiki -->
