StormShadow308 Cursor commited on
Commit
2e3ecc8
Β·
1 Parent(s): c893230

Disable LLM RAG sanitisation by default on HF Spaces to fix slow ingestion.

Browse files

One OpenAI call per PDF page was taking 330s+ per document on CPU Spaces; style_corpus uploads still force scrubbing.

Co-authored-by: Cursor <cursoragent@cursor.com>

Files changed (5) hide show
  1. .env.example +2 -0
  2. DEPLOY_HF_SPACES.md +2 -0
  3. Dockerfile +2 -0
  4. app/config.py +9 -1
  5. app/main.py +8 -0
.env.example CHANGED
@@ -61,6 +61,8 @@ OPENAI_API_KEY=sk-replace-me
61
 
62
  # ── RAG upload sanitisation (strip PII before vector indexing; on-disk files unchanged) ─
63
  # ENABLE_RAG_UPLOAD_SANITISATION=true
 
 
64
  # RAG_SANITISATION_SKIP_KB_TENANT=true
65
  # RAG_SANITISATION_CHUNK_CHARS=12000
66
  # RAG_SANITISATION_MAX_OUTPUT_TOKENS=4096
 
61
 
62
  # ── RAG upload sanitisation (strip PII before vector indexing; on-disk files unchanged) ─
63
  # ENABLE_RAG_UPLOAD_SANITISATION=true
64
+ # On Hugging Face Spaces this defaults to false (one OpenAI call per PDF page β†’ ~5+ min/doc).
65
+ # style_corpus uploads still force sanitisation when enabled in code.
66
  # RAG_SANITISATION_SKIP_KB_TENANT=true
67
  # RAG_SANITISATION_CHUNK_CHARS=12000
68
  # RAG_SANITISATION_MAX_OUTPUT_TOKENS=4096
DEPLOY_HF_SPACES.md CHANGED
@@ -96,6 +96,8 @@ Optional β€” override Dockerfile defaults if you want different behaviour:
96
  | Type | Name | Default | Notes |
97
  |---|---|---|---|
98
  | Variable | `KNOWLEDGE_BASE_ENABLED` | `false` | Set `true` *only* if you also bake KB PDFs into the image. The startup guard logs a `WARNING` when this is `false` in production β€” that's expected on the HF free tier (KB source PDFs are gitignored), so the warning is informational. |
 
 
99
  | Variable | `INSPECTOR_TOOL_AGENT` | `true` | Disable to force the legacy fixed pipeline. |
100
  | Variable | `UVICORN_WORKERS` | `1` | Correct for the 1-vCPU HF Spaces free tier. On bigger hosts, set to `(2 * CPU cores) + 1`. |
101
  | Variable | `RATE_LIMIT_GENERATE_RPM` | `20` | Per-tenant /generate rate limit. |
 
96
  | Type | Name | Default | Notes |
97
  |---|---|---|---|
98
  | Variable | `KNOWLEDGE_BASE_ENABLED` | `false` | Set `true` *only* if you also bake KB PDFs into the image. The startup guard logs a `WARNING` when this is `false` in production β€” that's expected on the HF free tier (KB source PDFs are gitignored), so the warning is informational. |
99
+ | Variable | `ENABLE_RAG_UPLOAD_SANITISATION` | `false` | **Keep `false` on HF.** When `true`, every PDF page gets an OpenAI scrub call before indexing (~5+ min per building survey). `style_corpus` uploads still sanitise even when this is `false`. |
100
+ | Variable | `MAX_CONCURRENT_INGESTS` | `2` | Lower than local dev (4) to reduce CPU/RAM pressure on the free tier. |
101
  | Variable | `INSPECTOR_TOOL_AGENT` | `true` | Disable to force the legacy fixed pipeline. |
102
  | Variable | `UVICORN_WORKERS` | `1` | Correct for the 1-vCPU HF Spaces free tier. On bigger hosts, set to `(2 * CPU cores) + 1`. |
103
  | Variable | `RATE_LIMIT_GENERATE_RPM` | `20` | Per-tenant /generate rate limit. |
