# ===================================== # PDF Q&A Bot - Environment Template # Copy this file to .env and update values as needed. # ===================================== # ─── Frontend (React) ──────────────────────────────────────────────────────── # Supabase project URL and anon key (used for authentication) REACT_APP_SUPABASE_URL=your_supabase_project_url REACT_APP_SUPABASE_ANON_KEY=your_supabase_anon_key # ─── LLM / Embedding ──────────────────────────────────────────────────────── # Hugging Face generation model used by rag-service/main.py # Examples: # - google/flan-t5-small (faster) # - google/flan-t5-base (better quality) HF_GENERATION_MODEL=google/flan-t5-base # Optional legacy variable (not required by current HF RAG flow) # Keep blank unless your custom code uses it. OPENAI_API_KEY= # ─── Networking ────────────────────────────────────────────────────────────── # Optional app host/port settings HOST=127.0.0.1 PORT=5000 # URL of the RAG FastAPI service used by the Express API Gateway. # Default: http://localhost:5000 RAG_SERVICE_URL=http://localhost:5000 # JWT secret key for signing authentication tokens (Express API Gateway). JWT_SECRET=your_jwt_secret_here # Shared secret used to authenticate the Express gateway to the RAG service. # When set, the RAG service will reject direct requests missing/incorrect token. # # ⚠️ PRODUCTION REQUIREMENT: This MUST be set to a strong random value in any # deployed environment. Without it, any caller with network access to the # RAG service port (5000) can invoke the full LLM pipeline — bypassing every # rate limiter, slow-down delay, and IP ban enforced by the Express gateway. # # Protected endpoints (when token is set): # POST /process-pdf # POST /ask # POST /ask/stream ← streaming inference; also protected since v0.x # POST /summarize # POST /validate-session-write # POST /sessions/lookup # GET /processing-status/{id} # Any future sub-route under /ask/ (prefix guard) # # Defense-in-depth: even with this token set, do NOT expose port 5000 # to the public internet. The Docker Compose config binds the RAG service # to the internal network only (no `ports:` entry). If you run without # Docker Compose, use a firewall rule or bind to 127.0.0.1 explicitly. # # Generate a strong random value (example): # openssl rand -hex 32 INTERNAL_RAG_TOKEN= # How often (in seconds) the background flush thread writes dirty session # metadata to per-session files. Lower values reduce data-loss exposure on # unclean shutdown; higher values batch more I/O. Defaults to 10 seconds. # SESSION_FLUSH_INTERVAL_SECONDS=10 # ─── Environment / Runtime ────────────────────────────────────────────────── # Set to "production" in deployed environments. # Express: controls whether detailed error messages are returned to the client. # - "production" → generic error messages only # - anything else → full error details included in responses (dev mode) # NODE_ENV=production # Controls uvicorn reload behaviour in rag-service/main.py. # - "production" → reload=False (stable, no filesystem watcher) # - anything else → reload=True (auto-restart on file changes, dev only) # ⚠️ MUST be set to "production" in deployed environments or sessions will be # silently destroyed whenever a file changes on disk. ENVIRONMENT=production # ─── Reverse Proxy / Trust ────────────────────────────────────────────────── # Number of reverse proxies in front of the Express server (e.g. Nginx, AWS ALB, Cloudflare). # Express uses this to extract the real client IP from X-Forwarded-For. # ⚠️ If left at 0 behind a load balancer, the rate limiter sees only the LB's IP # and will lock out ALL users when a single attacker exceeds the limit. # Default: 0 (no proxy) PROXY_COUNT=0 # ─── Rate Limiting (Express API Gateway) ───────────────────────────────────── # Storage backend used for rate limit counters + slow-down counters + IP ban state. # - memory: single-instance only (default) # - redis: distributed across replicas (recommended for production) # Default: memory RATE_LIMIT_STORE=memory # Redis connection URL for distributed rate limiting (used when RATE_LIMIT_STORE=redis). # You may also set REDIS_URL instead. # Example: redis://localhost:6379 RATE_LIMIT_REDIS_URL= # Prefix used for IP ban keys in Redis. # Default: ban: BAN_REDIS_PREFIX=ban: # Maximum PDF uploads per IP per hour. # Tripping this limit triggers the escalating IP ban system. # Default: 10 RATE_LIMIT_UPLOAD_MAX=10 # Number of free inference requests (per 5-min window) before progressive # slow-down kicks in. Each extra request adds (hits - threshold) × 500ms delay, # capped at 5 seconds. # Default: 10 RATE_LIMIT_SLOWDOWN_AFTER=10 # Hard cap on inference requests (/ask, /summarize) per IP per 5-min window. # Tripping this triggers the escalating IP ban system. # Default: 30 RATE_LIMIT_INFERENCE_MAX=30 # ─── Session & FAISS Memory Quotas (RAG Service) ──────────────────────────── # How long an idle session stays alive before automatic cleanup (minutes). # Default: 30 SESSION_TTL_MINUTES=30 # Maximum number of concurrent sessions stored in memory. # When exceeded, the oldest session is evicted. # Default: 100 MAX_ACTIVE_SESSIONS=100 # Maximum number of PDF documents that can be uploaded to a single session. # Prevents unbounded FAISS index growth from repeated uploads. # Default: 5 MAX_DOCUMENTS_PER_SESSION=5 # Maximum total text chunks across all documents in a single session. # Guards against memory exhaustion from very large PDFs. # Default: 2000 MAX_CHUNKS_PER_SESSION=2000 # ─── PDF Upload Safety (Express API Gateway) ──────────────────────────────── # Maximum allowed PDF file size per upload in megabytes (MB). # Requests with files larger than this will be rejected with HTTP 413 Payload Too Large. # This prevents attackers from uploading huge files to exhaust disk space or cause DoS. # Default: 50 (recommended for most deployments) MAX_UPLOAD_SIZE_MB=50 # ─── PDF Parsing Safety (RAG Service) ──────────────────────────────────────── # Hard wall-clock timeout for PDF parsing/text extraction (seconds). # This mitigates DoS-grade PDFs that are small but extremely expensive to parse. # Default: 20 PDF_PARSE_TIMEOUT_SECONDS=20 # Maximum number of pages allowed in a single PDF upload. # Default: 200 MAX_PDF_PAGES=200 # Maximum number of extracted characters kept from the PDF before chunking. # Default: 400000 MAX_PDF_EXTRACT_CHARS=400000 # ─── Retrieval Tuning (RAG Service) ───────────────────────────────────────── # Relevance threshold for FAISS retrieval in /ask (L2 distance). # Lower score = more similar. Chunks with score > this value are treated as irrelevant. # If ALL retrieved chunks exceed this threshold, a fallback answer is returned instead # of sending weak context to the LLM. Typical range: 0.5 (strict) to 1.5 (lenient). # Default: 1.0 RELEVANCE_THRESHOLD=1.0 # Number of candidate chunks retrieved from FAISS before diversity filtering. # Default: 12 ASK_RETRIEVAL_CANDIDATES=12 # Maximum chunks sent to the LLM as context after diversity filtering. # Default: 6 ASK_MAX_CONTEXT_CHUNKS=6 # Maximum chunks per source document included in context (diversity cap). # Default: 2 ASK_CHUNKS_PER_DOCUMENT=2 # ALLOWED_ORIGIN: Restricts CORS to this frontend origin only. # In production, set this to your deployed frontend URL (e.g. https://yourapp.com). # Requests from any other origin will be blocked by the browser. ALLOWED_ORIGIN=http://localhost:3000 # ─ Semantic Chunking (RAG Service) ─────────────────────────────────────────── # Soft maximum characters per chunk after Pass 1 (boundary-aware split). # Chunks will NOT be cut mid-sentence just to hit this limit. # Default: 1200 SEMANTIC_CHUNK_SOFT_MAX=1200 # Chunks shorter than this (chars) become candidates for semantic merging in Pass 2. # Default: 150 SEMANTIC_CHUNK_MERGE_MIN=150 # Hard upper bound on merged chunk length. Merging is skipped even when # similarity >= threshold if the result would exceed this size. # Default: 1400 SEMANTIC_CHUNK_MERGE_MAX=1400 # Cosine similarity threshold for merging adjacent tiny chunks (Pass 2). # Range: 0.0 (always merge) to 1.0 (never merge). Recommended: 0.70–0.80. # Default: 0.75 SEMANTIC_CHUNK_SIMILARITY_THRESHOLD=0.75 # Wall-clock warning threshold for the Pass 2 embedding calls (seconds). # A WARNING is logged if semantic merging for a single page exceeds this. # Default: 5.0 SEMANTIC_CHUNK_MERGE_WARN_SECS=5.0 # Enable hierarchical chunk storage (Pass 2b). # Each chunk carries small_chunk (retrieval unit) and parent_chunk # (small chunk + 1–2 neighbour sentences, sent to the LLM as context). # Set to false to disable and save metadata memory. # Default: true SEMANTIC_CHUNK_HIERARCHICAL=true