File size: 5,285 Bytes
f3793b5
 
 
 
 
 
 
 
 
cea2150
f3793b5
 
 
 
 
 
 
 
 
 
 
 
 
 
cea2150
f3793b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cea2150
 
 
 
f3793b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cea2150
 
 
 
 
f3793b5
 
 
 
 
 
 
 
 
 
 
 
 
 
cea2150
 
 
 
 
 
 
 
 
 
f3793b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/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"