#!/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 :~/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 "============================================================"