# ── LLM ────────────────────────────────────────────────────────────────────── # Optional: leave blank to use the free local sentence-transformers embedder. # Required only for OpenAI embeddings and GPT-4o-mini generation. OPENAI_API_KEY=sk-replace-me # ── Vector store (FAISS default; optional Qdrant for async pipeline) ───────── # Defaults to ~/.report_genius/faiss_index (cross-platform) # FAISS_INDEX_PATH=~/.report_genius/faiss_index # VECTORSTORE_BACKEND=faiss # QDRANT_URL=http://localhost:6333 # QDRANT_API_KEY= # QDRANT_COLLECTION=rics_chunks # QDRANT_CACHE_COLLECTION=rics_semantic_cache # ENABLE_HYBRID_RETRIEVAL=true # SEMANTIC_CACHE_ENABLED=true # SEMANTIC_CACHE_TTL_HOURS=24 # SEMANTIC_CACHE_SIMILARITY_THRESHOLD=0.92 # ── Report generation pipeline (default: standard RAG + LLM) ─────────────── # PRIMARY_GENERATE_PIPELINE=standard # AGENTIC_INSPECTOR_WHEN_NOTES_ONLY=false # NOTES_ONLY_GENERATION=true # ── Async pipeline (latency / scale) ──────────────────────────────────────── # ENABLE_ASYNC_PIPELINE=false # ENABLE_PARALLEL_SECTION_GENERATION=true # MAX_PARALLEL_SECTIONS=6 # MAX_CONCURRENT_LLM_CALLS=10 # NOTES_COVERAGE_MAX_RETRIES=1 # NOTES_EXPANSION_SKIP_LLM_MAX_BULLETS=4 # SKIP_LLM_GROUNDING_WHEN_NOTES_ONLY=true # SKIP_COMPLIANCE_RETRIES_WHEN_NOTES_ONLY=true # ── Phase 2 (requires ENABLE_ASYNC_PIPELINE=true for speculation + prompt cache) ─ # ENABLE_SPECULATIVE_EXECUTOR=false # ENABLE_PROMPT_CACHING=false # PROMPT_CACHE_MIN_SYSTEM_TOKENS=1024 # SPECULATIVE_CONTEXT_WINDOW=3 # SPECULATIVE_PROBABILITY_THRESHOLD=0.75 # SPECULATIVE_LEARN_MIN_OBSERVATIONS=5 # ALLOW_SQLITE_PARALLEL_SECTIONS=true # AGENTIC_INSPECTOR_WHEN_NOTES_ONLY=false # NOTES_ONLY_GENERATION=true # ── Phase 3: Redis rate limits + job queue ───────────────────────────────────── # REDIS_URL=redis://localhost:6379/0 # ENABLE_JOB_QUEUE=false # JOB_QUEUE_KEY=rics:jobs:generation # JOB_QUEUE_BLOCK_SECONDS=5 # JOB_QUEUE_MAX_CONCURRENT=2 # With ENABLE_JOB_QUEUE=true, run: python jobs_worker.py # Docker: docker compose --profile redis --profile jobs up -d # ── Temporal durable workflows (optional; docker compose --profile temporal) ─── # ENABLE_TEMPORAL_WORKFLOW=false # TEMPORAL_HOST=localhost:7233 # TEMPORAL_NAMESPACE=default # TEMPORAL_TASK_QUEUE=reports # GENERATION_TIMEOUT_SECONDS=3600 # GENERATION_STALE_SWEEP_SECONDS=120 # ── RAG upload sanitisation (strip PII before vector indexing; on-disk files unchanged) ─ # ENABLE_RAG_UPLOAD_SANITISATION=true # On Hugging Face Spaces this defaults to false (one OpenAI call per PDF page → ~5+ min/doc). # style_corpus uploads still force sanitisation when enabled in code. # RAG_SANITISATION_SKIP_KB_TENANT=true # RAG_SANITISATION_CHUNK_CHARS=12000 # RAG_SANITISATION_MAX_OUTPUT_TOKENS=4096 # RAG_SANITISATION_FAIL_CLOSED=true # ── Database ────────────────────────────────────────────────────────────────── DATABASE_URL=sqlite+aiosqlite:///./dev.db # ── File storage (defaults are cross-platform, override if needed) ──────────── # UPLOAD_DIR=~/.report_genius/uploads # ── Cache ───────────────────────────────────────────────────────────────────── # CACHE_DIR=/tmp/section_cache # ── LLM generation limits ───────────────────────────────────────────────────── MAX_CONTEXT_TOKENS=400 MAX_OUTPUT_TOKENS=300 # OpenAI embedding model (only used when OPENAI_API_KEY is set) EMBEDDING_MODEL=text-embedding-3-small # Local sentence-transformers model (used when no OPENAI_API_KEY is set) # Options: all-MiniLM-L6-v2 (384-dim, fast), all-mpnet-base-v2 (768-dim, better quality) LOCAL_EMBEDDING_MODEL=all-MiniLM-L6-v2 CHAT_MODEL=gpt-4o-mini # Optional: extra LLM compliance validator (PASS/FAIL + reasons) after generation. # Runs only when OPENAI_API_KEY is set; regenerates once with feedback on FAIL. # LLM_SECTION_VALIDATOR_ENABLED=false # LLM_SECTION_VALIDATOR_MAX_RETRIES=1 # Autonomous RICS inspector (agentic): OpenAI tool-calling so the model chooses RAG/KB/duplicate tools. # Requires OPENAI_API_KEY. Set false to force the legacy fixed pipeline. # INSPECTOR_TOOL_AGENT=true # INSPECTOR_MAX_TOOL_ROUNDS=12 # Retrieval RETRIEVAL_TOP_K=10 RERANK_TOP_N=3 CHUNK_SIZE=500 # Max inspector note lines per section (default 800); raise for huge field-note dumps # MAX_BULLETS_PER_SECTION=800 # Token budget for RAW NOTES in the generate prompt (separate from RAG snippet budget) # NOTES_PROMPT_TOKEN_BUDGET=3500 CHUNK_OVERLAP=75 # Hierarchical RAG (document → section → paragraph). Re-ingest PDFs after enabling if the index predates hierarchy. # HIERARCHICAL_RAG_ENABLED=true # HIERARCHICAL_K_DOCUMENT=4 # HIERARCHICAL_K_SECTION=8 # HIERARCHICAL_K_PARAGRAPH_POOL=36 # Comma-separated upload UUIDs for template/exemplar RICS PDFs (always in routing universe), e.g. Behrang RICS reference: # RICS_EXEMPLAR_DOCUMENT_IDS= # Standard paragraphs: .docx/.docm read directly; legacy .doc converted (pandoc | LibreOffice | Word+pywin32). # Default file: Behrang RICS Documents/HB-BS STANDARD PARAS v6 Sept 2015.doc — or place any supported format at repo root with same basename. # RICS_STANDARD_PARAGRAPHS_DOCX=Behrang RICS Documents/HB-BS STANDARD PARAS v6 Sept 2015.doc # Leave empty to fall back to glob discovery under KNOWLEDGE_BASE_DIRS instead: # RICS_STANDARD_PARAGRAPHS_DOCX= # STANDARD_PARAGRAPHS_DOCX_GLOBS=*standard*paragraph*.docx,*Standard*Paragraph*.docx # ── Bulk upload & batch processing ──────────────────────────────────────────── # Max logical documents per single POST /upload/batch request (after ZIP expansion) # MAX_UPLOAD_BATCH_FILES=2000 # Max compressed bytes for a .zip in a batch upload # MAX_ARCHIVE_UPLOAD_BYTES=524288000 # 500 MB # Max entries (files) inside one ZIP archive # MAX_ZIP_MEMBERS=50000 # Max declared uncompressed total bytes in one ZIP (zip-bomb guard) # MAX_ZIP_UNCOMPRESSED_BYTES=5368709120 # 5 GB # Parallel ingestion pipelines — each uses embedding + vector-store threads # MAX_CONCURRENT_INGESTS=16 # Max document IDs per POST /documents/batch-status request # MAX_BATCH_STATUS_DOCUMENT_IDS=10000 # Max rows returned by GET /documents # DOCUMENTS_LIST_MAX_LIMIT=500 # ── Section photo policy (tenant RAG uploads only; no letter heuristics) ─── # Scans completed PDF/DOCX in the tenant library for images under each RICS section heading. # Optional JSON overrides per section: REQUIRES_IMAGE | OPTIONAL_IMAGE | NO_IMAGE_NEEDED # SECTION_PHOTO_POLICY_OVERRIDES_JSON= # SECTION_PHOTO_POLICY_DATA_DRIVEN=true # SECTION_PHOTO_POLICY_MIN_EXAMPLES=3 # Fraction of uploads (where the section appears) that must contain a section image (1.0 = all) # SECTION_PHOTO_POLICY_TENANT_CONSENSUS_RATIO=1.0 # ── Security ───────────────────────────────────────────────────────────────── TENANT_SECRET_KEY=change-me-in-production DEV_MODE=true # CORS: comma-separated list of allowed origins. Default ["*"] (open). # In production set to your frontend URL, e.g.: ALLOWED_ORIGINS=["https://app.example.com"] # ALLOWED_ORIGINS=["*"]