diff --git a/laptop_full_setup.sh b/laptop_full_setup.sh index f93fada..dcd575a 100755 --- a/laptop_full_setup.sh +++ b/laptop_full_setup.sh @@ -235,27 +235,127 @@ if command -v ufw &>/dev/null && { [[ ! -f "$BASE/.ufw-done" ]] || $FORCE; }; th [[ "$LAN_SUBNET" =~ /[0-9]+$ ]] || LAN_SUBNET="${LAN_SUBNET}/24" fi -# ── Q5: Pull Ollama models now? ─────────────────────────────────────────────── +# ── Q5: Model selection wizard ──────────────────────────────────────────────── PULL_MODELS=false -PULL_DEEPSEEK=false +REASON_MODEL="" if $INSTALL_AI; then + + # speed estimate based on Q4 model size vs available VRAM + # no hard limits — just honest labels so the user can choose + speed_label() { + local mgb="$1" # approximate Q4 size in GB + if [[ "$VRAM_GB" -eq 0 ]]; then + printf "CPU only — very slow" + elif (( mgb <= VRAM_GB )); then + printf "✓ fast — fully in VRAM" + elif (( mgb <= VRAM_GB + 2 )); then + printf "~ good — fits with small overhang (~reading speed)" + elif (( mgb <= VRAM_GB + 8 )); then + printf "✗ slow — partial CPU offload" + else + printf "✗ very slow — heavy CPU offload" + fi + } + echo "" - echo -e " ${BOLD}[5/6] Download AI models now?${NC}" - echo " GPU detected: ${GPU_NAME} (${VRAM_GB}GB VRAM) → recommended tier: ${GPU_TIER}" + echo -e " ${BOLD}[5/6] Model selection${NC}" + echo " GPU: ${GPU_NAME:-None} (${VRAM_GB}GB VRAM)" echo "" - echo " Models that will be downloaded:" - echo " nomic-embed-text (~300MB) — RAG embeddings (required)" - echo " ${FAST_MODEL} (~5GB) — fast chat" - echo " ${CHAT_MODEL} (~9GB) — smart chat" - echo " ${CODE_MODEL} (~5GB) — code assistant" + echo " Origin preference:" + echo " 1) Western-only — Codestral (Mistral 🇫🇷) · Phi4 (Microsoft 🇺🇸) · Mistral 7B" + echo " 2) Performance-first — Qwen2.5 · Qwen2.5-Coder (Chinese, top benchmarks)" + echo " 3) Mixed — Western for chat/reasoning, Qwen for coding only" + echo " 4) Custom — enter model names manually" echo "" - read -rp " Download models now? (~20GB total) [Y/n]: " DO_PULL - if [[ "${DO_PULL,,}" != "n" ]]; then - PULL_MODELS=true - read -rp " Also download DeepSeek-R1:14b for reasoning? (~9GB extra) [y/N]: " DO_DS - [[ "${DO_DS,,}" == "y" ]] && PULL_DEEPSEEK=true + read -rp " Choice [1]: " MODEL_PREF + MODEL_PREF="${MODEL_PREF:-1}" + + # Q4 approximate sizes in GB: 7B=4, 13-15B=9, 22B=13, 32B=19, 70-72B=41 + echo "" + echo " Size tier — estimated speed on your ${VRAM_GB}GB GPU:" + echo " (No hard limits — Ollama uses all available VRAM automatically)" + echo "" + printf " %-8s %-42s %s\n" "Tier" "Models" "Speed on your system" + printf " %-8s %-42s %s\n" "--------" "------------------------------------------" "--------------------" + + case "$MODEL_PREF" in + 1) # Western + printf " %-8s %-42s %s\n" "7B" "mistral:7b + codellama:7b" "$(speed_label 4)" + printf " %-8s %-42s %s\n" "14B" "phi4:14b + starcoder2:15b" "$(speed_label 9)" + printf " %-8s %-42s %s\n" "22B" "phi4:14b + codestral:22b" "$(speed_label 13)" + printf " %-8s %-42s %s\n" "70B" "llama3.3:70b + codestral:22b" "$(speed_label 41)" + ;; + 2) # Performance + printf " %-8s %-42s %s\n" "7B" "qwen2.5:7b + qwen2.5-coder:7b" "$(speed_label 4)" + printf " %-8s %-42s %s\n" "14B" "qwen2.5:14b + qwen2.5-coder:14b" "$(speed_label 9)" + printf " %-8s %-42s %s\n" "32B" "qwen2.5:14b + qwen2.5-coder:32b" "$(speed_label 19)" + printf " %-8s %-42s %s\n" "72B" "qwen2.5:72b + qwen2.5-coder:32b" "$(speed_label 41)" + ;; + 3) # Mixed + printf " %-8s %-42s %s\n" "7B" "mistral:7b + qwen2.5-coder:7b" "$(speed_label 4)" + printf " %-8s %-42s %s\n" "14B" "phi4:14b + qwen2.5-coder:14b" "$(speed_label 9)" + printf " %-8s %-42s %s\n" "32B" "phi4:14b + qwen2.5-coder:32b" "$(speed_label 19)" + printf " %-8s %-42s %s\n" "70B" "llama3.3:70b + qwen2.5-coder:32b" "$(speed_label 41)" + ;; + esac + + # VRAM-based recommendation (soft — shown as suggestion only) + if [[ "$VRAM_GB" -ge 20 ]]; then REC_TIER="32B" + elif [[ "$VRAM_GB" -ge 12 ]]; then REC_TIER="22B" + elif [[ "$VRAM_GB" -ge 6 ]]; then REC_TIER="14B" + else REC_TIER="7B" fi + # performance pref has no 22B tier + [[ "$MODEL_PREF" == "2" && "$REC_TIER" == "22B" ]] && REC_TIER="32B" + + echo "" + + if [[ "$MODEL_PREF" == "4" ]]; then + # Custom — free-form entry + echo " Current defaults: fast=$FAST_MODEL chat=$CHAT_MODEL code=$CODE_MODEL" + echo " Press Enter on any line to keep the default shown." + echo "" + read -rp " Fast/chat model [$FAST_MODEL]: " _in; FAST_MODEL="${_in:-$FAST_MODEL}" + read -rp " Smart chat model [$CHAT_MODEL]: " _in; CHAT_MODEL="${_in:-$CHAT_MODEL}" + read -rp " Code model [$CODE_MODEL]: " _in; CODE_MODEL="${_in:-$CODE_MODEL}" + read -rp " Reasoning model (Enter to skip): " REASON_MODEL + else + read -rp " Choose tier [$REC_TIER]: " TIER_PICK + TIER_PICK="${TIER_PICK:-$REC_TIER}" + + case "${MODEL_PREF}:${TIER_PICK}" in + # Western + 1:7B) FAST_MODEL="mistral:7b"; CHAT_MODEL="mistral:7b"; CODE_MODEL="codellama:7b"; REASON_MODEL="" ;; + 1:14B) FAST_MODEL="mistral:7b"; CHAT_MODEL="phi4:14b"; CODE_MODEL="starcoder2:15b"; REASON_MODEL="phi4:14b" ;; + 1:22B) FAST_MODEL="mistral:7b"; CHAT_MODEL="phi4:14b"; CODE_MODEL="codestral:22b"; REASON_MODEL="phi4:14b" ;; + 1:70B) FAST_MODEL="mistral:7b"; CHAT_MODEL="llama3.3:70b"; CODE_MODEL="codestral:22b"; REASON_MODEL="llama3.3:70b" ;; + # Performance-first + 2:7B) FAST_MODEL="qwen2.5:7b"; CHAT_MODEL="qwen2.5:7b"; CODE_MODEL="qwen2.5-coder:7b"; REASON_MODEL="" ;; + 2:14B) FAST_MODEL="qwen2.5:7b"; CHAT_MODEL="qwen2.5:14b"; CODE_MODEL="qwen2.5-coder:14b"; REASON_MODEL="deepseek-r1:14b" ;; + 2:32B) FAST_MODEL="qwen2.5:7b"; CHAT_MODEL="qwen2.5:14b"; CODE_MODEL="qwen2.5-coder:32b"; REASON_MODEL="deepseek-r1:14b" ;; + 2:72B) FAST_MODEL="qwen2.5:7b"; CHAT_MODEL="qwen2.5:72b"; CODE_MODEL="qwen2.5-coder:32b"; REASON_MODEL="deepseek-r1:14b" ;; + # Mixed + 3:7B) FAST_MODEL="mistral:7b"; CHAT_MODEL="mistral:7b"; CODE_MODEL="qwen2.5-coder:7b"; REASON_MODEL="" ;; + 3:14B) FAST_MODEL="mistral:7b"; CHAT_MODEL="phi4:14b"; CODE_MODEL="qwen2.5-coder:14b"; REASON_MODEL="phi4:14b" ;; + 3:32B) FAST_MODEL="mistral:7b"; CHAT_MODEL="phi4:14b"; CODE_MODEL="qwen2.5-coder:32b"; REASON_MODEL="phi4:14b" ;; + 3:70B) FAST_MODEL="mistral:7b"; CHAT_MODEL="llama3.3:70b"; CODE_MODEL="qwen2.5-coder:32b"; REASON_MODEL="llama3.3:70b" ;; + *) + warn "Unrecognised tier '$TIER_PICK' — keeping detected defaults" + ;; + esac + fi + + echo "" + echo " Models selected:" + printf " %-16s %s\n" "Fast chat:" "$FAST_MODEL" + printf " %-16s %s\n" "Smart chat:" "$CHAT_MODEL" + printf " %-16s %s\n" "Code:" "$CODE_MODEL" + [[ -n "$REASON_MODEL" ]] && printf " %-16s %s\n" "Reasoning:" "$REASON_MODEL" + printf " %-16s %s\n" "Embed (RAG):" "$EMBED_MODEL" + echo "" + read -rp " Download these models now? [Y/n]: " DO_PULL + [[ "${DO_PULL,,}" != "n" ]] && PULL_MODELS=true fi # ── Summary ─────────────────────────────────────────────────────────────────── @@ -276,7 +376,7 @@ if $INSTALL_AI; then fi fi $INSTALL_KIWIX && echo " ✓ Kiwix ZIMs → $KIWIX_DIR" -$PULL_MODELS && echo " ✓ Pull models : embed + ${FAST_MODEL} + ${CHAT_MODEL} + ${CODE_MODEL}${PULL_DEEPSEEK:+ + deepseek-r1:14b}" +$PULL_MODELS && echo " ✓ Pull models : $EMBED_MODEL + $FAST_MODEL + $CHAT_MODEL + $CODE_MODEL${REASON_MODEL:+ + $REASON_MODEL}" [[ "$ZIM_CHOICE" == "1" ]] && echo " ✓ Download all ZIMs in background (~130GB)" [[ "$ZIM_CHOICE" == "2" ]] && echo " ✓ Select ZIMs to download (prompted after stack starts)" echo "" @@ -786,25 +886,37 @@ ok "status.sh" cat > "$BASE/pull-models.sh" << PULLSH #!/bin/bash +# Models chosen at install time — re-run setup to change selection +EMBED_MODEL="$EMBED_MODEL" +FAST_MODEL="$FAST_MODEL" +CHAT_MODEL="$CHAT_MODEL" +CODE_MODEL="$CODE_MODEL" +REASON_MODEL="$REASON_MODEL" + echo "Waiting for Ollama..." until docker exec ollama ollama list &>/dev/null; do sleep 3; done echo "Ollama ready." echo "" -echo "Pulling embed model (needed for RAG)..." -docker exec ollama ollama pull $EMBED_MODEL +echo "Pulling embed model (RAG — required)..." +docker exec ollama ollama pull "\$EMBED_MODEL" -echo "Pulling fast chat model (~5GB)..." -docker exec ollama ollama pull $FAST_MODEL +echo "Pulling fast chat model..." +docker exec ollama ollama pull "\$FAST_MODEL" -echo "Pulling smart chat model (~9GB)..." -docker exec ollama ollama pull $CHAT_MODEL +echo "Pulling smart chat model..." +[[ "\$CHAT_MODEL" != "\$FAST_MODEL" ]] && docker exec ollama ollama pull "\$CHAT_MODEL" -echo "Pulling code model (~5GB)..." -docker exec ollama ollama pull $CODE_MODEL +echo "Pulling code model..." +docker exec ollama ollama pull "\$CODE_MODEL" + +if [[ -n "\$REASON_MODEL" && "\$REASON_MODEL" != "\$CHAT_MODEL" ]]; then + echo "Pulling reasoning model..." + docker exec ollama ollama pull "\$REASON_MODEL" +fi echo "" -echo "Done. Models:" +echo "Done. Installed models:" docker exec ollama ollama list PULLSH chmod +x "$BASE/pull-models.sh" @@ -888,9 +1000,9 @@ if $INSTALL_AI && $PULL_MODELS; then info "Pulling code model..." docker exec ollama ollama pull "$CODE_MODEL" - if $PULL_DEEPSEEK; then - info "Pulling DeepSeek-R1:14b (reasoning)..." - docker exec ollama ollama pull deepseek-r1:14b + if [[ -n "$REASON_MODEL" ]]; then + info "Pulling reasoning model ($REASON_MODEL)..." + docker exec ollama ollama pull "$REASON_MODEL" fi ok "All models pulled."