document_agent / docs /DEPLOY.md
Jai-rathore29's picture
Deploy: DocAgent backend (deterministic date-anomaly fix)
f65e025
|
Raw
History Blame Contribute Delete
5.55 kB

Deployment guide

Architecture: frontend β†’ Vercel, backend β†’ a Docker container host (Render blueprint included). The two talk over HTTPS; the frontend proxies /api/* to the backend via a Next.js rewrite, so the browser only ever sees the Vercel origin.

  Browser ──> Vercel (Next.js)  ──/api/* rewrite──>  Backend container (FastAPI + Docling)
                                                      └── persistent disk /data
                                                      └── models baked into image

Why the backend can't be serverless: it bundles Docling + (CPU) torch + ~850 MB of layout/table/OCR models and needs real RAM/disk. Plan for 2 GB minimum, 4 GB recommended.


1. Backend β†’ Render (recommended)

The image bakes the models in, runs as non-root, exposes a health check, and binds $PORT. Everything is described in render.yaml.

  1. Push this repo to GitHub (Render deploys from Git):
    git remote add origin https://github.com/<you>/document-agent.git
    git push -u origin main
    
  2. In the Render dashboard β†’ New β†’ Blueprint, select the repo. Render reads render.yaml and provisions a Docker web service + a 10 GB disk at /data.
  3. When prompted, set the secret env vars:
    • OPENAI_API_KEY β€” your key
    • GEMINI_API_KEY β€” optional (leave blank to disable Gemini)
  4. After the first deploy, note the URL (e.g. https://document-agent-backend.onrender.com) and verify: GET <url>/api/health β†’ {"status":"ok", ...}.
  5. Set CORS_ORIGINS to your Vercel domain (see step 2 below) and redeploy.

First build is slow (downloads torch + models). Subsequent deploys reuse layers.

Free option β€” Hugging Face Spaces (no card required)

Render's free plan is 512 MB RAM with no disk and can't run this image. HF Spaces free CPU tier gives 16 GB RAM and runs Docker, so it fits β€” the only loss is persistence (free Spaces have no disk, so uploads/DB reset on restart/rebuild).

This repo ships an HF-ready root Dockerfile (builds the backend with the repo root as context, runs as UID 1000) and the HF config in the README.md frontmatter (sdk: docker, app_port: 8000).

  1. Create a free account at https://huggingface.co, then New β†’ Space:
    • SDK: Docker (blank template), name e.g. document-agent, visibility your choice.
  2. Push this repo to the Space's git remote:
    git remote add space https://huggingface.co/spaces/<hf-user>/document-agent
    git push space main          # auth: HF username + an HF access token as password
    
    (Create a write token at https://huggingface.co/settings/tokens.)
  3. In the Space: Settings β†’ Variables and secrets, add as secrets:
    • OPENAI_API_KEY (freshly rotated) and/or GEMINI_API_KEY
    • DEFAULT_LLM_PROVIDER (openai or gemini), ENABLE_OCR (true/false)
  4. The Space builds (slow first time: torch + ~850 MB models). When live, the URL is https://<hf-user>-document-agent.hf.space; verify GET <url>/api/health.
  5. Use that URL as NEXT_PUBLIC_API_BASE on Vercel (step 2 below).

Tip: if free RAM is tight on large scans, set ENABLE_OCR=false to cut memory.

Other alternatives

  • Fly.io: fly launch from ./backend (it detects the Dockerfile), add a volume (fly volumes create data) mounted at /data, set secrets with fly secrets set.
  • Railway: new service from the Dockerfile, add a volume at /data, set the env vars.

2. Frontend β†’ Vercel

The frontend is already env-driven β€” it needs exactly one variable pointing at the backend.

cd frontend
vercel            # first run: link/create the project
# set the backend URL for all environments:
vercel env add NEXT_PUBLIC_API_BASE
#   value: https://document-agent-backend.onrender.com   (no trailing slash)
vercel --prod     # deploy

NEXT_PUBLIC_API_BASE drives the /api/:path* rewrite in next.config.mjs, so uploads, page images, exports and the chat stream all flow through the same origin β€” no CORS needed in the common case.

Streaming note: chat uses SSE through the Vercel rewrite. If a host buffers the stream, switch to direct calls by setting BASE = process.env.NEXT_PUBLIC_API_BASE in frontend/lib/api.ts and make sure CORS_ORIGINS on the backend lists the Vercel domain.


3. Verify locally first (optional but recommended)

Build and run the real production image before shipping:

docker compose up --build
# backend: http://localhost:8000/api/health

docker-compose.yml mounts a named volume at /data and reads backend/.env, so it mirrors production (persistent uploads + sqlite + rendered pages).


Operational notes

  • Persistence: /data holds uploads, the SQLite DB, the numpy vector store and rendered page images. Keep it on a mounted disk/volume β€” without one, data resets on every deploy.
  • Models: baked into the image (not in /data), so they survive redeploys with no re-download.
  • Secrets: only ever via host env vars. backend/.env is git-ignored.
  • Scaling: state lives on local disk + SQLite, so run a single instance. To scale horizontally, move the DB to Postgres and the vector store to pgvector (services/vectorstore.py is a drop-in seam) and uploads to object storage.
  • Cost guard: the backend holds your LLM key behind a public URL. Consider adding auth or a rate limit before sharing widely.