kirana-saathi / scripts /space_entrypoint.sh
yobro4619's picture
Kirana Saathi: MiniCPM-V-4.6 (OpenBMB) + guided-JSON agent
817c779 verified
Raw
History Blame Contribute Delete
3.8 kB
#!/usr/bin/env bash
# HF Space entrypoint. Works in two modes, auto-detected from KIRANA_LLM_BASE_URL:
# • Modal-primary (default for the flagship): the URL points at a remote Modal
# endpoint → we run ONLY Gradio + Whisper(STT) + Veena/MMS(TTS), calling Modal
# for the LLM. Needs just a T4.
# • Self-contained: the URL is local (or unset) → we ALSO download a MiniCPM-V-4.6
# GGUF and start a local llama-server sidecar. Needs an L4. (The live Space uses
# OpenBMB's hosted MiniCPM-V-4.6 API instead, so this branch is the opt-in path.)
# app.py:main() tolerates the LLM still warming up (dashboard shows server_up=false).
set -uo pipefail
cd "$(dirname "$0")/.."
# --- decide whether the LLM is local (we host it) or remote (Modal hosts it)
LLM_URL="${KIRANA_LLM_BASE_URL:-http://127.0.0.1:8080/v1}"
case "$LLM_URL" in
*127.0.0.1*|*localhost*|*0.0.0.0*) LOCAL_LLM=1 ;;
*) LOCAL_LLM=0 ;;
esac
echo "[entrypoint] LLM_URL=$LLM_URL LOCAL_LLM=$LOCAL_LLM"
# --- data dir: prefer persistent /data; fall back to $HOME if not attached.
if ! mkdir -p "${KIRANA_DATA_DIR:-/data}" 2>/dev/null; then
export KIRANA_DATA_DIR="${HOME}/data"; mkdir -p "$KIRANA_DATA_DIR"
fi
echo "[entrypoint] DATA_DIR=$KIRANA_DATA_DIR"
# --- CTranslate2 (faster-whisper) needs libcudnn/libcublas; point the loader at
# torch's bundled CUDA libs.
TORCH_LIB="$(uv run python -c 'import os,torch;print(os.path.join(os.path.dirname(torch.__file__),"lib"))' 2>/dev/null || true)"
export LD_LIBRARY_PATH="${TORCH_LIB}:${LD_LIBRARY_PATH:-}"
# --- install the curated demo DB shipped in the image (data/). Overwrites on every
# boot so the Space always starts from the exact submission state; falls back to
# seeding only if no DB was shipped. (Skips the copy when DATA_DIR is already ./data.)
if [ -f "data/inventory.db" ] && [ -f "data/transactions.db" ] \
&& [ "$(realpath data)" != "$(realpath "${KIRANA_DATA_DIR}")" ]; then
echo "[entrypoint] installing shipped demo DB into ${KIRANA_DATA_DIR}"
cp -f data/inventory.db data/transactions.db "${KIRANA_DATA_DIR}/"
elif [ ! -f "${KIRANA_DATA_DIR}/inventory.db" ]; then
echo "[entrypoint] seeding demo DB"; uv run python -m kirana.db --reset || true
fi
# --- local llama-server ONLY when we're hosting the LLM in-container. This is the
# optional self-host path; the live Space talks to OpenBMB's hosted MiniCPM-V-4.6
# API instead. Repo/filenames are env-overridable (defaults = the verified files
# from openbmb/MiniCPM-V-4.6-gguf: model uses "4_6", projector "mmproj-model-f16").
if [ "$LOCAL_LLM" = "1" ]; then
MODELS_DIR="${HOME}/app/models/minicpm"; mkdir -p "$MODELS_DIR"
LLM_REPO="${LLM_REPO:-openbmb/MiniCPM-V-4.6-gguf}"
LLM_FILE="${LLM_FILE:-MiniCPM-V-4_6-Q4_K_M.gguf}"
LLM_MMPROJ="${LLM_MMPROJ:-mmproj-model-f16.gguf}"
export KIRANA_LOCAL_GGUF="${MODELS_DIR}/${LLM_FILE}"
export KIRANA_LOCAL_MMPROJ="${MODELS_DIR}/${LLM_MMPROJ}"
LLM_REPO="$LLM_REPO" LLM_FILE="$LLM_FILE" LLM_MMPROJ="$LLM_MMPROJ" \
uv run python - <<'PY'
import os
from huggingface_hub import hf_hub_download
repo = os.environ["LLM_REPO"]
d = os.path.join(os.environ["HOME"], "app", "models", "minicpm")
for f in (os.environ["LLM_FILE"], os.environ["LLM_MMPROJ"]):
print("[models]", hf_hub_download(repo_id=repo, filename=f, local_dir=d))
PY
LLAMA="$(command -v llama-server || echo /app/llama-server)"
echo "[entrypoint] starting local llama-server: $LLAMA"
"$LLAMA" -m "$KIRANA_LOCAL_GGUF" --mmproj "$KIRANA_LOCAL_MMPROJ" \
--host 127.0.0.1 --port 8080 -c "${KIRANA_LLM_CTX:-8192}" -ngl 99 --jinja &
else
echo "[entrypoint] using remote LLM at $LLM_URL — not starting a local llama-server"
fi
# --- Gradio app (foreground; Whisper + Veena lazy-load on first use).
exec uv run python -m kirana.app