auralynq-rag / deploy /huggingface /entrypoint.sh
MHamdan's picture
fix(api): run 2 uvicorn workers β€” a blocking LLM call in an async endpoint was freezing the single event loop (HTTP 000 outages)
9318680 verified
Raw
History Blame Contribute Delete
2.56 kB
#!/usr/bin/env bash
# Starts the API (loopback-only, background) and the Next.js web server
# (foreground, PID 1's direct child so it receives Space restart/stop signals
# correctly). Next.js proxies /api/* to the API process β€” see
# web/next.config.js and deploy/huggingface/Dockerfile.
set -euo pipefail
DATA_DIR="${AURALYNQ_DATA_DIR:-/data/auralynq}"
mkdir -p "$DATA_DIR"
# Local LLM server (Ollama) β€” self-contained, uses the GPU when the Space runs
# on GPU hardware and falls back to CPU otherwise. The model is baked into the
# image (OLLAMA_MODELS). If ollama isn't installed/serving, the app's provider
# resolution falls back to the local GGUF (slm) or extractive β€” never fatal.
if command -v ollama >/dev/null 2>&1; then
OLLAMA_HOST=127.0.0.1:11434 ollama serve &
OLLAMA_PID=$!
trap 'kill "$OLLAMA_PID" 2>/dev/null || true' EXIT INT TERM
echo "[entrypoint] waiting for ollama..."
for _ in $(seq 1 40); do
curl -fsS "http://127.0.0.1:11434/api/tags" >/dev/null 2>&1 && { echo "[entrypoint] ollama ready"; break; }
sleep 1
done
fi
# Demo mode: seed and index the public demo corpus on first boot only, so a
# Space restart doesn't re-index for no reason. Never touches an existing
# index. Safe to skip entirely if AURALYNQ_DEMO_MODE=false.
if [ "${AURALYNQ_DEMO_MODE:-false}" = "true" ] && [ ! -f "$DATA_DIR/index/last_ingested.json" ]; then
echo "[entrypoint] demo mode: seeding the public demo corpus (examples/demo_corpus/docs)"
mkdir -p "$DATA_DIR/corpus"
cp -r /app/examples/demo_corpus/docs/. "$DATA_DIR/corpus/"
python -m auralynq.cli index --input "$DATA_DIR/corpus" \
|| echo "[entrypoint] demo indexing failed; continuing without a pre-built index"
fi
# Multiple workers: the /query endpoints are async but the LLM call to Ollama is
# a blocking HTTP call, which would freeze a single event loop (and the health
# check / proxy) for the duration. Extra workers keep the API responsive when one
# is busy generating. Ollama is a shared external process, so the model is loaded
# once regardless of worker count.
python -m uvicorn auralynq.serving.app:app --host 127.0.0.1 --port 8000 \
--workers "${AURALYNQ_API_WORKERS:-2}" --timeout-keep-alive 75 &
API_PID=$!
trap 'kill "$API_PID" "${OLLAMA_PID:-}" 2>/dev/null || true' EXIT INT TERM
echo "[entrypoint] waiting for the API to become healthy..."
for _ in $(seq 1 30); do
if curl -fsS "http://127.0.0.1:8000/health" >/dev/null 2>&1; then
echo "[entrypoint] API is healthy"
break
fi
sleep 1
done
cd /app/web
exec node server.js