File size: 5,052 Bytes
2b4501a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/bin/sh
# Shared helpers for Bonsai demo scripts.
# Source this file: . "$(dirname "$0")/common.sh"

# ── Model selection ──
# Set BONSAI_MODEL to choose which model size to use.
# Valid values: 8B (default), 4B, 1.7B
BONSAI_MODEL="${BONSAI_MODEL:-8B}"
GGUF_MODEL_DIR="models/gguf/${BONSAI_MODEL}"

MLX_MODEL_DIR="models/Bonsai-${BONSAI_MODEL}-mlx"

# Validate BONSAI_MODEL β€” call at the top of every run/server script
assert_valid_model() {
    case "$BONSAI_MODEL" in
        8B|4B|1.7B) return 0 ;;
        *)
            err "Unknown BONSAI_MODEL='${BONSAI_MODEL}'. Valid values: 8B, 4B, 1.7B"
            echo "  Example: export BONSAI_MODEL=8B"
            exit 1 ;;
    esac
}

# Check GGUF model is downloaded β€” prompts to download if missing
assert_gguf_downloaded() {
    if ! ls "$GGUF_MODEL_DIR"/*.gguf >/dev/null 2>&1; then
        err "GGUF model not found for Bonsai-${BONSAI_MODEL} (expected in ${GGUF_MODEL_DIR}/)."
        echo "  Download it with:"
        echo "    BONSAI_MODEL=${BONSAI_MODEL} ./scripts/download_models.sh"
        exit 1
    fi
}

# Check MLX model is downloaded β€” prompts to download if missing
assert_mlx_downloaded() {
    if [ ! -f "$MLX_MODEL_DIR/config.json" ]; then
        err "MLX model not found for Bonsai-${BONSAI_MODEL} (expected in ${MLX_MODEL_DIR}/)."
        echo "  Download it with:"
        echo "    BONSAI_MODEL=${BONSAI_MODEL} ./scripts/download_models.sh"
        exit 1
    fi
}

# ── Colors ──
if [ -t 1 ]; then
    _CLR_GREEN="\033[32m"
    _CLR_YELLOW="\033[33m"
    _CLR_RED="\033[31m"
    _CLR_CYAN="\033[36m"
    _CLR_RESET="\033[0m"
else
    _CLR_GREEN="" _CLR_YELLOW="" _CLR_RED="" _CLR_CYAN="" _CLR_RESET=""
fi

info()  { printf "${_CLR_GREEN}[OK]${_CLR_RESET}   %s\n" "$*"; }
warn()  { printf "${_CLR_YELLOW}[WARN]${_CLR_RESET} %s\n" "$*"; }
err()   { printf "${_CLR_RED}[ERR]${_CLR_RESET}  %s\n" "$*" >&2; }
step()  { printf "${_CLR_CYAN}==>    %s${_CLR_RESET}\n" "$*"; }

# ── download(url, dest) β€” supports curl and wget ──
download() {
    if command -v curl >/dev/null 2>&1; then
        curl -LsSf "$1" -o "$2"
    elif command -v wget >/dev/null 2>&1; then
        wget -qO "$2" "$1"
    else
        err "Neither curl nor wget found. Install one and re-run."
        exit 1
    fi
}

# ── Smart context size for llama.cpp ──
# Default: -c 0 lets llama.cpp's --fit auto-size KV cache to available memory.
# Fallback: if -c 0 is not supported, pick a safe value from system RAM.
# Max context: 65536.
# Memory = ~1.1 GB weights + ~140 bytes/token KV cache + activations.
#   8 GB  β†’ -c  8192  (~2.5 GB total, leaves ~5 GB for OS)
#  16 GB  β†’ -c 32768  (~5.9 GB total, leaves ~10 GB for OS)
#  24 GB+ β†’ -c 65536  (~10.5 GB total, leaves ~13+ GB for OS)

CTX_SIZE_DEFAULT=0

get_context_size_fallback() {
    if [ "$(uname -s)" = "Darwin" ]; then
        _mem_gb=$(( $(sysctl -n hw.memsize) / 1073741824 ))
    else
        _mem_kb=$(awk '/MemTotal/ {print $2}' /proc/meminfo 2>/dev/null)
        _mem_gb=$(( ${_mem_kb:-0} / 1048576 ))
    fi

    if [ "$_mem_gb" -le 8 ] 2>/dev/null; then
        echo 8192
    elif [ "$_mem_gb" -le 18 ] 2>/dev/null; then
        echo 32768
    else
        echo 65536
    fi
}

# ── Resolve DEMO_DIR (parent of scripts/) ──
resolve_demo_dir() {
    _script_dir="$(cd "$(dirname "$0")" && pwd)"
    echo "$(cd "$_script_dir/.." && pwd)"
}

# ── Locate a llama.cpp binary ──
# Optional override:
#   BONSAI_LLAMA_BIN_DIR=/abs/path/to/bin
find_llama_bin() {
    _demo_dir="$1"
    _bin_name="$2"

    for _dir in \
        "${BONSAI_LLAMA_BIN_DIR:-}" \
        "$_demo_dir/../llama.cpp-1bit-turboquant/build-tbq-cuda/bin" \
        "$_demo_dir/../llama.cpp-1bit-turboquant/build-cuda/bin" \
        "$_demo_dir/../llama.cpp-1bit-turboquant/build/bin" \
        "$_demo_dir/../prism-llama.cpp/build-tbq-cuda/bin" \
        "$_demo_dir/../prism-llama.cpp/build-cuda/bin" \
        "$_demo_dir/../prism-llama.cpp/build/bin" \
        "$_demo_dir/../embed/llama.cpp/build-tbq-cuda/bin" \
        "$_demo_dir/../embed/llama.cpp/build-cuda/bin" \
        "$_demo_dir/../embed/llama.cpp/build/bin" \
        "$_demo_dir/../embed/llama.cpp/build-tbq-cpu/bin" \
        "$_demo_dir/llama.cpp/build-tbq-cuda/bin" \
        "$_demo_dir/llama.cpp/build-cuda/bin" \
        "$_demo_dir/llama.cpp/build/bin" \
        "$_demo_dir/llama.cpp/build-mac/bin" \
        "$_demo_dir/bin/cuda" \
        "$_demo_dir/bin/mac"
    do
        [ -n "$_dir" ] || continue
        if [ -f "$_dir/$_bin_name" ]; then
            echo "$_dir/$_bin_name"
            return 0
        fi
    done

    return 1
}

# ── Ensure .venv is active (for MLX / Python scripts) ──
ensure_venv() {
    _demo="$1"
    if [ -z "$VIRTUAL_ENV" ] && [ -f "$_demo/.venv/bin/activate" ]; then
        . "$_demo/.venv/bin/activate"
    fi
    if [ -z "$VIRTUAL_ENV" ]; then
        err "Python venv not found. Create one with 'uv venv .venv --python 3.11' and install the Python deps you need."
        exit 1
    fi
}