Skip to content

Repository files navigation

GraphRAG

GraphRAG is a FastAPI-based Retrieval-Augmented Generation (RAG) service that stores uploaded knowledge in Neo4j and answers questions with graph-aware retrieval.

The project ingests Markdown or text documents, builds both lexical and property/community graph representations, and exposes an HTTP chat interface for querying that knowledge base with an LLM-powered agent.

What it does

GraphRAG provides an end-to-end flow for graph-backed question answering:

  1. Upload a ZIP archive containing .md or .txt files.
  2. Create or update a knowledge base record in Neo4j.
  3. Ingest the documents into two retrieval structures:
    • Lexical graph: chunk-level document text and embeddings for semantic search.
    • Property/community graph: extracted structured knowledge, communities, and summaries.
  4. Ask questions through the chat API.
  5. The RAG agent retrieves relevant lexical and community context and returns an answer.

Main components

api/
  main.py                    FastAPI application entry point
  routers/
    chat.py                  Chat endpoint
    knowledge_base.py        Knowledge-base ingestion endpoint
  dependencies/              Dependency providers for LLMs, vector stores, graph DB, and agent
  schema/                    API request and response models
  bruno/                     Bruno API collection

common/
  graph/                     Neo4j client and configuration
  schema/                    Shared knowledge-base schemas
  services/                  Knowledge-base persistence service
  utils/                     Environment and logging helpers

ingestion/
  pipeline.py                Ingestion orchestration
  ingestors/                 Lexical and property graph ingestors
  readers/                   Markdown/text readers
  prompts/                   Extraction prompts
  schema/                    Ingestion models

rag/
  agent.py                   RAG agent factory
  retrievers/                Vector, similarity, and DRIFT retrievers
  tools/                     Agent search tools
  prompts/                   Agent and retriever prompts
  cyphers/                   Cypher snippets
  schema/                    RAG context and retriever schemas

main.py                      Local/manual experimentation script
compose.yaml                 Docker Compose configuration
dockerfile                   Container image definition
pyproject.toml               Python package metadata

Technologies used

  • Python 3.13 for the application runtime.
  • FastAPI for the HTTP API.
  • Neo4j for graph persistence and vector-backed retrieval through LangChain Neo4j.
  • Neo4j Graph Data Science (GDS) for Leiden community detection during property-graph ingestion.
  • LangChain for document, vector-store, prompt, parser, and chat-model integrations.
  • LangGraph with a SQLite checkpointer for conversational agent state.
  • Google Generative AI embeddings through langchain-google-genai for vector embeddings.
  • OpenAI-compatible chat models through langchain-openai; defaults point at OpenRouter unless overridden by environment variables.
  • Pydantic for API and extraction schemas.
  • uv for container dependency installation.
  • Docker / Docker Compose for containerized API startup.

How extraction works

Document ingestion is handled by the knowledge-base ingestion route and the Pipeline class. The route extracts an uploaded ZIP archive, keeps .md and .txt files, reads them as documents, and then runs both lexical and property graph ingestors.

Lexical graph extraction

The lexical ingestor stores document chunks in the Neo4j vector store, attaches each chunk to the knowledge base, creates a File node, and links chunks to their source file. It then retrieves chunk embeddings and creates SIMILAR relationships between chunks whose vector similarity is above the configured lexical threshold.

Property graph extraction

The property graph ingestor uses the configured chat model to extract structured graph data from document text. If the knowledge base does not already provide an ontology, the ingestor first asks the LLM to derive one from the knowledge extraction prompt. That ontology defines allowed entity labels and relationship rules.

For each document chunk, the ingestor sends the chunk text, ontology, and previously discovered entities to the LLM. The LLM response is parsed into entities and triplets with Pydantic output parsers. The ingestor deduplicates entities within the file, assigns stable internal IDs, writes entity nodes, links entities back to source chunks with BELONGS_TO, and creates extracted relationships between entities.

Community extraction and summaries

