All checks were successful
Quality gates / quality (pull_request) Successful in 1m30s
151 lines
4.5 KiB
Bash
Executable File
151 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
LLAMA_CPP_COMMIT="${TIMMY_LLAMA_CPP_COMMIT:-6d05498314db1b57f81c271080018aa2d0b89be9}"
|
|
MODEL_SHA256="${TIMMY_MODEL_SHA256:-0cf76814555b8665149075b74ab6b5c1d428ea1d3d01c1918c12012e8d7c9f58}"
|
|
MMPROJ_SHA256="${TIMMY_MMPROJ_SHA256:-ae07ea1facd07dd3230c4483b63e8cda96c6944ad2481f33d531f79e892dd024}"
|
|
HOST="${TIMMY_MODEL_HOST:-127.0.0.1}"
|
|
PORT="${TIMMY_MODEL_PORT:-8080}"
|
|
ROOT="${TIMMY_SELFHOST_ROOT:-${XDG_DATA_HOME:-$HOME/.local/share}/timmy-selfhost}"
|
|
MODEL_DIR="$ROOT/models"
|
|
MODEL="$MODEL_DIR/SmolVLM2-2.2B-Instruct-Q4_K_M.gguf"
|
|
MMPROJ="$MODEL_DIR/mmproj-SmolVLM2-2.2B-Instruct-Q8_0.gguf"
|
|
SOURCE="$ROOT/llama.cpp"
|
|
BUILD="$SOURCE/build"
|
|
HF_BASE="https://huggingface.co/ggml-org/SmolVLM2-2.2B-Instruct-GGUF/resolve/main"
|
|
SERVER="$BUILD/bin/llama-server"
|
|
RUNTIME="$ROOT/run"
|
|
PIDFILE="$RUNTIME/llama-server.pid"
|
|
LOGFILE="$RUNTIME/llama-server.log"
|
|
|
|
verify_files() {
|
|
for file in "$MODEL" "$MMPROJ"; do
|
|
if [[ ! -f "$file" ]]; then
|
|
printf 'Missing required file: %s. Run %s install.\n' "$file" "$0" >&2
|
|
return 1
|
|
fi
|
|
done
|
|
printf '%s %s\n%s %s\n' "$MODEL_SHA256" "$MODEL" "$MMPROJ_SHA256" "$MMPROJ" | sha256sum --check --status
|
|
}
|
|
|
|
download_verified() {
|
|
local url="$1" target="$2" expected="$3" temporary="$2.download"
|
|
rm -f "$temporary"
|
|
curl --fail --location --retry 3 --output "$temporary" "$url"
|
|
printf '%s %s\n' "$expected" "$temporary" | sha256sum --check --status || {
|
|
rm -f "$temporary"
|
|
printf 'Downloaded file failed pinned SHA-256 verification: %s\n' "$target" >&2
|
|
return 1
|
|
}
|
|
mv "$temporary" "$target"
|
|
}
|
|
|
|
install_worker() {
|
|
command -v git >/dev/null
|
|
command -v cmake >/dev/null
|
|
command -v curl >/dev/null
|
|
mkdir -p "$ROOT" "$MODEL_DIR"
|
|
if [[ ! -d "$SOURCE/.git" ]]; then
|
|
git clone https://github.com/ggml-org/llama.cpp "$SOURCE"
|
|
fi
|
|
git -C "$SOURCE" fetch origin "$LLAMA_CPP_COMMIT"
|
|
git -C "$SOURCE" checkout --detach "$LLAMA_CPP_COMMIT"
|
|
cmake -S "$SOURCE" -B "$BUILD" -DCMAKE_BUILD_TYPE=Release -DLLAMA_CURL=OFF
|
|
cmake --build "$BUILD" --parallel "${TIMMY_BUILD_JOBS:-4}" --target llama-server
|
|
download_verified "$HF_BASE/SmolVLM2-2.2B-Instruct-Q4_K_M.gguf" "$MODEL" "$MODEL_SHA256"
|
|
download_verified "$HF_BASE/mmproj-SmolVLM2-2.2B-Instruct-Q8_0.gguf" "$MMPROJ" "$MMPROJ_SHA256"
|
|
verify_files
|
|
printf 'Pinned model files verified.\n'
|
|
}
|
|
|
|
health_worker() {
|
|
curl --fail --silent --show-error --retry 5 --retry-connrefused --retry-delay 1 --max-time 3 "http://$HOST:$PORT/v1/models" | grep -q 'SmolVLM2-2.2B-Instruct'
|
|
printf 'Self-hosted worker healthy at http://%s:%s/v1\n' "$HOST" "$PORT"
|
|
}
|
|
|
|
start_worker() {
|
|
verify_files
|
|
if [[ ! -x "$SERVER" ]]; then
|
|
printf 'Missing llama-server executable: %s. Run %s install.\n' "$SERVER" "$0" >&2
|
|
return 1
|
|
fi
|
|
mkdir -p "$RUNTIME"
|
|
if [[ -f "$PIDFILE" ]] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; then
|
|
health_worker
|
|
return
|
|
fi
|
|
rm -f "$PIDFILE"
|
|
nohup "$SERVER" \
|
|
--model "$MODEL" \
|
|
--mmproj "$MMPROJ" \
|
|
--alias SmolVLM2-2.2B-Instruct \
|
|
--host "$HOST" \
|
|
--port "$PORT" \
|
|
--ctx-size 4096 \
|
|
--parallel 1 \
|
|
--threads "${TIMMY_MODEL_THREADS:-4}" \
|
|
--no-webui >"$LOGFILE" 2>&1 &
|
|
printf '%s\n' "$!" > "$PIDFILE"
|
|
for _ in {1..30}; do
|
|
if health_worker >/dev/null 2>&1; then
|
|
printf 'Self-hosted worker started privately at http://%s:%s/v1\n' "$HOST" "$PORT"
|
|
return
|
|
fi
|
|
sleep 0.2
|
|
done
|
|
kill "$(cat "$PIDFILE")" 2>/dev/null || true
|
|
rm -f "$PIDFILE"
|
|
printf 'Worker did not become healthy; inspect %s\n' "$LOGFILE" >&2
|
|
return 1
|
|
}
|
|
|
|
stop_worker() {
|
|
if [[ ! -f "$PIDFILE" ]]; then
|
|
printf 'Self-hosted worker is not running.\n'
|
|
return
|
|
fi
|
|
local pid
|
|
pid="$(cat "$PIDFILE")"
|
|
kill "$pid" 2>/dev/null || true
|
|
for _ in {1..25}; do
|
|
if ! kill -0 "$pid" 2>/dev/null; then
|
|
rm -f "$PIDFILE"
|
|
printf 'Self-hosted worker stopped.\n'
|
|
return
|
|
fi
|
|
sleep 0.1
|
|
done
|
|
kill -9 "$pid" 2>/dev/null || true
|
|
rm -f "$PIDFILE"
|
|
printf 'Self-hosted worker stopped.\n'
|
|
}
|
|
|
|
case "${1:-}" in
|
|
receipt)
|
|
printf 'llama.cpp commit: %s\n' "$LLAMA_CPP_COMMIT"
|
|
printf 'SmolVLM2-2.2B-Instruct-Q4_K_M.gguf sha256: %s\n' "$MODEL_SHA256"
|
|
printf 'mmproj-SmolVLM2-2.2B-Instruct-Q8_0.gguf sha256: %s\n' "$MMPROJ_SHA256"
|
|
printf 'bind address: %s:%s\n' "$HOST" "$PORT"
|
|
;;
|
|
verify)
|
|
verify_files
|
|
printf 'Pinned model files verified.\n'
|
|
;;
|
|
install)
|
|
install_worker
|
|
;;
|
|
start)
|
|
start_worker
|
|
;;
|
|
health)
|
|
health_worker
|
|
;;
|
|
stop)
|
|
stop_worker
|
|
;;
|
|
*)
|
|
printf 'Usage: %s {install|start|health|stop|receipt|verify}\n' "$0" >&2
|
|
exit 64
|
|
;;
|
|
esac
|