Local hybrid retrieval-augmented generation over text files. Documents are chunked, embedded, and stored in MongoDB. Queries are answered with a mix of semantic vector search and BM25 keyword search, then optionally passed to an LLM.
- Document ingestion with overlapping chunks and multilingual embeddings
- Vector search with cosine similarity
- BM25 lexical search
- Hybrid fusion with Reciprocal Rank Fusion (RRF)
- Optional Metis / OpenAI-compatible generation
- FastAPI service and a small web UI
If no LLM API key is set, the app still returns the top retrieved passage so you can test retrieval locally.
- Start MongoDB:
docker compose up -d- Create a virtual environment and install dependencies:
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt-
Copy
.env.exampleto.envand fill in your Metis key if you want generated answers. -
Ingest the sample documents from the project root:
python -m app.ingestion.ingest- Run the API:
uvicorn app.main:app --reloadOpen http://127.0.0.1:8000 for the UI, or http://127.0.0.1:8000/docs for the API.
curl -X POST http://127.0.0.1:8000/query ^
-H "Content-Type: application/json" ^
-d "{\"query\": \"What product does Ara Company build for restaurants?\", \"mode\": \"hybrid\"}"Retrieval modes: hybrid, vector, bm25.
Put .txt files in data/documents/, then run ingest again or click Re-ingest documents in the UI.
- Embeddings use
paraphrase-multilingual-MiniLM-L12-v2locally, so ingestion works without an LLM key. - Generation uses the OpenAI-compatible Metis endpoint from
.env. - Vector search currently scores embeddings in Python, which is fine for a small local corpus.