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:
Leonid Pershin
2026-08-21 08:19:37 +03:00
parent ccba40a228
commit 91d2ce0fab
7 changed files with 311 additions and 79 deletions
+157 -64
View File
@@ -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}, 515 мин)…"
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