Fast GraphRAG
Fast GraphRAG uses Personalized PageRank to expand context from seed entities, without the overhead of community detection.
Overview
Fast GraphRAG (from circlemind-ai/fast-graphrag) is designed for:
- Fast queries with minimal LLM calls
- Incremental updates without full reprocessing
- Cost efficiency by avoiding community detection
- Large-scale graphs with millions of entities
Key idea: Use Personalized PageRank seeded from query entities to naturally surface relevant connected context.
How It Works
1. Insert Pipeline
Documents
↓
Chunking
↓
Entity & Relation Extraction (LLM + gleaning)
↓
Graph Construction with Deduplication
├─→ Summarize duplicate descriptions
└─→ Merge similar edges
↓
HNSW Embedding of Entities
↓
StorageKey features:
- LLM-based deduplication: Automatically summarizes duplicate entity descriptions
- Edge merging: Combines similar relationships above threshold
- Domain-aware extraction: Uses domain + example queries for better entity detection
2. Query Pipeline
Query
↓
Extract Query Entities (LLM)
↓
Vector Similarity Search (HNSW)
↓
Seed Personalized PageRank
↓
Rank Nodes (damping=0.85)
↓
Token Budget Truncation
↓
LLM Answer GenerationKey features:
- No community detection: Faster indexing and updates
- Personalized PageRank: Surfaces relevant connected nodes
- Token budgets: Separate budgets for entities, relations, and chunks
- Automatic pruning: Only includes nodes above score threshold
Installation
pnpm add @graphrag-js/fastBasic Usage
import { createGraph } from "@graphrag-js/core";
import { fastGraph } from "@graphrag-js/fast";
import { memoryStorage } from "@graphrag-js/memory";
import { openai } from "@ai-sdk/openai";
const graph = createGraph({
model: openai("gpt-4o-mini"),
embedding: openai.embedding("text-embedding-3-small"),
provider: fastGraph({
entityTypes: ["PERSON", "ORGANIZATION", "LOCATION", "CONCEPT"],
domain: "Scientific research papers on climate change",
exampleQueries: [
"What organizations lead climate research?",
"How does deforestation affect emissions?",
],
}),
storage: memoryStorage(),
});
await graph.insert(documents);
// PageRank retrieval (default)
const { text } = await graph.query("What are the main findings?");
// With references
const { text, context } = await graph.query("Key conclusions?", {
withReferences: true,
});Configuration
interface FastGraphConfig {
entityTypes?: string[];
domain?: string;
exampleQueries?: string[];
maxGleanings?: number;
concurrency?: number;
pagerank?: PageRankConfig;
tokenBudgets?: TokenBudgets;
mergePolicy?: MergePolicy;
}Entity Types
Explicitly specify entity types to extract:
fastGraph({
entityTypes: ["PERSON", "COMPANY", "PRODUCT", "TECHNOLOGY"],
})Default: Auto-detect based on domain and example queries
Tips:
- Use UPPERCASE for entity types (follows fast_graphrag convention)
- Keep to 4-6 types for best results
- Domain-specific types work better than generic types
Domain
Natural language description of your data domain:
fastGraph({
domain: "Technical documentation for React.js library",
})When to use:
- Specialized or technical domains
- Better entity extraction
- Domain-specific relationships
Example Queries
Provide example questions users might ask:
fastGraph({
exampleQueries: [
"How do I use hooks in React?",
"What's the difference between useState and useReducer?",
"How does React rendering work?",
],
})Benefits:
- Guides entity extraction toward relevant concepts
- Improves retrieval relevance
- Optimizes graph structure for your use cases
PageRank Configuration
interface PageRankConfig {
damping?: number; // default: 0.85
maxIterations?: number; // default: 100
tolerance?: number; // default: 1e-6
maxEntities?: number; // default: 128
scoreThreshold?: number; // default: 0.05
}Example:
fastGraph({
pagerank: {
damping: 0.85, // Standard PageRank damping factor
maxIterations: 100, // Convergence iterations
tolerance: 1e-6, // Convergence tolerance
maxEntities: 128, // Maximum entities to include
scoreThreshold: 0.05, // Minimum score to include
},
})Tuning tips:
- Higher damping (0.9): More graph influence, less direct similarity
- Lower damping (0.7): More direct similarity, less graph influence
- Higher maxEntities: Better recall, higher cost
- Higher scoreThreshold: Better precision, faster queries
Token Budgets
Control context size with separate budgets:
interface TokenBudgets {
entities?: number; // default: 4000
relations?: number; // default: 3000
chunks?: number; // default: 9000
}Example:
fastGraph({
tokenBudgets: {
entities: 3000, // Entity descriptions
relations: 2000, // Relationship descriptions
chunks: 8000, // Source chunks
},
})Total context budget: entities + relations + chunks (default: 16000 tokens)
Tuning tips:
- Increase entity budget for entity-centric queries
- Increase relation budget for relationship-centric queries
- Increase chunk budget when you need more source text
Merge Policy
Configure deduplication and merging:
interface MergePolicy {
maxNodeDescriptionSize?: number; // default: 512
edgeMergeThreshold?: number; // default: 5
}Example:
fastGraph({
mergePolicy: {
maxNodeDescriptionSize: 512, // Trigger LLM summarization above this
edgeMergeThreshold: 5, // Merge similar edges above this count
},
})How it works:
- When entity descriptions exceed
maxNodeDescriptionSize, LLM summarizes them - When similar edges exceed
edgeMergeThreshold, they're merged into one
Query Modes
PageRank Mode (Default)
Uses Personalized PageRank for context expansion:
const { text } = await graph.query("What are the key findings?");
// Explicit mode
const { text } = await graph.query("Question", { mode: "pagerank" });How it works:
- Extract entities from query using LLM
- Vector search to find seed entities
- Run Personalized PageRank from seeds
- Rank and filter nodes by score
- Truncate to token budgets
- Generate answer with LLM
Best for:
- Questions with clear entity mentions
- Connected information retrieval
- Multi-hop queries
Naive Mode
Falls back to pure vector search:
const { text } = await graph.query("Question", { mode: "naive" });How it works:
- Vector search on chunks
- Return top-K chunks
- Generate answer with LLM
Best for:
- Broad questions without clear entities
- Baseline comparison
- When PageRank doesn't find relevant entities
Query Options
interface FastQueryOptions {
mode?: "pagerank" | "naive";
withReferences?: boolean;
stream?: boolean;
contextOnly?: boolean;
}Examples:
// With source references
const { text, context } = await graph.query("Question", {
withReferences: true,
});
// Streaming response
const { textStream } = await graph.query("Question", {
stream: true,
});
for await (const chunk of textStream) {
process.stdout.write(chunk);
}
// Context only (no LLM generation)
const { context } = await graph.query("Question", {
contextOnly: true,
});Personalized PageRank Explained
PageRank measures node importance based on incoming links. Personalized PageRank biases the random walk toward specific seed nodes (query entities).
Algorithm:
1. Start with seed nodes (from query)
2. Initialize: 100% probability on seeds
3. For each iteration:
- Distribute probability to neighbors
- Apply damping factor (85% walk, 15% teleport back to seeds)
4. Converge when probabilities stabilize
5. Rank nodes by final probabilityResult: Nodes strongly connected to query entities get higher scores.
Advantages
1. Fast and Cheap
- No community detection: Saves time during indexing
- Minimal LLM calls: Only for extraction and answer generation
- Fast queries: PageRank is efficient on large graphs
2. Incremental Updates
- Add new documents without rebuilding communities
- Deduplication merges with existing entities
- HNSW index supports incremental inserts
3. Scalable
- Handles millions of entities
- HNSW provides fast approximate search
- Token budgets prevent context overflow
4. Flexible
- No predefined community structure
- Works with any graph topology
- Adapts to query-specific contexts
When to Use Fast GraphRAG
Use Fast GraphRAG when:
- ✅ You need fast query responses
- ✅ Your graph is large (>100k entities)
- ✅ You want incremental updates
- ✅ Cost is a major concern
- ✅ Queries have clear entity mentions
Don't use Fast GraphRAG when:
- ❌ You need global thematic summaries (use Microsoft GraphRAG)
- ❌ Your queries are very broad (use LightRAG hybrid mode)
- ❌ Community structure is important for your use case
Complete Example
import { createGraph } from "@graphrag-js/core";
import { fastGraph } from "@graphrag-js/fast";
import { neo4jGraph } from "@graphrag-js/neo4j";
import { qdrantVector } from "@graphrag-js/qdrant";
import { redisKV } from "@graphrag-js/redis";
import { openai } from "@ai-sdk/openai";
const graph = createGraph({
model: openai("gpt-4o-mini"),
embedding: openai.embedding("text-embedding-3-small"),
provider: fastGraph({
entityTypes: ["PERSON", "ORGANIZATION", "LOCATION", "PRODUCT", "TECHNOLOGY"],
domain: "Software engineering and open-source projects",
exampleQueries: [
"Which organizations contribute to React?",
"What technologies does Netflix use?",
"How are microservices related to Kubernetes?",
],
pagerank: {
damping: 0.85,
maxEntities: 128,
scoreThreshold: 0.05,
},
tokenBudgets: {
entities: 4000,
relations: 3000,
chunks: 8000,
},
mergePolicy: {
maxNodeDescriptionSize: 512,
edgeMergeThreshold: 5,
},
maxGleanings: 1,
concurrency: 8,
}),
storage: {
graph: neo4jGraph({ url: process.env.NEO4J_URL, ... }),
vector: qdrantVector({ url: process.env.QDRANT_URL, ... }),
kv: redisKV({ host: process.env.REDIS_HOST, ... }),
},
});
// Insert documents
await graph.insert(documents);
// Query with PageRank
const { text } = await graph.query(
"What are the major open-source contributions by Google?"
);
console.log(text);Comparison with Other Algorithms
| Feature | Fast | LightRAG | Microsoft | Similarity |
|---|---|---|---|---|
| Entity extraction | ✅ | ✅ | ✅ | ❌ |
| Community detection | ❌ | ❌ | ✅ | ❌ |
| PageRank | ✅ | ❌ | ❌ | ❌ |
| Dual vectors | ❌ | ✅ | ❌ | ❌ |
| Indexing speed | Fast | Medium | Slow | Fastest |
| Query speed | Fast | Medium | Medium | Fast |
| Cost | Low | Medium | High | Low |
| Best for | Large graphs | General use | Deep analysis | Prototyping |
Tips and Best Practices
1. Provide Domain Context
fastGraph({
domain: "Technical API documentation for cloud services",
exampleQueries: [
"How do I configure AWS S3?",
"What are the rate limits for the API?",
],
})2. Tune PageRank Parameters
Start with defaults, then adjust based on results:
- Too many irrelevant entities? Increase
scoreThreshold - Missing relevant entities? Increase
maxEntities - Need more graph influence? Increase
damping
3. Monitor Token Budgets
Check if context is being truncated:
const { text, metadata } = await graph.query("Question");
console.log(metadata.tokensUsed, metadata.budgetExceeded);4. Use Streaming for Long Answers
const { textStream } = await graph.query("Complex question", {
stream: true,
});
for await (const chunk of textStream) {
process.stdout.write(chunk);
}5. Incremental Updates
Fast GraphRAG is optimized for incremental updates:
// Initial insert
await graph.insert(initialDocuments);
// Later: add more documents
await graph.insert(newDocuments); // Efficiently mergedSee Also
- LightRAG - Dual-level retrieval
- Microsoft GraphRAG - Community detection
- AWS GraphRAG - Fact-centric graphs
- Algorithms Overview - Compare all algorithms