ma-rag / DEPLOY.md
DannyTeo
Drop Fly.io deploy path; document HF Spaces as Option 2
8e2022e
|
Raw
History Blame Contribute Delete
5.82 kB

Deploying the Multi-Agent RAG Web App

This app is a single FastAPI process that serves both the API and the frontend. Everything ships as one Docker image, so it runs the same way on any platform.

What's in the image

  • Python 3.12 + all deps from backend/requirements.txt
  • The embedding model (sentence-transformers/all-mpnet-base-v2) pre-baked
  • Your data/source/ files (re-indexed on first boot)
  • The static frontend under /

Persistent state lives in a single directory: /home/user/app/data/chroma — mount a volume there so the vector DB survives redeploys. (The path is baked into the image by the Dockerfile; override it with the CHROMA_DB_PATH env var if you prefer a different mount point.)

Required runtime secrets

Env var Required Notes
GROQ_API_KEY yes gsk_... from https://console.groq.com/keys
GROQ_MODEL no defaults to openai/gpt-oss-120b
CORS_ORIGINS no comma-separated origins; * for open
CHROMA_DB_PATH no image default: /home/user/app/data/chroma

Minimum recommended VM: 1 GB RAM, 1 vCPU. The embedding model alone is ~420 MB resident.


Option 1 — Local / any VPS with Docker Compose

Simplest path. Works on a $4 DigitalOcean droplet, Hetzner, EC2, your Pi, etc.

# 1. On the server
git clone <your-repo> && cd Langchain
cp .env.example .env
# edit .env and set GROQ_API_KEY=gsk_...

# 2. Build + run
docker compose up -d --build

# 3. First-time: ingest the Dell docs into Chroma
curl -X POST http://localhost:8000/api/ingest

# 4. Verify
curl http://localhost:8000/api/health

Put Caddy or Nginx + certbot in front for HTTPS and your own domain.

Minimal Caddy (/etc/caddy/Caddyfile):

yourdomain.com {
    reverse_proxy localhost:8000
}

Option 2 — Hugging Face Spaces (free, zero-ops)

The repo's top-level README.md has HF Spaces frontmatter, so pushing this repo to a Space builds it as a Docker Space on port 8000.

# 1. Create an empty Docker Space at https://huggingface.co/new-space
#    (SDK: Docker, Hardware: CPU basic is enough)
# 2. In the Space's Settings → Variables and secrets:
#      Secret: GROQ_API_KEY = gsk_...
# 3. Push the code:
HF_USER=your_hf_username \
HF_SPACE=your_space_name \
HF_TOKEN=hf_your_write_token \
  ./scripts/push-to-hf.sh

Notes:

  • First build is ~5–8 minutes (it pre-downloads the embedding model).
  • Auto-ingest runs on the first request after boot (~30 s).
  • Spaces do not support persistent volumes on the free tier, so Chroma rebuilds from data/source/ each cold start. This is fine because the corpus is small and re-ingest is fast.
  • Subsequent deploys are just git push hf HEAD:main.

Option 3 — Google Cloud Run (pay-per-request, generous free tier)

Good fit because traffic is bursty and Cloud Run bills per request. Caveat: Cloud Run's local filesystem is ephemeral, so you need a mounted volume for Chroma. Use a second-gen service + a Cloud Storage FUSE mount or switch Chroma to a hosted vector DB (Pinecone, Qdrant Cloud, etc.).

Simplest version (ephemeral Chroma, re-ingests on cold start — fine for demos):

gcloud auth login
gcloud config set project YOUR_PROJECT

# build + push
gcloud builds submit --tag gcr.io/YOUR_PROJECT/langgraph-rag

# deploy
gcloud run deploy langgraph-rag \
  --image gcr.io/YOUR_PROJECT/langgraph-rag \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated \
  --memory 2Gi \
  --cpu 2 \
  --concurrency 10 \
  --timeout 300 \
  --min-instances 0 \
  --max-instances 3 \
  --set-env-vars GROQ_MODEL=openai/gpt-oss-120b \
  --set-secrets GROQ_API_KEY=GROQ_API_KEY:latest

For persistent Chroma on Cloud Run, either (a) add a GCS volume mount (--add-volume + --add-volume-mount) pointing at /home/user/app/data/chroma, or (b) swap Chroma for a managed vector DB.


Option 4 — Render / Railway

Both give you a managed container host with a UI instead of a CLI.

Render

  1. New -> Web Service -> connect your repo
  2. Runtime: Docker
  3. Instance type: Standard (2 GB) — the free 512 MB tier will OOM
  4. Add a Disk: mount path /home/user/app/data/chroma, size 1 GB
  5. Env vars: GROQ_API_KEY=gsk_...
  6. Health check path: /api/health

Railway

  1. New Project -> Deploy from GitHub -> pick this repo
  2. Railway autodetects the Dockerfile
  3. Variables: GROQ_API_KEY=gsk_...
  4. Add a Volume mounted at /home/user/app/data/chroma
  5. Hit the generated *.up.railway.app URL

Post-deploy checklist

  • GET /api/health returns {"status":"ok","has_api_key":"yes"}
  • POST /api/ingest returns non-zero chunk counts for each collection
  • Chat UI at / answers a Dell question and shows the debug trace
  • HTTPS is enforced (platform-provided or Caddy/Nginx)
  • GROQ_API_KEY is stored in platform secrets, not in a committed .env
  • CORS_ORIGINS is set to your real domain(s) instead of *
  • Volume backup for /home/user/app/data/chroma if the content matters

Scaling notes

  • Keep 1 worker per process. The embedding model is loaded once per process (~420 MB); 4 workers = ~1.7 GB just for model weights.
  • To go beyond ~10 concurrent users, scale horizontally (more instances) with a shared vector DB — Chroma's local file backend is single-writer.
  • For heavier loads swap Chroma for Qdrant / Pinecone / Weaviate and point CHROMA_DB_PATH logic at the managed DB instead (requires code changes in backend/app/ingest.py + backend/app/graph.py).