npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ashes_born/graph-rag-ts

v0.1.7

Published

Reference implementation of a chunked GraphRAG engine: markdown-aware ingestion, Leiden community detection, hybrid vector+keyword retrieval and evidence-grounded answers (Bun + TypeScript).

Downloads

563

Readme

graphrag-ts

TypeScript GraphRAG for Markdown corpora. Build a knowledge graph, detect communities, and answer with evidence-backed retrieval.

Why this project exists

Traditional vector RAG is good at similarity search, but it is limited when you need cross-document structure, entity relationships, and global context. This repository implements a GraphRAG-style pipeline in TypeScript so you can index Markdown content and retrieve answers from a graph-backed knowledge base without a Python runtime or a custom product framework.

The project is designed for practical backend use:

  • ingest Markdown files and split them into chunks
  • extract entities, edges, and claims
  • store graph data in PostgreSQL via Prisma
  • detect communities and build community summaries
  • support incremental ingestion with SHA-256 diffing and cascade document pruning
  • differential community summary updates (0 LLM cost for unchanged communities)
  • fuse vector, keyword, and topology-based recall for retrieval
  • generate answers from evidence instead of raw model output alone

What it gives you

  • a readable GraphRAG reference implementation in TypeScript
  • database-backed persistence for entities, claims, edges, and communities
  • full and incremental builds (buildIncrementalRAG / startIncrementalBuild / deleteRAGDocument)
  • namespace-aware builds for multi-tenant or multi-corpus usage
  • hybrid retrieval that combines semantic, keyword, and graph signals
  • deterministic fallback behavior when model-based chunking fails
  • a small public API that is easy to embed in an application service

Core pipeline

flowchart LR
    MD[Markdown files] --> SPLIT[Chunking and slicing]
    SPLIT --> GRAPH[Entity + edge + claim graph]
    GRAPH --> COMM[Community detection]
    COMM --> SUMMARY[Community summaries]
    Q[User query] --> INTENT[Intent parsing]
    INTENT --> HYBRID[Hybrid recall: vector + keyword + community]
    HYBRID --> EVIDENCE[Evidence aggregation]
    EVIDENCE --> ANSWER[Grounded answer]

The implementation matches this flow in the codebase:

  • src/build/ handles slicing, graph construction, and community detection
  • src/retrieval/ handles query parsing, ranking, evidence selection, and answer generation
  • prisma/schema.prisma defines the persisted GraphRAG tables
  • src/index.ts exposes the main runtime injection and public API

Quick start

# install dependencies
pnpm install

# generate Prisma client
pnpm run db:generate

# copy environment variables
cp .env.example .env

# apply the schema
pnpm run db:push

# run tests
bun test

# run the demo
bun run examples/demo.ts

Requirements

Before running the project, make sure you have:

  • pnpm 10+
  • Bun 1.1+
  • PostgreSQL with pgvector enabled
  • a chat model for slicing and judging
  • an embedding model compatible with OpenAI-style APIs

Runtime configuration

This repo expects configuration to be provided by the caller. The model loader reads environment variables from src/build/modelLoader.ts.

DATABASE_URL="postgresql://user:pass@localhost:5432/graphrag?schema=public"

RAG_SLICE_API_KEY="your-slice-key"
RAG_SLICE_MODEL="deepseek-chat"
RAG_SLICE_BASE_URL="https://api.deepseek.com/"

RAG_JUDGE_API_KEY="your-judge-key"
RAG_JUDGE_MODEL="deepseek-chat"
RAG_JUDGE_BASE_URL="https://api.deepseek.com/"

RAG_EMBED_API_KEY="your-embedding-key"
RAG_EMBED_MODEL="local-embedding-model"
RAG_EMBED_BASE_URL="http://127.0.0.1:1234/v1"

Typical runtime injection pattern:

import { PrismaClient } from '@prisma/client';
import {
  injectGraphRAG,
  GraphRAGRetrievalService,
  startBuild,
  createBuildRegistry,
} from '@ashes_born/graph-rag-ts';

await injectGraphRAG({
  database: {
    client: new PrismaClient({ datasourceUrl: process.env.DATABASE_URL }),
  },
  models: [
    {
      type: 'slice',
      baseURL: process.env.RAG_SLICE_BASE_URL!,
      model: process.env.RAG_SLICE_MODEL!,
      apiKey: process.env.RAG_SLICE_API_KEY!,
    },
    {
      type: 'judge',
      baseURL: process.env.RAG_JUDGE_BASE_URL!,
      model: process.env.RAG_JUDGE_MODEL!,
      apiKey: process.env.RAG_JUDGE_API_KEY!,
    },
    {
      type: 'embedding',
      baseURL: process.env.RAG_EMBED_BASE_URL!,
      model: process.env.RAG_EMBED_MODEL!,
      apiKey: process.env.RAG_EMBED_API_KEY!,
    },
  ],
});

const registry = createBuildRegistry();
const buildId = startBuild(
  [{ title: 'sample.md', content: 'Alice works with Bob at Acme Corp.' }],
  registry,
  'demo-namespace',
);

const service = new GraphRAGRetrievalService();
const result = await service.retrieve({
  query: 'Who works with Alice?',
  topK: 5,
});

console.log(result.answer);

Public API

This repo exposes a compact API surface that matches the implementation (available via root package or subpaths like @ashes_born/graph-rag-ts/incremental):

Ingestion & Incremental APIs

  • startBuild(...) / startIncrementalBuild(...): starts an async full/incremental build job and returns a build ID
  • buildRAG(...) / buildIncrementalRAG(...): runs full/incremental pipeline and returns BuildSummary
  • deleteRAGDocument(...): cascades deletion of a document, its chunks, graph edges, and claims
  • diffDocuments(...) / computeCommunityFingerprint(...): incremental comparison and topological fingerprint utilities
  • createBuildRegistry(): tracks build lifecycle state
  • GraphRAGRetrievalService: executes hybrid retrieval and evidence-grounded answer generation
  • injectGraphRAG(...): injects Prisma, model config, and optional defaults
  • registerChatAdapter(provider, adapter) / registerEmbeddingAdapter(provider, adapter): register custom LangChain models (e.g. Anthropic, Ollama, Google GenAI)

Custom LangChain Model Adapters

You can register any LangChain-compatible model via the adapter layer:

import { registerChatAdapter, registerEmbeddingAdapter } from '@ashes_born/graph-rag-ts';
import { ChatAnthropic } from '@langchain/anthropic';
import { OllamaEmbeddings } from '@langchain/ollama';

// Register custom chat adapter
registerChatAdapter('anthropic', ({ config, isSlice }) => {
  return new ChatAnthropic({
    anthropicApiKey: config.apiKey,
    modelName: config.model,
  });
});

// Register custom embedding adapter
registerEmbeddingAdapter('ollama', ({ config }) => {
  return new OllamaEmbeddings({
    baseUrl: config.baseURL,
    model: config.model,
  });
});
  • injectModelConfigs(...): initializes model adapters from config objects
  • injectPrismaClient(...): installs the shared Prisma client

Repository layout:

  • src/build/: chunking, graph construction, community detection, registry
  • src/retrieval/: query parsing, recall, ranking, evidence selection, answer generation
  • src/namespace/: namespace scoping and isolation
  • src/config/: default retrieval/build tuning values
  • examples/: demo and benchmark scripts
  • docs/: architecture and comparison notes

Tuning and defaults

The project supports global runtime defaults via injectGraphRAG(...), and request-level overrides via the retrieve(...) options object. The production defaults live in src/config/defaults.ts.

await injectGraphRAG({
  retrievalDefaults: {
    topK: 8,
    vectorChildTopK: 12,
    keywordSearchLimit: 24,
    evidenceChildLimit: 40,
    rrfK: 80,
  },
  buildDefaults: {
    maxChunkSize: 800,
    chunkOverlapRatio: 0.1,
  },
});

Example per-request tuning:

const result = await service.retrieve({
  query: 'Who is Irene Adler?',
  topK: 6,
  options: {
    vectorChildTopK: 20,
    keywordSearchLimit: 30,
    evidenceChildLimit: 50,
    rrfK: 80,
  },
});

These knobs control the retrieval window and ranking behavior:

  • topK: community-level candidate count
  • vectorChildTopK: child chunks returned by vector search
  • keywordSearchLimit: keyword-matched child chunks
  • evidenceChildLimit: evidence merge cap
  • rrfK: reciprocal rank fusion sensitivity
  • maxChunkSize and chunkOverlapRatio: deterministic chunking fallback

Demo and benchmark

# demo build + retrieval
bun run examples/demo.ts

# benchmark recall metrics
bun run demo:benchmark

The benchmark script evaluates retrieval quality against generated Markdown corpora and reports real metrics for the persisted GraphRAG namespace. It is intended to validate the actual build and retrieval pipeline instead of relying on mocked behavior.

Documentation

Contributing

Contributions are welcome through issues and pull requests. The project is organized around small, testable modules, so the most useful changes usually fit into one of these areas:

  • graph construction quality
  • retrieval quality and ranking
  • namespace isolation
  • model-loading robustness
  • documentation and examples

License

MIT