Spaces:
Sleeping
Sleeping
| # GeminiRAG β Handover Document | |
| **Project:** GeminiRAG β Multimodal RAG Pipeline | |
| **Delivered by:** Dhrumil Parikh | |
| **Delivery date:** 3 June 2026 | |
| **Client:** MasterCRM Internal Engineering | |
| --- | |
| ## How to Run the System | |
| ### Prerequisites | |
| | Requirement | Notes | | |
| |---|---| | |
| | Python 3.11+ | 3.13 disables cross-encoder reranker (safe, falls back gracefully) | | |
| | Node.js 18+ | Frontend only | | |
| | PostgreSQL 16 | Native install or Docker | | |
| | Redis 7+ | Docker recommended | | |
| | ChromaDB 0.5+ | Must run as HTTP server on port 8001 | | |
| | Groq API key | Free tier is sufficient for development | | |
| | Gemini API key | Optional β only needed for `/v1/query/stream` SSE endpoint | | |
| ### First-time setup | |
| ```bash | |
| # 1. Copy and fill environment file | |
| cp .env.example .env | |
| # Required keys: GROQ_API_KEY, SECRET_KEY, DATABASE_URL, REDIS_URL | |
| # See .env.example for all options | |
| # 2. Start Redis and ChromaDB | |
| docker compose up -d redis chromadb | |
| # 3. Create the PostgreSQL database (skip if using Docker Compose postgres service) | |
| createdb geminirag && createuser geminirag --password geminirag | |
| # 4. Install Python dependencies | |
| pip install -e . | |
| # 5. Run migrations | |
| alembic upgrade head | |
| # 6. Seed admin user | |
| py scripts/seed_admin.py --email admin@mastercrm.com --password YourSecurePass! | |
| # 7. API server (terminal 1) | |
| py -m uvicorn app.main:app --reload --port 8000 | |
| # 8. Celery worker (terminal 2) | |
| py -m celery -A app.workers.celery_app worker --loglevel=info --pool=solo | |
| # 9. Frontend (terminal 3) | |
| cd frontend && npm install && npm run dev | |
| # β http://localhost:5173 | |
| ``` | |
| ### Production (Docker) | |
| ```bash | |
| # Set ALLOWED_ORIGINS=https://your-domain.com in .env first | |
| docker compose -f docker-compose.prod.yml up --build | |
| ``` | |
| --- | |
| ## Admin Credentials | |
| ```bash | |
| # Create or update an admin user | |
| py scripts/seed_admin.py --email demo@mastercrm.com --password Demo2026! | |
| # To reset: delete the row in PostgreSQL and re-run | |
| DELETE FROM users WHERE email = 'demo@mastercrm.com'; | |
| ``` | |
| --- | |
| ## LLM Configuration | |
| | Role | Model | Env var | | |
| |---|---|---| | |
| | RAG answer generation | `llama-3.3-70b-versatile` | `GROQ_MODEL` | | |
| | File extraction / summaries / RAGAS | `llama-3.1-8b-instant` | `GROQ_PROCESSING_MODEL` | | |
| | Image OCR / video frames | `meta-llama/llama-4-scout-17b-16e-instruct` | `GROQ_VISION_MODEL` | | |
| | Speech-to-text | `whisper-large-v3` | `WHISPER_MODEL` | | |
| | Streaming query (optional) | `gemini-2.0-flash` | `GEMINI_MODEL` | | |
| | Agent synthesis | `llama-3.1-8b-instant` | hardcoded in `agent/agent.py` | | |
| | Embeddings | `BAAI/bge-small-en-v1.5` (local) | `EMBEDDING_MODEL` | | |
| All Groq calls are logged to `usage_logs` with prompt tokens, completion tokens, and latency. | |
| --- | |
| ## RAGAS Baseline Evaluation | |
| ```bash | |
| # 1. Create a test set | |
| cat > /tmp/ragas_test_set.json << 'EOF' | |
| [ | |
| { | |
| "question": "What is the main topic of the document?", | |
| "ground_truth": "The document covers...", | |
| "job_id": "<UUID of a completed job>" | |
| } | |
| ] | |
| EOF | |
| # 2. Run baseline | |
| py scripts/ragas_baseline.py --test-set /tmp/ragas_test_set.json | |
| # β /tmp/ragas_baseline.json | |
| ``` | |
| **Delivery targets:** Faithfulness β₯ 0.80 Β· Answer Relevancy β₯ 0.75 Β· Context Precision β₯ 0.70 | |
| --- | |
| ## Key Source Files | |
| | File | Purpose | | |
| |---|---| | |
| | `app/main.py` | FastAPI factory, middleware, model warmup | | |
| | `app/config.py` | All env vars with startup validation | | |
| | `app/models/db.py` | ORM tables (User, Job, UsageLog, QueryHistory) | | |
| | `app/api/files.py` | Upload endpoint, file type dispatch | | |
| | `app/api/query.py` | RAG query (JSON + SSE streaming) | | |
| | `app/api/admin.py` | Usage stats, RAGAS trends, user management | | |
| | `app/processors/base.py` | Abstract processor, Groq LLM helpers | | |
| | `app/processors/audio_utils.py` | Whisper transcription + SpeechBrain diarization | | |
| | `app/rag/engine.py` | Hybrid search, confidence gate, Groq answer | | |
| | `app/rag/chunker.py` | Hierarchical (parent/child) chunking | | |
| | `app/rag/vectorstore.py` | ChromaDB helpers + RRF merge | | |
| | `app/rag/bm25_index.py` | BM25 index (Redis-cached) | | |
| | `app/rag/reranker.py` | Cross-encoder reranker | | |
| | `app/agent/agent.py` | Intent classification + Groq synthesis | | |
| | `app/agent/tools.py` | ingest, status, query, list, summarize tools | | |
| | `app/workers/tasks.py` | process_file, compute_ragas, cleanup_old_uploads | | |
| | `app/evaluation/ragas_eval.py` | RAGAS metric computation | | |
| | `scripts/seed_admin.py` | Create initial admin user | | |
| | `scripts/seed_ragas_scores.py` | Seed day-by-day RAGAS demo data | | |
| | `scripts/ragas_baseline.py` | Offline RAGAS baseline evaluation | | |
| --- | |
| ## Adding a New File Type | |
| 1. Create `app/processors/newtype.py` extending `BaseProcessor` β implement `extract()` and `summarise()`. | |
| 2. Add the extension(s) to `EXTENSION_MAP` in `app/api/files.py`. | |
| 3. Add the dispatch case to `process_file()` in `app/workers/tasks.py`. | |
| 4. Add the extension to the accepted types list in `frontend/src/pages/UploadPage.tsx`. | |
| 5. Add tests in `tests/test_processors.py`. | |
| --- | |
| ## Job Processing Pipeline | |
| ``` | |
| Upload β Job(PENDING) β Celery enqueue | |
| β PROCESSING / extracting β processor.extract() | |
| β PROCESSING / summarising β processor.summarise() + Groq LLM | |
| β PROCESSING / chunking β chunk_markdown_hierarchical() | |
| β PROCESSING / embedding β embed_chunks() via fastembed (local) | |
| β PROCESSING / indexing β ChromaDB upsert + BM25 invalidate | |
| β COMPLETED (chunk_count set) | |
| On retryable error (rate limit, unknown): | |
| β FAILED β re-enqueue (60 Γ 2βΏ s) β repeat up to 3Γ | |
| β FAILED_PERMANENT + Redis dead-letter queue | |
| Speaker embeddings (audio/video only): | |
| SpeechBrain ECAPA mean embedding per speaker attached as | |
| speaker_embedding_json metadata on each ChromaDB chunk. | |
| ``` | |
| --- | |
| ## Known Limitations | |
| 1. **Speaker diarization accuracy** depends on audio quality. Mono recordings with minimal background noise and clearly distinct voices produce the best results. Overlapping speech is not supported. | |
| 2. **Large video files (> 500 MB)** are rejected at upload. Near-duplicate frame skipping (> 98 % histogram similarity) reduces the number of frames processed. | |
| 3. **RAGAS token cost** β every RAG query triggers a background RAGAS evaluation that calls the Groq LLM again. At high query volumes this can be significant. Disable by removing `compute_ragas.delay(str(qh.id))` in `app/rag/engine.py`. | |
| 4. **ChromaDB persistence** β embeddings live in a Docker named volume. Deleting the volume loses all vectors; documents must be re-uploaded and re-processed. Back up the `chromadata` Docker volume before infrastructure changes. | |
| 5. **Agent LLM window** β the last 10 conversation turns are sent to Groq; full history is stored in Redis for 7 days but not included in the LLM context after 10 turns. | |
| 6. **Reranker on Python 3.13+** β disabled by default due to native tokenizer crash. Set `GEMINIRAG_RERANKER=1` to force-enable (Python 3.11 / Docker only). | |
| 7. **Streaming query requires Gemini** β `POST /v1/query/stream` uses the Gemini SDK for SSE streaming. Set `GEMINI_API_KEY` to use it. The standard `POST /v1/query` always uses Groq and does not require a Gemini key. | |