Dockerfile CHANGED
@@ -101,6 +101,8 @@ ENV PORT=7860 \
101
  UVICORN_WORKERS=1 \
102
  DEV_MODE=false \
103
  KNOWLEDGE_BASE_ENABLED=false \
 
 
104
  DATABASE_URL=sqlite+aiosqlite:////home/user/.report_genius/dev.db \
105
  FAISS_INDEX_PATH=/home/user/.report_genius/faiss_index \
106
  UPLOAD_DIR=/home/user/.report_genius/uploads \
 
101
  UVICORN_WORKERS=1 \
102
  DEV_MODE=false \
103
  KNOWLEDGE_BASE_ENABLED=false \
104
+ ENABLE_RAG_UPLOAD_SANITISATION=false \
105
+ MAX_CONCURRENT_INGESTS=2 \
106
  DATABASE_URL=sqlite+aiosqlite:////home/user/.report_genius/dev.db \
107
  FAISS_INDEX_PATH=/home/user/.report_genius/faiss_index \
108
  UPLOAD_DIR=/home/user/.report_genius/uploads \
app/config.py CHANGED
@@ -672,12 +672,20 @@ class Settings(BaseSettings):
672
 
673
  @model_validator(mode="after")
674
  def _sync_openai_key_from_process_env(self) -> Self:
675
- """HF Space secrets inject OPENAI_API_KEY at runtime (not in the image)."""
676
  if not os.environ.get("SPACE_ID"):
677
  return self
678
  env_key = (os.environ.get("OPENAI_API_KEY") or "").strip()
679
  if env_key:
680
  self.openai_api_key = env_key
 
 
 
 
 
 
 
 
681
  return self
682
 
683
 
 
672
 
673
  @model_validator(mode="after")
674
  def _sync_openai_key_from_process_env(self) -> Self:
675
+ """HF Space runtime tweaks (secrets + sensible free-tier defaults)."""
676
  if not os.environ.get("SPACE_ID"):
677
  return self
678
  env_key = (os.environ.get("OPENAI_API_KEY") or "").strip()
679
  if env_key:
680
  self.openai_api_key = env_key
681
+ # RAG upload sanitisation runs one LLM call per PDF page before indexing.
682
+ # On HF CPU Spaces that turns a ~30s ingest into 5+ minutes per file.
683
+ # Opt in explicitly via ENABLE_RAG_UPLOAD_SANITISATION=true; style_corpus
684
+ # uploads still force sanitisation regardless of this flag.
685
+ if "ENABLE_RAG_UPLOAD_SANITISATION" not in os.environ:
686
+ self.enable_rag_upload_sanitisation = False
687
+ if "MAX_CONCURRENT_INGESTS" not in os.environ:
688
+ self.max_concurrent_ingests = min(int(self.max_concurrent_ingests), 2)
689
  return self
690
 
691
 
app/main.py CHANGED
@@ -259,6 +259,14 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
259
  except Exception as exc: # noqa: BLE001
260
  logger.warning("Redis configured but not reachable at startup: %s", exc)
261
 
 
 
 
 
 
 
 
 
262
  logger.info("Startup complete.")
263
  yield
264
  from app.redis_client import close_redis, redis_configured as _redis_cfg
 
259
  except Exception as exc: # noqa: BLE001
260
  logger.warning("Redis configured but not reachable at startup: %s", exc)
261
 
262
+ if os.environ.get("SPACE_ID"):
263
+ logger.info(
264
+ "HF Space ingest policy: rag_upload_sanitisation=%s max_concurrent_ingests=%d "
265
+ "(set ENABLE_RAG_UPLOAD_SANITISATION=true to opt into LLM scrub per PDF page)",
266
+ settings.enable_rag_upload_sanitisation,
267
+ int(settings.max_concurrent_ingests),
268
+ )
269
+
270
  logger.info("Startup complete.")
271
  yield
272
  from app.redis_client import close_redis, redis_configured as _redis_cfg