mirror of
https://github.com/Nighthawk42/fulloch.git
synced 2026-08-30 08:52:26 +00:00
215 lines
6.3 KiB
Bash
Executable File
215 lines
6.3 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e
|
|
|
|
# Helper function to ask user for confirmation
|
|
ask_download() {
|
|
local model_name="$1"
|
|
read -p "Download $model_name? (y/n): " response
|
|
response=${response,,}
|
|
[[ "$response" == "y" || "$response" == "yes" ]]
|
|
}
|
|
|
|
# Directory definitions
|
|
BASE_DIR="$(pwd)/data/models"
|
|
GRAMMAR_DIR="$BASE_DIR/grammars"
|
|
HUB_DIR="$BASE_DIR/hub"
|
|
|
|
# Model specific variables
|
|
QWEN_REPO="unsloth/Qwen3-4B-Instruct-2507-GGUF"
|
|
QWEN_FILE="Qwen3-4B-Instruct-2507-Q4_K_M.gguf"
|
|
|
|
# Define the cache folders
|
|
ASR_TINY_DIR="$HUB_DIR/models--UsefulSensors--moonshine-tiny"
|
|
ASR_DIR="$HUB_DIR/models--Qwen--Qwen3-ASR-1.7B"
|
|
TTS_TINY_DIR="$HUB_DIR/models--hexgrad--Kokoro-82M"
|
|
TTS_DIR="$HUB_DIR/models--Qwen--Qwen3-TTS-12Hz-1.7B-Base"
|
|
|
|
# 1. Ensure Dependencies are installed
|
|
echo "🔍 Checking dependencies..."
|
|
|
|
# Check for curl
|
|
if ! command -v curl &> /dev/null; then
|
|
echo "❌ curl not found. Please install curl first."
|
|
echo " e.g. sudo apt install curl"
|
|
exit 1
|
|
fi
|
|
|
|
# Check for wget
|
|
if ! command -v wget &> /dev/null; then
|
|
echo "❌ wget not found. Please install wget first."
|
|
echo " e.g. sudo apt install wget"
|
|
exit 1
|
|
fi
|
|
|
|
# Check for docker and docker compose
|
|
if ! command -v docker &> /dev/null; then
|
|
echo "❌ docker not found. Please install Docker first."
|
|
echo " See https://docs.docker.com/engine/install/"
|
|
exit 1
|
|
fi
|
|
|
|
if ! docker compose version &> /dev/null; then
|
|
echo "❌ docker compose not found. Please install the Docker Compose plugin."
|
|
echo " See https://docs.docker.com/compose/install/"
|
|
exit 1
|
|
fi
|
|
|
|
# Check for hf (install via standalone installer if missing)
|
|
if ! command -v hf &> /dev/null; then
|
|
echo "⬇️ hf not found. Installing via standalone installer..."
|
|
curl -LsSf https://hf.co/cli/install.sh | bash
|
|
# Source updated PATH so hf is available in this session
|
|
export PATH="$HOME/.local/bin:$PATH"
|
|
if ! command -v hf &> /dev/null; then
|
|
echo "❌ hf still not found after install."
|
|
echo " Try running: curl -LsSf https://hf.co/cli/install.sh | bash"
|
|
echo " Then restart your shell and run ./launch.sh again."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "✅ All dependencies found."
|
|
|
|
# 2. Create Directory Structure
|
|
echo "📂 Checking directory structure..."
|
|
mkdir -p "$HUB_DIR" "$GRAMMAR_DIR"
|
|
|
|
# 2a. Check for config.yml and .env, create from templates if missing
|
|
CONFIG_FILE="$(pwd)/data/config.yml"
|
|
CONFIG_EXAMPLE="$(pwd)/data/config.example.yml"
|
|
ENV_FILE="$(pwd)/.env"
|
|
ENV_EXAMPLE="$(pwd)/.env.example"
|
|
|
|
CREATED_FILES=()
|
|
|
|
if [ ! -f "$CONFIG_FILE" ]; then
|
|
echo "📝 config.yml not found. Creating from template..."
|
|
cp "$CONFIG_EXAMPLE" "$CONFIG_FILE"
|
|
CREATED_FILES+=("data/config.yml")
|
|
else
|
|
echo "✅ config.yml exists."
|
|
fi
|
|
|
|
if [ ! -f "$ENV_FILE" ]; then
|
|
echo "📝 .env not found. Creating from template..."
|
|
cp "$ENV_EXAMPLE" "$ENV_FILE"
|
|
CREATED_FILES+=(".env")
|
|
else
|
|
echo "✅ .env exists."
|
|
fi
|
|
|
|
if [ ${#CREATED_FILES[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "📄 Created: ${CREATED_FILES[*]}"
|
|
echo ""
|
|
read -p "Continue with defaults or exit to edit these files first? (c)ontinue / (e)xit: " response
|
|
response=${response,,}
|
|
if [[ "$response" == "e" || "$response" == "exit" ]]; then
|
|
echo ""
|
|
echo " Edit the files and run ./launch.sh again when ready."
|
|
exit 0
|
|
fi
|
|
echo "✅ Continuing with defaults."
|
|
fi
|
|
|
|
# 3. Check and Download json.gbnf
|
|
if [ ! -f "$GRAMMAR_DIR/json.gbnf" ]; then
|
|
if ask_download "json.gbnf (grammar file)"; then
|
|
echo "⬇️ Downloading json.gbnf..."
|
|
wget -q --show-progress -O "$GRAMMAR_DIR/json.gbnf" \
|
|
"https://raw.githubusercontent.com/ggml-org/llama.cpp/master/grammars/json.gbnf"
|
|
else
|
|
echo "⏭️ Skipping json.gbnf"
|
|
fi
|
|
else
|
|
echo "✅ json.gbnf exists."
|
|
fi
|
|
|
|
# 4. Check and Download Qwen3 GGUF
|
|
if [ ! -f "$BASE_DIR/$QWEN_FILE" ]; then
|
|
if ask_download "Qwen3 4B SLM (2.5GB)"; then
|
|
echo "⬇️ Downloading $QWEN_FILE..."
|
|
hf download "$QWEN_REPO" "$QWEN_FILE" \
|
|
--local-dir "$BASE_DIR"
|
|
else
|
|
echo "⏭️ Skipping Qwen3 SLM"
|
|
fi
|
|
else
|
|
echo "✅ $QWEN_FILE exists."
|
|
fi
|
|
|
|
# 5. Check and Download Qwen3 TTS model
|
|
if [ ! -d "$TTS_DIR" ]; then
|
|
if ask_download "Qwen3 TTS (3.4GB)"; then
|
|
echo "⬇️ Downloading Qwen3 TTS..."
|
|
hf download Qwen/Qwen3-TTS-12Hz-1.7B-Base \
|
|
--cache-dir "$HUB_DIR"
|
|
else
|
|
echo "⏭️ Skipping Qwen3 TTS"
|
|
fi
|
|
else
|
|
echo "✅ Qwen3 TTS model exists."
|
|
fi
|
|
|
|
# 5a. Check and Download Kokoro-82M (TTS)
|
|
if [ ! -d "$TTS_TINY_DIR" ]; then
|
|
if ask_download "Kokoro-82M TTS Tiny (200MB)"; then
|
|
echo "⬇️ Downloading Kokoro-82M..."
|
|
hf download hexgrad/Kokoro-82M \
|
|
--cache-dir "$HUB_DIR"
|
|
else
|
|
echo "⏭️ Skipping Kokoro-82M"
|
|
fi
|
|
else
|
|
echo "✅ Kokoro-82M exists."
|
|
fi
|
|
|
|
# 6. Check and Download Qwen3 ASR model
|
|
if [ ! -d "$ASR_DIR" ]; then
|
|
if ask_download "Qwen3 ASR (3.4GB)"; then
|
|
echo "⬇️ Downloading Qwen3 ASR..."
|
|
hf download Qwen/Qwen3-ASR-1.7B \
|
|
--cache-dir "$HUB_DIR"
|
|
else
|
|
echo "⏭️ Skipping Qwen3 ASR"
|
|
fi
|
|
else
|
|
echo "✅ Qwen3 ASR model exists."
|
|
fi
|
|
|
|
# 6a. Check and Download Moonshine Tiny ASR model
|
|
if [ ! -d "$ASR_TINY_DIR" ]; then
|
|
if ask_download "Moonshine Tiny ASR (60MB)"; then
|
|
echo "⬇️ Downloading Moonshine Tiny..."
|
|
hf download UsefulSensors/moonshine-tiny \
|
|
--cache-dir "$HUB_DIR"
|
|
else
|
|
echo "⏭️ Skipping Moonshine Tiny"
|
|
fi
|
|
else
|
|
echo "✅ Moonshine-tiny exists."
|
|
fi
|
|
|
|
# 7. Prompt the user
|
|
read -p "Are you using an NVIDIA GPU? (y/n): " response
|
|
response=${response,,}
|
|
if [[ "$response" == "y" || "$response" == "yes" ]]; then
|
|
COMPOSE_FILE="compose_gpu.yml"
|
|
echo "✅ Using GPU enabled containers"
|
|
else
|
|
COMPOSE_FILE="compose.yml"
|
|
echo "✅ Using default containers"
|
|
fi
|
|
|
|
# 8. Prepare runtime environment
|
|
# Ensure XDG_RUNTIME_DIR is set with the correct UID (compose files reference it)
|
|
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
|
|
|
# Ensure PulseAudio cookie exists (PipeWire systems may not create one)
|
|
mkdir -p "${HOME}/.config/pulse"
|
|
[ -f "${HOME}/.config/pulse/cookie" ] || touch "${HOME}/.config/pulse/cookie"
|
|
|
|
# 9. Launch Docker Compose
|
|
echo "🚀 All files checked. Starting services..."
|
|
docker compose -f "$COMPOSE_FILE" up -d
|