Loading repository data…
Loading repository data…
AmirhosseinHonardoust / repository
An explainable AI system that combines Graph Intelligence, Vector Search, and Retrieval-Augmented Generation (RAG) to deliver grounded answers and transparent reasoning paths. Includes a FastAPI backend, Streamlit UI, FAISS vector index, and an in-memory knowledge graph for hybrid retrieval and recommendations.
An explainable Graph + Vector Retrieval system that indexes Markdown documents, builds a lightweight knowledge graph, retrieves relevant chunks with FAISS, expands results through graph concepts, and returns source-grounded answers with citations, reasoning paths, and retrieval traces.
Important: This project is an LLM-ready retrieval system, not a fully autonomous knowledge engine.
By default, it uses extractive answer mode, meaning it answers from retrieved passages instead of generating unsupported claims. Optional LLM mode can be enabled with an API key for grounded answer generation.
Many RAG projects behave like black boxes: a question goes in, an answer comes out, and the user cannot easily see why the system selected certain sources.
Graph-RAG-Engine takes a more transparent approach. It combines dense vector search with a lightweight graph layer so answers can include retrieved passages, citations, related concepts, graph paths, and score-level retrieval traces.
The goal is to demonstrate how a RAG workflow can be turned into an explainable retrieval system, not just a chatbot wrapper around an embedding index.
This project focuses on:
This project can:
data/docs/This project does not:
A production RAG platform would need stronger retrieval evaluation, source governance, monitoring, feedback loops, access control, observability, data-security review, and deployment hardening.
all-MiniLM-L6-v2Markdown documents
↓
Chunking + concept extraction
↓
Sentence embeddings ───────────────→ FAISS vector index
↓
Docs / chunks / concepts ──────────→ NetworkX graph
↓
User question
↓
Vector search
↓
Graph expansion
↓
Hybrid reranking
↓
Extractive answer or optional LLM answer
↓
Citations + graph paths + retrieval traces
Graph-RAG-Engine/
│
├── .github/
│ └── workflows/
│ └── ci.yml
│
├── backend/
│ ├── __init__.py
│ ├── api.py
│ ├── llm.py
│ ├── rag.py
│ └── retriever.py
│
├── data/
│ ├── docs/
│ │ ├── api_contracts.md
│ │ ├── chunking_strategies.md
│ │ ├── citation_grounding.md
│ │ ├── graph_rag_overview.md
│ │ ├── hybrid_retrieval.md
│ │ ├── retrieval_evaluation.md
│ │ └── ...
│ └── index/ # generated by ingestion (gitignored)
│ ├── chunks.json
│ ├── docs.json
│ ├── faiss.index
│ ├── graph.json
│ └── vectors.npy
│
├── env/
│ └── requirements.txt
│
├── evaluation/
│ ├── __init__.py
│ ├── evaluate_retrieval.py
│ ├── baseline.json
│ ├── golden_queries.json
│ ├── metrics.py
│ └── results/ # generated by evaluation (gitignored)
│ └── retrieval_eval.json
│
├── graph/
│ ├── __init__.py
│ └── graph_store.py
│
├── ingest/
│ ├── __init__.py
│ ├── ingest_docs.py
│ └── split.py
│
├── tests/
│ ├── test_evaluation_baseline.py
│ ├── test_graph_store.py
│ ├── test_llm.py
│ ├── test_project_integrity.py
│ ├── test_retrieval_evaluation_dataset.py
│ ├── test_retrieval_evaluation_smoke.py
│ ├── test_retrieval_metrics.py
│ ├── test_retrieval_trace.py
│ ├── test_retriever_api_contract.py
│ ├── test_split.py
│ └── test_ui_contracts.py
│
├── ui/
│ ├── __init__.py
│ └── app.py
│
├── pipeline.py
├── run_backend.py
├── Makefile
├── pyproject.toml
├── .gitignore
├── .pre-commit-config.yaml
├── README.md
└── LICENSE
git clone https://github.com/AmirhosseinHonardoust/Graph-RAG-Engine.git
cd Graph-RAG-Engine
On Windows CMD:
python -m venv .venv
.venv\Scripts\activate
On Windows PowerShell:
python -m venv .venv
.venv\Scripts\Activate.ps1
On macOS/Linux:
python -m venv .venv
source .venv/bin/activate
Install in editable mode. This pulls in all dependencies and registers the
graph-rag-ingest, graph-rag-eval, and graph-rag-serve commands:
python -m pip install --upgrade pip
pip install -e .
For development tools (Ruff, Black, mypy, pre-commit):
pip install -e ".[dev]"
The pinned dependency list is also available at env/requirements.txt. The
first embedding run may download the SentenceTransformer model, so an internet
connection is required for initial setup.
Once installed, build the index and validate retrieval quality in one command:
graph-rag-pipeline
This ingests the documents, builds the index, runs the golden-query evaluation,
and fails if any metric drops below evaluation/baseline.json. Common tasks are
also wrapped in a Makefile:
make dev # install with dev tools and git hooks
make pipeline # ingest + evaluate
make serve # run the FastAPI backend
make lint # ruff + black + mypy
make test # run the unit tests
On platforms without make, use the console commands directly
(graph-rag-ingest, graph-rag-eval, graph-rag-serve, graph-rag-pipeline).
Run ingestion (from anywhere once installed):
graph-rag-ingest
This will:
data/docs/data/index/Generated index artifacts are saved in:
data/index/
Security note: Index artifacts (
chunks.json,docs.json,graph.json) are stored as JSON, so loading them cannot execute code. The FAISS index andvectors.npyare binary numeric files. Only the embedding vectors and FAISS index require trusting the producer; none of the artifacts are pickled.
Start the FastAPI backend:
graph-rag-serve
This serves backend.api:app on 127.0.0.1:8000 with reload enabled. You can
also run uvicorn directly: uvicorn backend.api:app --reload --port 8000.
Open the API docs:
http://localhost:8000/docs
Health check:
curl http://localhost:8000/health
Expected response:
{
"ok": true
}
In another terminal, run:
streamlit run ui/app.py
The UI opens at:
http://localhost:8501
By default, the UI calls the backend at:
http://localhost:8000
You can override this with:
export GRAPH_RAG_API_URL="http://localhost:8000"
On Windows PowerShell:
$env:GRAPH_RAG_API_URL="http://localhost:8000"
The Streamlit app supports both answer modes:
extractivellmIf LLM mode is selected without a valid API key, the backend falls back to extractive mode and returns an LLM error message.
The project supports two answer modes.
Extractive mode is the default.
It uses retrieved passages directly and avoids generating unsupported claims.
{
"question": "What is FAISS?",
"mode": "extractive"
}
This mode is useful for:
LLM mode sends retrieved passages to an OpenAI-compatible chat-comple