After entities and relationships are written, the property graph ingestor can run community extraction. It projects the file's graph into Neo4j GDS, runs the Leiden algorithm, writes community IDs, creates Community nodes, and links entities with IN_COMMUNITY. It then asks the LLM to summarize each community's triplets and embeds those summaries so the chat flow can retrieve community-level context.

API interface

The FastAPI application is configured with a /v1 root path.

GET /v1/

Returns a basic service message.

Example response:

{
  "message": "GraphRAG API"
}

POST /v1/knowledge_base/ingest

Uploads and ingests a knowledge base.

The endpoint accepts multipart form data described by IngestionRequest.

Field Type Required Description
id string Yes Knowledge-base identifier.
name string Yes Human-readable knowledge-base name.
description string No Optional knowledge-base description.
knowledge_extraction_prompt string No Optional prompt used to guide property graph extraction.
ontology object No Optional ontology definition for extracted entities and relationships.
files file Yes ZIP archive containing .md or .txt files.

During ingestion, the API extracts the archive, reads supported files, creates a KnowledgeBase, and schedules the ingestion pipeline as a background task.

POST /v1/chat

Sends a question to the RAG agent.

Request body:

{
  "query": "What does the knowledge base say about Ayrton Senna?",
  "thread_id": "optional-existing-thread-id"
}
Field Type Required Description
query string Yes User question.
thread_id string No Existing conversation thread ID. If omitted, the API creates one.

Example response:

{
  "thread_id": "generated-or-supplied-thread-id",
  "message": {
    "content": "..."
  }
}

The chat route invokes the RAG agent with lexical and community vector stores plus DRIFT retrieval settings:

{
  "top_k": 5,
  "max_depth": 2,
  "max_follow_ups": 3
}

Runtime requirements

  • Python >=3.13
  • Neo4j
  • Provider credentials for the configured embedding model and chat model

Core Python dependencies include FastAPI, LangChain, LangChain Neo4j, LangChain OpenAI, LangChain Google GenAI, LangGraph SQLite checkpointing, Pydantic, NumPy, and python-dotenv.

Configuration

Create environment variables for Neo4j and any model providers used by your deployment.

Common Neo4j variables:

NEO4J_URI=
NEO4J_USER=
NEO4J_PASSWORD=

Depending on the selected LLM and embedding providers, you may also need provider-specific API keys such as:

GOOGLE_API_KEY=
OPENAI_API_KEY=
OPENROUTER_API_KEY=

Running the API

Install dependencies, then run the FastAPI application.

Using the FastAPI CLI:

fastapi dev api/main.py

Using Uvicorn:

uvicorn api.main:app --reload

The API routes are exposed under /v1.

Docker setup

The repository includes a dockerfile and compose.yaml for containerizing the API service. The image is based on python:3.13-slim, installs uv, runs uv sync --no-dev, copies the application into /app, creates a non-root appuser, exposes port 8000, and starts Uvicorn with api.main:app bound to 0.0.0.0:8000.

Build and run the API container with Docker Compose:

docker compose up --build

The compose file maps host port 8000 to container port 8000, so the API is available at:

http://localhost:8000/v1/

The current compose file defines only the graphrag API service. You still need an accessible Neo4j instance configured through environment variables. Make sure the container receives the required Neo4j and model-provider variables, either through your shell environment, a Compose environment: block, or a Compose env_file: entry.

Example .env values:

NEO4J_URI=bolt://host.docker.internal:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=password
NEO4J_DATABASE=neo4j
LLM_MODEL=openai/gpt-oss-120b:free
LLM_BASE_URL=https://openrouter.ai/api/v1
LLM_TEMPERATURE=0.7
SQL_LITE_DB=database.db

Local experimentation

The top-level main.py script demonstrates manual setup for embeddings, chat models, Neo4j vector stores, ingestion checks, retrieval checks, and RAG-agent invocation. It is separate from the FastAPI app entry point in api/main.py.

API collection

A Bruno collection is included in api/bruno/ with example requests and environment configuration for the API.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages