RAG (Retrieval-Augmented Generation) assistant for Echamor data.
This project:
- Loads markdown knowledge documents from
knowledge-base/ - Chunks and embeds them into a local Chroma database in
preprocessed_db/ - Answers user questions with retrieval + reranking + LLM response generation
- Exposes an interactive chat UI with Gradio
- Python 3.11+
uvfor dependency and environment management- ChromaDB for local vector storage
- OpenAI embeddings (
text-embedding-3-large) - LiteLLM for chat completions (
openai/gpt-4.1-nanoby default) - Gradio for the chat interface
src/injest.py: ingestion pipeline (load docs, chunk, embed, index)src/answer.py: retrieval, reranking, query rewrite, final answer generationsrc/app.py: Gradio UIsrc/config.py: model/database/path configuration constantsknowledge-base/: markdown source documentspreprocessed_db/: persisted Chroma vector databasenotebooks/: exploratory notebook(s)
- Python 3.11+
uvinstalled- OpenAI API key
-
Install dependencies:
uv sync
-
Create a
.envfile in the project root (or export env vars in your shell):OPENAI_API_KEY=your_key_here
Notes:
python-dotenvis loaded by the app and ingestion scripts, so local.envvalues are picked up automatically.
Main settings live in src/config.py:
EMBEDDING_MODEL = "text-embedding-3-large"MODEL = "openai/gpt-4.1-nano"DB_NAME = "preprocessed_db"COLLECTION_NAME = "docs"KNOWLEDGE_BASE_PATH = "knowledge-base"
You can edit these constants to change models, collection name, or data paths.
Run:
uv run python src/injest.py
What it does:
- Reads all markdown files recursively under
knowledge-base/ - Splits content into chunks (LLM-assisted for larger files)
- Generates embeddings in batches
- Recreates the Chroma collection and stores all vectors/documents
Important ingestion knobs in src/injest.py:
WORKERS(parallel chunking processes)MAX_EMBEDDING_BATCH_SIZEAVERAGE_CHUNK_SIZE,SINGLE_CHUNK_THRESHOLD
If you hit rate limits, lower WORKERS (the script already suggests setting it to 1).
After ingestion:
uv run python src/app.py
Then open the Gradio URL shown in the terminal (the app also launches in your browser).
The UI includes:
- Chat conversation panel
- Retrieved context panel (source snippets used for answering)
High-level pipeline in src/answer.py:
- Rewrite user query to improve retrieval recall
- Retrieve top chunks for both original and rewritten query
- Merge results and rerank with the LLM
- Keep top final chunks
- Build a context-grounded system prompt and generate final answer
Start JupyterLab:
uv run jupyter lab
Example notebook is available in notebooks/extract_data.ipynb.
-
Missing API key: Ensure
OPENAI_API_KEYis set in.envor shell environment. -
Empty or poor answers: Re-run ingestion after updating files in
knowledge-base/. -
Rate limit or timeout errors during ingestion: Reduce
WORKERSand retry. -
Unexpected retrieval behavior: Review model names and paths in
src/config.py, then rebuild the vector DB.
uv sync- Set
OPENAI_API_KEYin.env uv run python src/injest.pyuv run python src/app.py