90 lines
4.1 KiB
Bash
90 lines
4.1 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# =============================================================================
|
||
|
|
# install-nuc.sh
|
||
|
|
# Deploy Phi-4 Multimodal Q4_K_M to an Intel NUC (8 GB RAM, CPU-only)
|
||
|
|
# and register it with Ollama for use with OpenClaw.
|
||
|
|
#
|
||
|
|
# Usage:
|
||
|
|
# On the NUC, run:
|
||
|
|
# bash install-nuc.sh [path/to/phi4-mm-Q4_K_M.gguf]
|
||
|
|
#
|
||
|
|
# Or from the build machine, copy files first then run:
|
||
|
|
# scp phi4-mm-Q4_K_M.gguf Modelfile openclaw-config.json user@nuc-ip:~/phi4-deploy/
|
||
|
|
# ssh user@nuc-ip "cd ~/phi4-deploy && bash install-nuc.sh"
|
||
|
|
# =============================================================================
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
GGUF_DEFAULT="/home/$(whoami)/phi4-deploy/phi4-mm-Q4_K_M.gguf"
|
||
|
|
GGUF_PATH="${1:-$GGUF_DEFAULT}"
|
||
|
|
MODELFILE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
MODEL_NAME="phi4-mm-nuc"
|
||
|
|
|
||
|
|
echo "============================================================"
|
||
|
|
echo " Phi-4 Multimodal NUC Deployment"
|
||
|
|
echo "============================================================"
|
||
|
|
echo " GGUF : $GGUF_PATH"
|
||
|
|
echo " Model : $MODEL_NAME"
|
||
|
|
echo " Host : $(hostname)"
|
||
|
|
echo "============================================================"
|
||
|
|
|
||
|
|
# ── 1. Verify GGUF exists ─────────────────────────────────────────────────────
|
||
|
|
if [[ ! -f "$GGUF_PATH" ]]; then
|
||
|
|
echo "ERROR: GGUF not found at $GGUF_PATH"
|
||
|
|
echo "Transfer it first: scp <build-host>:~/models/phi4-mm-Q4_K_M.gguf $GGUF_PATH"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ── 2. Install Ollama if missing ──────────────────────────────────────────────
|
||
|
|
if ! command -v ollama &>/dev/null; then
|
||
|
|
echo ""
|
||
|
|
echo ">>> Installing Ollama..."
|
||
|
|
curl -fsSL https://ollama.com/install.sh | sh
|
||
|
|
echo ">>> Ollama installed."
|
||
|
|
else
|
||
|
|
echo ">>> Ollama already installed: $(ollama --version)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ── 3. Ensure Ollama daemon is running ────────────────────────────────────────
|
||
|
|
if ! pgrep -x ollama &>/dev/null; then
|
||
|
|
echo ">>> Starting Ollama daemon..."
|
||
|
|
ollama serve &>/dev/null &
|
||
|
|
sleep 3
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ── 4. Patch Modelfile with absolute GGUF path ───────────────────────────────
|
||
|
|
MODELFILE_TMP="$(mktemp)"
|
||
|
|
sed "s|FROM ./phi4-mm-Q4_K_M.gguf|FROM ${GGUF_PATH}|" \
|
||
|
|
"${MODELFILE_DIR}/Modelfile" > "$MODELFILE_TMP"
|
||
|
|
|
||
|
|
# ── 5. Register model with Ollama ─────────────────────────────────────────────
|
||
|
|
echo ""
|
||
|
|
echo ">>> Creating Ollama model: $MODEL_NAME"
|
||
|
|
ollama create "$MODEL_NAME" -f "$MODELFILE_TMP"
|
||
|
|
rm "$MODELFILE_TMP"
|
||
|
|
echo ">>> Model registered."
|
||
|
|
|
||
|
|
# ── 6. Smoke-test ─────────────────────────────────────────────────────────────
|
||
|
|
echo ""
|
||
|
|
echo ">>> Running smoke test (one token)..."
|
||
|
|
RESPONSE=$(ollama run "$MODEL_NAME" "Reply with exactly: OK" --nowordwrap 2>&1 | head -5)
|
||
|
|
echo " Response: $RESPONSE"
|
||
|
|
|
||
|
|
# ── 7. Systemd user service for Ollama (optional) ─────────────────────────────
|
||
|
|
if command -v systemctl &>/dev/null && systemctl --user status ollama.service &>/dev/null 2>&1; then
|
||
|
|
echo ">>> Ollama systemd service already configured."
|
||
|
|
else
|
||
|
|
echo ""
|
||
|
|
echo ">>> To keep Ollama running at startup, enable the service:"
|
||
|
|
echo " sudo systemctl enable --now ollama"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ── Done ──────────────────────────────────────────────────────────────────────
|
||
|
|
echo ""
|
||
|
|
echo "============================================================"
|
||
|
|
echo " DONE. Model is ready."
|
||
|
|
echo ""
|
||
|
|
echo " Test: ollama run $MODEL_NAME"
|
||
|
|
echo " API endpoint: http://localhost:11434/v1"
|
||
|
|
echo " OpenClaw model: ollama/$MODEL_NAME"
|
||
|
|
echo "============================================================"
|