Anti-Hallucination / scripts /deploy_hf_space.sh
MHRDYN7's picture
Deploy Anti-Hallucination Chat
cea2150 verified
Raw
History Blame Contribute Delete
5.29 kB
#!/usr/bin/env bash
# Deploy Anti-Hallucination Chat to a Hugging Face Docker Space.
#
# Required:
# HF_TOKEN Write-scoped token from https://huggingface.co/settings/tokens
# GOOGLE_API_KEY Gemini API key (stored as a Space *secret*, never uploaded)
#
# Optional:
# SPACE_ID e.g. your-user/anti-hallucination-chat
# default: value in .hf-space-id
# SPACE_PRIVATE set to 1 for a private Space (default: public)
# SKIP_SECRET set to 1 to skip setting GOOGLE_API_KEY on the Space
#
# Usage (from repo root or this directory):
# export HF_TOKEN=hf_...
# export GOOGLE_API_KEY=...
# bash scripts/deploy_hf_space.sh
# # or:
# SPACE_ID=myuser/anti-hallucination-chat bash scripts/deploy_hf_space.sh
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
TARGET_FILE="$ROOT/.hf-space-id"
if [[ -z "${HF_TOKEN:-}" ]]; then
echo "error: HF_TOKEN is not set" >&2
echo " Create a write token at https://huggingface.co/settings/tokens" >&2
echo " then: export HF_TOKEN=hf_..." >&2
exit 1
fi
export HF_TOKEN
export HUGGING_FACE_HUB_TOKEN="${HUGGING_FACE_HUB_TOKEN:-$HF_TOKEN}"
HF=(uv run --with "huggingface_hub>=0.30" hf)
echo "==> Checking Hugging Face auth"
WHOAMI="$("${HF[@]}" auth whoami --format json 2>/dev/null || "${HF[@]}" auth whoami || true)"
if [[ -z "$WHOAMI" || "$WHOAMI" == *"Not logged in"* || "$WHOAMI" == *"Error"* ]]; then
echo "error: HF auth failed. Check HF_TOKEN (needs write scope)." >&2
exit 1
fi
echo "$WHOAMI"
if [[ -z "${SPACE_ID:-}" && -f "$TARGET_FILE" ]]; then
SPACE_ID="$(tr -d '[:space:]' < "$TARGET_FILE")"
fi
if [[ -z "${SPACE_ID:-}" ]]; then
USER_NAME="$(
printf '%s\n' "$WHOAMI" | python3 -c '
import json, re, sys
raw = sys.stdin.read().strip()
try:
data = json.loads(raw)
print(
data.get("name")
or data.get("user")
or data.get("fullname")
or data.get("fullnameName")
or ""
)
except Exception:
m = re.search(r"(?:name|user|fullname)[\"'\''\\s:]+([A-Za-z0-9_-]+)", raw, re.I)
print(m.group(1) if m else "")
'
)"
if [[ -z "$USER_NAME" ]]; then
echo "error: could not resolve HF username; set SPACE_ID=user/space-name" >&2
exit 1
fi
SPACE_ID="${USER_NAME}/anti-hallucination-chat"
fi
if [[ ! "$SPACE_ID" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then
echo "error: invalid SPACE_ID '$SPACE_ID' (expected namespace/name)" >&2
exit 1
fi
echo "==> Target Space: $SPACE_ID"
echo "==> Exporting requirements.txt"
if command -v uv >/dev/null 2>&1; then
uv export --no-hashes --no-dev -o requirements.txt
else
echo "warning: uv not found; using existing requirements.txt" >&2
fi
VISIBILITY=(--public)
if [[ "${SPACE_PRIVATE:-0}" == "1" ]]; then
VISIBILITY=(--private)
fi
if "${HF[@]}" spaces info "$SPACE_ID" --format json >/dev/null 2>&1; then
echo "==> Updating existing Docker Space"
else
echo "==> Creating Docker Space (exist-ok)"
"${HF[@]}" repos create "$SPACE_ID" \
--type space \
--space-sdk docker \
"${VISIBILITY[@]}" \
--exist-ok
fi
echo "==> Uploading app (secrets and .env excluded)"
"${HF[@]}" upload "$SPACE_ID" "$ROOT" . \
--type space \
--commit-message "Deploy Anti-Hallucination Chat" \
--exclude ".env" \
--exclude ".env.*" \
--exclude ".venv/**" \
--exclude "**/.venv/**" \
--exclude ".cursor/**" \
--exclude "**/.cursor/**" \
--exclude ".git/**" \
--exclude "**/__pycache__/**" \
--exclude "tests/**" \
--exclude "**/*.pyc" \
--exclude "*.tex" \
--exclude "plan.md" \
--exclude "benchmark_*.py" \
--exclude "uv.lock" \
--exclude ".python-version"
if [[ "${SKIP_SECRET:-0}" != "1" ]]; then
if [[ -z "${GOOGLE_API_KEY:-}" ]]; then
echo "warning: GOOGLE_API_KEY not set — Space will build but chat will error until you add the secret:" >&2
echo " hf spaces secrets add $SPACE_ID --secrets GOOGLE_API_KEY=YOUR_KEY" >&2
else
echo "==> Setting GOOGLE_API_KEY Space secret"
"${HF[@]}" spaces secrets add "$SPACE_ID" \
--secrets "GOOGLE_API_KEY=${GOOGLE_API_KEY}"
fi
fi
# Optional non-secret model overrides (visible in Space settings)
if [[ -n "${CHAT_MODEL:-}" || -n "${AUDIT_MODEL:-}" || -n "${SEARCH_MODEL:-}" ]]; then
echo "==> Setting optional model env vars on the Space"
ENV_ARGS=()
[[ -n "${CHAT_MODEL:-}" ]] && ENV_ARGS+=(--env "CHAT_MODEL=${CHAT_MODEL}")
[[ -n "${AUDIT_MODEL:-}" ]] && ENV_ARGS+=(--env "AUDIT_MODEL=${AUDIT_MODEL}")
[[ -n "${SEARCH_MODEL:-}" ]] && ENV_ARGS+=(--env "SEARCH_MODEL=${SEARCH_MODEL}")
# Newer CLIs: hf spaces env / repos create --env; fall back to secrets-free note
if "${HF[@]}" spaces --help 2>/dev/null | grep -q "env"; then
"${HF[@]}" spaces env add "$SPACE_ID" "${ENV_ARGS[@]}" 2>/dev/null \
|| echo "note: set CHAT_MODEL/AUDIT_MODEL/SEARCH_MODEL in Space Settings → Variables" >&2
else
echo "note: set model overrides in Space Settings → Variables if desired" >&2
fi
fi
echo
echo "Deployed: https://huggingface.co/spaces/${SPACE_ID}"
echo "Build logs: https://huggingface.co/spaces/${SPACE_ID}/logs"
echo
echo "If the Space is asleep or still building, wait a minute then open the URL."
echo "Free Docker Spaces may require HF Pro: https://huggingface.co/pro"