Spaces:
Sleeping
Sleeping
| version: "3.9" | |
| # ── Report Genius AI — Production Stack ────────────────────────────────────── | |
| # | |
| # Services: | |
| # api — FastAPI + Uvicorn (FAISS by default; optional Qdrant for async pipeline) | |
| # qdrant — Optional vector DB when VECTORSTORE_BACKEND=qdrant | |
| # temporal — Optional durable workflow server (ENABLE_TEMPORAL_WORKFLOW=true) | |
| # temporal-worker — Runs worker.py when Temporal is enabled | |
| # | |
| # Quick start: | |
| # cp .env.example .env # set OPENAI_API_KEY and TENANT_SECRET_KEY | |
| # docker compose up --build -d | |
| # open http://localhost:8000 | |
| # | |
| # To use PostgreSQL instead of SQLite, set DATABASE_URL in .env: | |
| # DATABASE_URL=postgresql+asyncpg://user:pass@postgres:5432/reportgenius | |
| # | |
| # Phase 2 + 3 (scale): | |
| # SCALE_OPTIMIZATION_PROFILE=true REDIS_URL=redis://redis:6379/0 \ | |
| # docker compose --profile redis --profile jobs up -d | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| services: | |
| redis: | |
| image: redis:7-alpine | |
| container_name: report_genius_redis | |
| restart: unless-stopped | |
| ports: | |
| - "6379:6379" | |
| profiles: | |
| - redis | |
| jobs-worker: | |
| build: | |
| context: . | |
| dockerfile: Dockerfile | |
| target: production | |
| image: report-genius-ai:latest | |
| container_name: report_genius_jobs_worker | |
| restart: unless-stopped | |
| command: ["python", "jobs_worker.py"] | |
| environment: | |
| OPENAI_API_KEY: "${OPENAI_API_KEY}" | |
| TENANT_SECRET_KEY: "${TENANT_SECRET_KEY:-change-me-in-production}" | |
| DATABASE_URL: "${DATABASE_URL:-sqlite+aiosqlite:////data/dev.db}" | |
| FAISS_INDEX_PATH: "/data/faiss_index" | |
| UPLOAD_DIR: "/mnt/data/uploads" | |
| CACHE_DIR: "/tmp/section_cache" | |
| REDIS_URL: "${REDIS_URL:-redis://redis:6379/0}" | |
| ENABLE_JOB_QUEUE: "true" | |
| SCALE_OPTIMIZATION_PROFILE: "${SCALE_OPTIMIZATION_PROFILE:-true}" | |
| ENABLE_ASYNC_PIPELINE: "${ENABLE_ASYNC_PIPELINE:-false}" | |
| ENABLE_SPECULATIVE_EXECUTOR: "${ENABLE_SPECULATIVE_EXECUTOR:-false}" | |
| ENABLE_PROMPT_CACHING: "${ENABLE_PROMPT_CACHING:-false}" | |
| VECTORSTORE_BACKEND: "${VECTORSTORE_BACKEND:-faiss}" | |
| QDRANT_URL: "${QDRANT_URL:-http://qdrant:6333}" | |
| GENERATION_STALE_SWEEP_SECONDS: "${GENERATION_STALE_SWEEP_SECONDS:-120}" | |
| GENERATION_TIMEOUT_SECONDS: "${GENERATION_TIMEOUT_SECONDS:-3600}" | |
| volumes: | |
| - uploads:/mnt/data/uploads | |
| - section_cache:/tmp/section_cache | |
| - db_data:/data | |
| - faiss_index:/data/faiss_index | |
| depends_on: | |
| redis: | |
| condition: service_started | |
| profiles: | |
| - jobs | |
| qdrant: | |
| image: qdrant/qdrant:v1.12.5 | |
| container_name: report_genius_qdrant | |
| restart: unless-stopped | |
| ports: | |
| - "6333:6333" | |
| volumes: | |
| - qdrant_data:/qdrant/storage | |
| profiles: | |
| - qdrant | |
| api: | |
| build: | |
| context: . | |
| dockerfile: Dockerfile | |
| target: production | |
| image: report-genius-ai:latest | |
| container_name: report_genius_api | |
| restart: unless-stopped | |
| ports: | |
| - "8000:8000" | |
| environment: | |
| # Pin PORT=8000 so the container's CMD listens on 8000 and the existing | |
| # `localhost:8000` URL keeps working. The Dockerfile defaults to 7860 | |
| # (Hugging Face Spaces convention) when this env var is absent. | |
| PORT: "8000" | |
| OPENAI_API_KEY: "${OPENAI_API_KEY}" | |
| TENANT_SECRET_KEY: "${TENANT_SECRET_KEY:-change-me-in-production}" | |
| DATABASE_URL: "${DATABASE_URL:-sqlite+aiosqlite:////data/dev.db}" | |
| FAISS_INDEX_PATH: "/data/faiss_index" | |
| UPLOAD_DIR: "/mnt/data/uploads" | |
| CACHE_DIR: "/tmp/section_cache" | |
| MAX_CONTEXT_TOKENS: "${MAX_CONTEXT_TOKENS:-400}" | |
| MAX_OUTPUT_TOKENS: "${MAX_OUTPUT_TOKENS:-300}" | |
| RETRIEVAL_TOP_K: "${RETRIEVAL_TOP_K:-10}" | |
| RERANK_TOP_N: "${RERANK_TOP_N:-3}" | |
| MAX_CONCURRENT_INGESTS: "${MAX_CONCURRENT_INGESTS:-4}" | |
| RATE_LIMIT_GENERATE_RPM: "${RATE_LIMIT_GENERATE_RPM:-20}" | |
| RATE_LIMIT_READ_RPM: "${RATE_LIMIT_READ_RPM:-120}" | |
| DEV_MODE: "false" | |
| SCALE_OPTIMIZATION_PROFILE: "${SCALE_OPTIMIZATION_PROFILE:-false}" | |
| ENABLE_ASYNC_PIPELINE: "${ENABLE_ASYNC_PIPELINE:-false}" | |
| ENABLE_SPECULATIVE_EXECUTOR: "${ENABLE_SPECULATIVE_EXECUTOR:-false}" | |
| ENABLE_PROMPT_CACHING: "${ENABLE_PROMPT_CACHING:-false}" | |
| ENABLE_TEMPORAL_WORKFLOW: "${ENABLE_TEMPORAL_WORKFLOW:-false}" | |
| ENABLE_HYBRID_RETRIEVAL: "${ENABLE_HYBRID_RETRIEVAL:-true}" | |
| SEMANTIC_CACHE_ENABLED: "${SEMANTIC_CACHE_ENABLED:-true}" | |
| AGENTIC_INSPECTOR_WHEN_NOTES_ONLY: "${AGENTIC_INSPECTOR_WHEN_NOTES_ONLY:-false}" | |
| NOTES_ONLY_GENERATION: "${NOTES_ONLY_GENERATION:-true}" | |
| GENERATION_TIMEOUT_SECONDS: "${GENERATION_TIMEOUT_SECONDS:-3600}" | |
| GENERATION_STALE_SWEEP_SECONDS: "${GENERATION_STALE_SWEEP_SECONDS:-120}" | |
| TEMPORAL_HOST: "${TEMPORAL_HOST:-temporal:7233}" | |
| TEMPORAL_NAMESPACE: "${TEMPORAL_NAMESPACE:-default}" | |
| VECTORSTORE_BACKEND: "${VECTORSTORE_BACKEND:-faiss}" | |
| QDRANT_URL: "${QDRANT_URL:-http://qdrant:6333}" | |
| MAX_CONCURRENT_LLM_CALLS: "${MAX_CONCURRENT_LLM_CALLS:-10}" | |
| REDIS_URL: "${REDIS_URL:-}" | |
| ENABLE_JOB_QUEUE: "${ENABLE_JOB_QUEUE:-false}" | |
| volumes: | |
| - uploads:/mnt/data/uploads | |
| - section_cache:/tmp/section_cache | |
| - db_data:/data | |
| - faiss_index:/data/faiss_index | |
| depends_on: | |
| qdrant: | |
| condition: service_started | |
| required: false | |
| temporal: | |
| condition: service_started | |
| required: false | |
| healthcheck: | |
| test: ["CMD", "curl", "-fsS", "http://localhost:8000/health"] | |
| interval: 30s | |
| timeout: 10s | |
| retries: 3 | |
| start_period: 20s | |
| temporal: | |
| image: temporalio/auto-setup:1.25.2 | |
| container_name: report_genius_temporal | |
| restart: unless-stopped | |
| ports: | |
| - "7233:7233" | |
| environment: | |
| - DB=sqlite | |
| profiles: | |
| - temporal | |
| temporal-worker: | |
| build: | |
| context: . | |
| dockerfile: Dockerfile | |
| target: production | |
| image: report-genius-ai:latest | |
| container_name: report_genius_temporal_worker | |
| restart: unless-stopped | |
| command: ["python", "worker.py"] | |
| environment: | |
| OPENAI_API_KEY: "${OPENAI_API_KEY}" | |
| TENANT_SECRET_KEY: "${TENANT_SECRET_KEY:-change-me-in-production}" | |
| DATABASE_URL: "${DATABASE_URL:-sqlite+aiosqlite:////data/dev.db}" | |
| FAISS_INDEX_PATH: "/data/faiss_index" | |
| UPLOAD_DIR: "/mnt/data/uploads" | |
| CACHE_DIR: "/tmp/section_cache" | |
| ENABLE_TEMPORAL_WORKFLOW: "true" | |
| ENABLE_ASYNC_PIPELINE: "${ENABLE_ASYNC_PIPELINE:-false}" | |
| ENABLE_SPECULATIVE_EXECUTOR: "${ENABLE_SPECULATIVE_EXECUTOR:-false}" | |
| ENABLE_PROMPT_CACHING: "${ENABLE_PROMPT_CACHING:-false}" | |
| VECTORSTORE_BACKEND: "${VECTORSTORE_BACKEND:-faiss}" | |
| QDRANT_URL: "${QDRANT_URL:-http://qdrant:6333}" | |
| ENABLE_HYBRID_RETRIEVAL: "${ENABLE_HYBRID_RETRIEVAL:-true}" | |
| SEMANTIC_CACHE_ENABLED: "${SEMANTIC_CACHE_ENABLED:-true}" | |
| AGENTIC_INSPECTOR_WHEN_NOTES_ONLY: "${AGENTIC_INSPECTOR_WHEN_NOTES_ONLY:-false}" | |
| NOTES_ONLY_GENERATION: "${NOTES_ONLY_GENERATION:-true}" | |
| GENERATION_TIMEOUT_SECONDS: "${GENERATION_TIMEOUT_SECONDS:-3600}" | |
| GENERATION_STALE_SWEEP_SECONDS: "${GENERATION_STALE_SWEEP_SECONDS:-120}" | |
| TEMPORAL_HOST: "${TEMPORAL_HOST:-temporal:7233}" | |
| TEMPORAL_NAMESPACE: "${TEMPORAL_NAMESPACE:-default}" | |
| TEMPORAL_TASK_QUEUE: "${TEMPORAL_TASK_QUEUE:-reports}" | |
| MAX_CONCURRENT_LLM_CALLS: "${MAX_CONCURRENT_LLM_CALLS:-10}" | |
| volumes: | |
| - uploads:/mnt/data/uploads | |
| - section_cache:/tmp/section_cache | |
| - db_data:/data | |
| - faiss_index:/data/faiss_index | |
| depends_on: | |
| temporal: | |
| condition: service_started | |
| profiles: | |
| - temporal | |
| volumes: | |
| qdrant_data: | |
| driver: local | |
| uploads: | |
| driver: local | |
| section_cache: | |
| driver: local | |
| db_data: | |
| driver: local | |
| faiss_index: | |
| driver: local | |