#!/usr/bin/env bash # Thanatos-27B — fetch the vision projector (mmproj) for image input. # # Why this is separate from build.sh: # build.sh is for the Ollama text path. The mmproj is only useful for # llama.cpp / llama-cpp-python right now, because Ollama's vendored # llama.cpp fork is missing the qwen35 arch entries needed to attach # it (see README Vision section, ollama/ollama#15898). # # Usage: # ./scripts/fetch_vision.sh # default: F16, ~927 MB # ./scripts/fetch_vision.sh BF16 # ~931 MB # ./scripts/fetch_vision.sh F32 # ~1.8 GB # # Requires: huggingface-cli (or hf). set -euo pipefail PRECISION="${1:-${PRECISION:-F16}}" REPO_ID="${REPO_ID:-unsloth/Qwen3.6-27B-GGUF}" FILE_NAME="mmproj-${PRECISION}.gguf" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DEST="${MMPROJ_PATH:-${ROOT}/${FILE_NAME}}" echo "[*] repo: ${REPO_ID}" echo "[*] precision: ${PRECISION}" echo "[*] file: ${FILE_NAME}" echo "[*] dest: ${DEST}" if [[ -f "${DEST}" ]]; then echo "[=] already present at ${DEST}, skipping." exit 0 fi HF="" if command -v hf >/dev/null 2>&1; then HF="hf" elif command -v huggingface-cli >/dev/null 2>&1; then HF="huggingface-cli" else echo "[!] Neither 'hf' nor 'huggingface-cli' found." >&2 echo " pip install -U huggingface_hub" >&2 exit 1 fi DEST_DIR="$(dirname "${DEST}")" mkdir -p "${DEST_DIR}" case "${HF}" in hf) hf download "${REPO_ID}" "${FILE_NAME}" --local-dir "${DEST_DIR}" ;; huggingface-cli) huggingface-cli download "${REPO_ID}" "${FILE_NAME}" --local-dir "${DEST_DIR}" ;; esac if [[ ! -f "${DEST}" ]]; then echo "[!] download failed: ${DEST} not present." >&2 exit 1 fi echo echo "[+] Done. Use it via:" echo " python ${ROOT}/examples/llama_cpp_vision.py \\" echo " --gguf /path/to/Qwen3.6-27B-Q4_K_M.gguf \\" echo " --mmproj ${DEST} \\" echo " --image /path/to/photo.jpg \\" echo " --prompt 'Describe this image.'"