Enhance LLM configuration and installation scripts for improved flexibility
- Added new environment variables in `env.example` and `gpu-rent.vars.example` for fine-tuning LLM settings, including CUDA build options and model version pinning. - Updated `llm.md` documentation to include detailed descriptions of new configuration options and usage cases for LLM setups. - Enhanced the `provision.py` script to forward new environment variables during remote installations, improving the installation process for LLM components. - Modified the `install_llamacpp.sh` script to support conditional CUDA builds and asset URL overrides, ensuring better compatibility with various environments. - Improved logging in the installation scripts to provide clearer feedback during the setup process.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install llama-server (CUDA) for OpenAI-compatible API on loopback :8080.
|
||||
# Official GitHub releases ship Windows CUDA only — on Linux we build from source.
|
||||
# Install llama-server for OpenAI-compatible API on loopback :8080.
|
||||
#
|
||||
# Default: official Linux release asset (Ubuntu Vulkan — GPU without compile).
|
||||
# CUDA source build only as last resort (or LLAMACPP_BUILD_CUDA=1).
|
||||
# Pin: LLAMACPP_TAG=b10545 LLAMACPP_ASSET_URL=... LLAMACPP_SHA256=...
|
||||
set -euo pipefail
|
||||
|
||||
SWARM_USER="${SWARM_USER:-ubuntu}"
|
||||
@@ -28,8 +31,21 @@ SERVER_BIN="${BIN_DIR}/llama-server"
|
||||
LLAMACPP_TAG="${LLAMACPP_TAG:-}"
|
||||
LLAMACPP_ASSET_URL="${LLAMACPP_ASSET_URL:-}"
|
||||
LLAMACPP_SHA256="${LLAMACPP_SHA256:-}"
|
||||
# 1 = force CUDA compile; 0/empty = prebuilt first, build only if prebuilt fails
|
||||
LLAMACPP_BUILD_CUDA="${LLAMACPP_BUILD_CUDA:-}"
|
||||
LLAMACPP_FORCE_REINSTALL="${LLAMACPP_FORCE_REINSTALL:-}"
|
||||
LLAMACPP_NGL="${LLAMACPP_NGL:-}"
|
||||
LLAMACPP_CTX="${LLAMACPP_CTX:-}"
|
||||
LLAMACPP_HOST="${LLAMACPP_HOST:-127.0.0.1}"
|
||||
LLAMACPP_PORT="${LLAMACPP_PORT:-8080}"
|
||||
LLAMACPP_EXTRA_ARGS="${LLAMACPP_EXTRA_ARGS:-}"
|
||||
|
||||
# Pick a Linux release asset (never Windows/macOS). Prefer ubuntu CUDA → vulkan → cpu.
|
||||
if [[ "${LLAMACPP_FORCE_REINSTALL}" == "1" ]]; then
|
||||
log "LLAMACPP_FORCE_REINSTALL=1 — удаляю старый бинарь"
|
||||
rm -f "$SERVER_BIN" "$STAMP"
|
||||
fi
|
||||
|
||||
# Prefer ubuntu CUDA (rare) → vulkan → cpu. Never Windows/macOS/cudart-only.
|
||||
pick_linux_asset_url() {
|
||||
python3 -c '
|
||||
import json,sys
|
||||
@@ -107,7 +123,7 @@ ensure_build_deps() {
|
||||
export PATH="/usr/local/cuda/bin:${PATH}"
|
||||
return 0
|
||||
fi
|
||||
log "ставлю nvidia-cuda-toolkit (нужен nvcc для сборки)…"
|
||||
log "ставлю nvidia-cuda-toolkit (нужен nvcc)…"
|
||||
apt-get install -y -qq nvidia-cuda-toolkit >/dev/null
|
||||
if command -v nvcc >/dev/null 2>&1; then
|
||||
return 0
|
||||
@@ -119,14 +135,24 @@ ensure_build_deps() {
|
||||
return 1
|
||||
}
|
||||
|
||||
ensure_vulkan_runtime() {
|
||||
if ldconfig -p 2>/dev/null | grep -q 'libvulkan\.so'; then
|
||||
return 0
|
||||
fi
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
log "ставлю libvulkan1 (для Ubuntu Vulkan prebuilt)…"
|
||||
apt-get install -y -qq libvulkan1 mesa-vulkan-drivers >/dev/null 2>&1 || \
|
||||
apt-get install -y -qq libvulkan1 >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
install_from_archive_url() {
|
||||
local url="$1"
|
||||
local tmp
|
||||
tmp="$(mktemp -d)"
|
||||
(
|
||||
cd "$tmp"
|
||||
log "asset $url"
|
||||
curl -fL "$url" -o pkg.bin
|
||||
log "скачиваю prebuilt: $url"
|
||||
curl -fL --progress-bar "$url" -o pkg.bin
|
||||
if [[ -n "$LLAMACPP_SHA256" ]]; then
|
||||
echo "${LLAMACPP_SHA256} pkg.bin" | sha256sum -c -
|
||||
else
|
||||
@@ -149,58 +175,19 @@ install_from_archive_url() {
|
||||
exit 1
|
||||
fi
|
||||
install -m 755 "$found" "$SERVER_BIN"
|
||||
chown "${SWARM_USER}:${SWARM_USER}" "$SERVER_BIN"
|
||||
# Shared libs next to binary (release tarballs ship .so alongside).
|
||||
find out -type f \( -name '*.so' -o -name '*.so.*' \) -print0 2>/dev/null \
|
||||
| while IFS= read -r -d '' so; do
|
||||
install -m 755 "$so" "${BIN_DIR}/$(basename "$so")"
|
||||
done
|
||||
chown -R "${SWARM_USER}:${SWARM_USER}" "$BIN_DIR"
|
||||
)
|
||||
local rc=$?
|
||||
rm -rf "$tmp"
|
||||
return "$rc"
|
||||
}
|
||||
|
||||
build_cuda_from_source() {
|
||||
local tag="$1"
|
||||
local arch
|
||||
arch="$(cuda_architectures)"
|
||||
log "собираю llama-server CUDA из исходников (tag=${tag}, arch=${arch})…"
|
||||
if ! ensure_build_deps; then
|
||||
log "нет nvcc — CUDA-сборку пропускаем"
|
||||
return 1
|
||||
fi
|
||||
log "nvcc $(nvcc --version 2>/dev/null | tail -n1 || echo '?')"
|
||||
|
||||
mkdir -p "$SRC_DIR"
|
||||
if [[ -d "${SRC_DIR}/.git" ]]; then
|
||||
git -C "$SRC_DIR" fetch --depth 1 origin tag "$tag" 2>/dev/null || true
|
||||
if ! git -C "$SRC_DIR" checkout -f "$tag" 2>/dev/null; then
|
||||
rm -rf "$SRC_DIR"
|
||||
git clone --depth 1 --branch "$tag" "$REPO" "$SRC_DIR"
|
||||
fi
|
||||
else
|
||||
rm -rf "$SRC_DIR"
|
||||
git clone --depth 1 --branch "$tag" "$REPO" "$SRC_DIR"
|
||||
fi
|
||||
|
||||
cmake -S "$SRC_DIR" -B "${SRC_DIR}/build" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DGGML_CUDA=ON \
|
||||
-DCMAKE_CUDA_ARCHITECTURES="${arch}" \
|
||||
-DLLAMA_CURL=ON \
|
||||
-DLLAMA_BUILD_SERVER=ON
|
||||
cmake --build "${SRC_DIR}/build" -j"$(nproc)" --target llama-server
|
||||
|
||||
local built="${SRC_DIR}/build/bin/llama-server"
|
||||
if [[ ! -x "$built" ]]; then
|
||||
log "сборка не дала ${built}"
|
||||
return 1
|
||||
fi
|
||||
install -m 755 "$built" "$SERVER_BIN"
|
||||
chown "${SWARM_USER}:${SWARM_USER}" "$SERVER_BIN"
|
||||
echo "cuda:${tag}:${arch}" >"$STAMP"
|
||||
chown "${SWARM_USER}:${SWARM_USER}" "$STAMP"
|
||||
log "CUDA binary → ${SERVER_BIN}"
|
||||
return 0
|
||||
}
|
||||
|
||||
install_linux_release_fallback() {
|
||||
install_linux_release() {
|
||||
local tag="$1"
|
||||
local api url
|
||||
api="${API_BASE}/releases/tags/${tag}"
|
||||
@@ -210,36 +197,134 @@ install_linux_release_fallback() {
|
||||
return 1
|
||||
fi
|
||||
if [[ "$url" == *vulkan* ]]; then
|
||||
log "WARN: официального Linux CUDA нет — беру Ubuntu Vulkan prebuilt"
|
||||
elif [[ "$url" != *cuda* ]]; then
|
||||
log "WARN: беру Linux prebuilt без CUDA (CPU) — лучше собрать с nvcc"
|
||||
log "беру Ubuntu Vulkan prebuilt (GPU без compile; CUDA-сборка — LLAMACPP_BUILD_CUDA=1)"
|
||||
ensure_vulkan_runtime
|
||||
elif [[ "$url" == *cuda* ]]; then
|
||||
log "беру Linux CUDA prebuilt"
|
||||
else
|
||||
log "WARN: Linux prebuilt без GPU backend (CPU) — ${url##*/}"
|
||||
fi
|
||||
install_from_archive_url "$url"
|
||||
echo "asset:${tag}" >"$STAMP"
|
||||
chown "${SWARM_USER}:${SWARM_USER}" "$STAMP"
|
||||
}
|
||||
|
||||
# Quiet CUDA build: no cmake spam; heartbeat every 30s with last %.
|
||||
build_cuda_from_source() {
|
||||
local tag="$1"
|
||||
local arch build_log pid pct line
|
||||
arch="$(cuda_architectures)"
|
||||
build_log="${LLAMA_ROOT}/build-cuda.log"
|
||||
log "крайний случай: сборка CUDA из исходников (tag=${tag}, arch=${arch}, 5–15 мин)…"
|
||||
log "полный лог: ${build_log}"
|
||||
if ! ensure_build_deps; then
|
||||
log "нет nvcc — CUDA-сборку пропускаем"
|
||||
return 1
|
||||
fi
|
||||
log "nvcc $(nvcc --version 2>/dev/null | tail -n1 || echo '?')"
|
||||
|
||||
mkdir -p "$SRC_DIR"
|
||||
export GIT_TERMINAL_PROMPT=0
|
||||
if [[ -d "${SRC_DIR}/.git" ]]; then
|
||||
git -C "$SRC_DIR" -c advice.detachedHead=false fetch --depth 1 origin tag "$tag" 2>>"$build_log" || true
|
||||
if ! git -C "$SRC_DIR" -c advice.detachedHead=false checkout -f "$tag" >>"$build_log" 2>&1; then
|
||||
rm -rf "$SRC_DIR"
|
||||
git -c advice.detachedHead=false clone --depth 1 --branch "$tag" "$REPO" "$SRC_DIR" >>"$build_log" 2>&1
|
||||
fi
|
||||
else
|
||||
rm -rf "$SRC_DIR"
|
||||
git -c advice.detachedHead=false clone --depth 1 --branch "$tag" "$REPO" "$SRC_DIR" >>"$build_log" 2>&1
|
||||
fi
|
||||
|
||||
cmake -S "$SRC_DIR" -B "${SRC_DIR}/build" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DGGML_CUDA=ON \
|
||||
-DCMAKE_CUDA_ARCHITECTURES="${arch}" \
|
||||
-DLLAMA_BUILD_SERVER=ON \
|
||||
-DLLAMA_BUILD_UI=OFF \
|
||||
-DLLAMA_USE_PREBUILT_UI=OFF \
|
||||
-DGGML_CCACHE=OFF \
|
||||
>>"$build_log" 2>&1
|
||||
|
||||
# Background build + heartbeat (keeps SSH stream alive without 200 cmake lines).
|
||||
cmake --build "${SRC_DIR}/build" -j"$(nproc)" --target llama-server \
|
||||
>>"$build_log" 2>&1 &
|
||||
pid=$!
|
||||
while kill -0 "$pid" 2>/dev/null; do
|
||||
pct="$(grep -oE '\[[[:space:]]*[0-9]+%\]' "$build_log" 2>/dev/null | tail -n1 || true)"
|
||||
line="$(grep -E 'Building CUDA|Built target|Linking' "$build_log" 2>/dev/null | tail -n1 || true)"
|
||||
if [[ -n "$pct" ]]; then
|
||||
log "сборка CUDA ещё идёт… ${pct}${line:+ · ${line}}"
|
||||
else
|
||||
log "сборка CUDA ещё идёт… (cmake/nvcc, см. build.log)"
|
||||
fi
|
||||
sleep 30
|
||||
done
|
||||
if ! wait "$pid"; then
|
||||
log "сборка упала — хвост ${build_log}:"
|
||||
tail -n 40 "$build_log" >&2 || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
local built="${SRC_DIR}/build/bin/llama-server"
|
||||
if [[ ! -x "$built" ]]; then
|
||||
log "сборка не дала ${built}"
|
||||
return 1
|
||||
fi
|
||||
install -m 755 "$built" "$SERVER_BIN"
|
||||
# CUDA build may need libs from build/bin
|
||||
find "${SRC_DIR}/build/bin" -maxdepth 1 -type f \( -name '*.so' -o -name '*.so.*' \) -print0 2>/dev/null \
|
||||
| while IFS= read -r -d '' so; do
|
||||
install -m 755 "$so" "${BIN_DIR}/$(basename "$so")"
|
||||
done
|
||||
chown -R "${SWARM_USER}:${SWARM_USER}" "$BIN_DIR"
|
||||
echo "cuda:${tag}:${arch}" >"$STAMP"
|
||||
chown "${SWARM_USER}:${SWARM_USER}" "$STAMP"
|
||||
log "CUDA binary → ${SERVER_BIN}"
|
||||
return 0
|
||||
}
|
||||
|
||||
normalize_tag() {
|
||||
printf '%s' "$1" | tr -d '\r' | head -n1 | awk 'NF{print; exit}'
|
||||
}
|
||||
|
||||
if [[ -x "$SERVER_BIN" ]]; then
|
||||
log "llama-server уже есть: ${SERVER_BIN}"
|
||||
else
|
||||
if [[ -n "$LLAMACPP_ASSET_URL" ]]; then
|
||||
log "скачиваю llama-server по LLAMACPP_ASSET_URL…"
|
||||
log "скачиваю по LLAMACPP_ASSET_URL…"
|
||||
install_from_archive_url "$LLAMACPP_ASSET_URL"
|
||||
echo "asset-url" >"$STAMP"
|
||||
chown "${SWARM_USER}:${SWARM_USER}" "$STAMP"
|
||||
else
|
||||
if [[ -z "$LLAMACPP_TAG" ]]; then
|
||||
log "WARN: LLAMACPP_TAG/ASSET_URL не заданы — берём latest (нет pin). См. docs/llm.md"
|
||||
log "WARN: LLAMACPP_TAG не задан — latest (см. docs/llm.md)"
|
||||
fi
|
||||
tag="$(resolve_release_tag)"
|
||||
tag="$(printf '%s' "$tag" | tr -d '\r' | head -n1 | awk 'NF{print; exit}')"
|
||||
tag="$(normalize_tag "$(resolve_release_tag)")"
|
||||
if [[ -z "$tag" || "$tag" == *" "* || "$tag" == *"["* ]]; then
|
||||
log "не удалось определить release tag (got: ${tag:-empty})"
|
||||
exit 1
|
||||
fi
|
||||
if ! build_cuda_from_source "$tag"; then
|
||||
log "CUDA-сборка не удалась — fallback на Linux release asset"
|
||||
install_linux_release_fallback "$tag"
|
||||
|
||||
installed=0
|
||||
if [[ "${LLAMACPP_BUILD_CUDA}" == "1" ]]; then
|
||||
log "LLAMACPP_BUILD_CUDA=1 — сразу CUDA-сборка"
|
||||
if build_cuda_from_source "$tag"; then
|
||||
installed=1
|
||||
fi
|
||||
else
|
||||
if install_linux_release "$tag"; then
|
||||
installed=1
|
||||
else
|
||||
log "prebuilt не вышел — крайний случай: CUDA из исходников"
|
||||
if build_cuda_from_source "$tag"; then
|
||||
installed=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [[ "$installed" != "1" ]]; then
|
||||
log "не удалось поставить llama-server"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -292,7 +377,14 @@ else:
|
||||
PY
|
||||
)" || true
|
||||
fi
|
||||
log "llama.cpp -ngl ${NGL} -c ${CTX}"
|
||||
# Explicit overrides from gpu-rent.vars / .env (forwarded by provision).
|
||||
if [[ -n "$LLAMACPP_NGL" ]]; then
|
||||
NGL="$LLAMACPP_NGL"
|
||||
fi
|
||||
if [[ -n "$LLAMACPP_CTX" ]]; then
|
||||
CTX="$LLAMACPP_CTX"
|
||||
fi
|
||||
log "llama.cpp -ngl ${NGL} -c ${CTX} host=${LLAMACPP_HOST} port=${LLAMACPP_PORT}${LLAMACPP_EXTRA_ARGS:+ extra=${LLAMACPP_EXTRA_ARGS}}"
|
||||
|
||||
cat >/etc/systemd/system/${UNIT}.service <<EOF
|
||||
[Unit]
|
||||
@@ -305,7 +397,8 @@ Type=simple
|
||||
User=${SWARM_USER}
|
||||
Group=${SWARM_USER}
|
||||
WorkingDirectory=${LLAMA_ROOT}
|
||||
ExecStart=${SERVER_BIN} ${MODEL_ARG} ${MMPROJ_ARG} --host 127.0.0.1 --port 8080 -ngl ${NGL} -c ${CTX}
|
||||
Environment=LD_LIBRARY_PATH=${BIN_DIR}
|
||||
ExecStart=${SERVER_BIN} ${MODEL_ARG} ${MMPROJ_ARG} --host ${LLAMACPP_HOST} --port ${LLAMACPP_PORT} -ngl ${NGL} -c ${CTX} ${LLAMACPP_EXTRA_ARGS}
|
||||
Restart=on-failure
|
||||
RestartSec=8
|
||||
|
||||
|
||||
Reference in New Issue
Block a user