DocuRAG Backend is a FastAPI-based retrieval-augmented generation (RAG) service for document ingestion, vector search, source-grounded answers, and retrieval evaluation.
The project focuses on an end-to-end backend pipeline:
document upload
-> document loader
-> chunk splitting and metadata enrichment
-> embedding generation
-> PostgreSQL / pgvector storage
-> scoped or global vector retrieval
-> source-grounded RAG answer generation
-> retrieval and answer-layer evaluation
- FastAPI backend with typed Pydantic request and response models.
- Document ingestion with path validation and upload isolation.
- Chunk metadata for traceability:
file_id,user_id,chunk_id,digest,chunk_index,source_file, andpage. - Configurable embedding providers, with local Hugging Face embeddings supported by default in
.env.example. - PostgreSQL + pgvector vector store with async wrappers and metadata filtering.
- Structured retrieval APIs for single-file and global knowledge-base search.
- Prefix-scoped global retrieval for clean evaluation boundaries.
- RAG chat APIs returning
answer,sources,refusal, andanswer_strategy. - Optional OpenAI-compatible LLM generation layer for grounded answers with
[source n]citations. - Extractive fallback and no-context / low-confidence refusal behavior.
- HotpotQA / BEIR subset evaluation scripts for retrieval and answer-layer grounding metrics.
- Docker Compose setup for local API + pgvector development.
Client
-> FastAPI app
-> /embed or /embed-upload
-> Loader
-> RecursiveCharacterTextSplitter
-> Embedding provider
-> pgvector
-> /retrieval/search or /retrieval/search_global
-> /rag/chat or /rag/chat_global
-> answer + sources + refusal
See docs/architecture.md for a fuller architecture walkthrough.
Copy the example environment file:
cp .env.example .envThe example configuration uses:
VECTOR_DB_TYPE=pgvector
EMBEDDINGS_PROVIDER=huggingface
EMBEDDINGS_MODEL=BAAI/bge-m3
RAG_LLM_PROVIDER=disabledTo enable LLM answer generation, set the optional RAG_LLM_* variables in your local .env. Do not commit real API keys.
docker compose up --buildThe API will be available at:
http://127.0.0.1:8000
Health check:
curl http://127.0.0.1:8000/healthUse Python 3.10+:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8000If you run the API locally while pgvector runs in Docker, set:
DB_HOST=127.0.0.1
DB_PORT=5433curl -X POST "http://127.0.0.1:8000/embed" \
-F "file_id=demo-doc-1" \
-F "file=@examples/demo.txt;type=text/plain"curl -X POST "http://127.0.0.1:8000/retrieval/search" \
-H "Content-Type: application/json" \
-d '{
"query": "What is this document about?",
"file_id": "demo-doc-1",
"k": 5
}'curl -X POST "http://127.0.0.1:8000/retrieval/search_global" \
-H "Content-Type: application/json" \
-d '{
"query": "What does the knowledge base say?",
"k": 5
}'curl -X POST "http://127.0.0.1:8000/retrieval/search_global" \
-H "Content-Type: application/json" \
-d '{
"query": "What does the evaluation subset say?",
"k": 5,
"file_id_prefix": "hotpotqa-day11-"
}'curl -X POST "http://127.0.0.1:8000/rag/chat_global" \
-H "Content-Type: application/json" \
-d '{
"query": "Answer using retrieved sources.",
"k": 5,
"max_context_chars": 2200,
"use_llm": true
}'The response includes:
answer
refusal
answer_strategy
used_context_count
sources[]
This repository includes scripts for HotpotQA / BEIR subset evaluation:
scripts/hotpotqa_prepare_subset.pyscripts/hotpotqa_import_subset.pyscripts/evaluate_hotpotqa_retrieval.pyscripts/evaluate_hotpotqa_rag_answers.pyscripts/evaluate_rag_refusals.py
The reported project metrics are based on a strict subset, not the full HotpotQA / BEIR benchmark:
Dataset: BEIR HotpotQA
Queries: 100
Candidate docs: 5200
Relevant support docs: 200
Random negatives: 5000
Embedding: BAAI/bge-m3
Vector store: PostgreSQL + pgvector
Final subset metrics:
Prefix-scoped global retrieval:
Recall@5 = 96.5%
All-Support@5 = 93.0%
Recall@10 = 98.0%
All-Support@10 = 96.0%
100-query answer-layer evaluation:
support-source hit rate = 100%
all-support-in-sources rate = 93.0%
citation marker rate = 100%
LLM grounded answer rate = 92.0%
low-confidence refusal rate = 8.0%
answer_error_count = 0
These are subset grounding and retrieval metrics. They are not official full-corpus HotpotQA / BEIR benchmark results and are not official answer EM/F1 scores.
See docs/evaluation.md for commands and metric definitions.
Install test dependencies:
pip install -r test_requirements.txtRun the test suite:
pytestRun selected tests:
pytest tests/test_main.py tests/services/test_rag.py tests/test_hotpotqa_eval_scripts.py -q- Never commit
.env, API keys, model service credentials, uploaded files, or downloaded datasets. data/anduploads/are runtime directories and are ignored by Git.- Use
file_id,entity_id, and metadata filters to keep retrieval scoped to authorized documents. - The LLM layer is optional; embeddings and retrieval can run locally without an LLM API key.
- If an LLM is enabled, only retrieved source snippets are sent to the model provider.
See LICENSE.