Skip to content

Instantly share code, notes, and snippets.

@alexander-hanel
Created August 21, 2026 16:24
Show Gist options
  • Select an option

  • Save alexander-hanel/7d45a289d5043e39249e0f750edeca5c to your computer and use it in GitHub Desktop.

Select an option

Save alexander-hanel/7d45a289d5043e39249e0f750edeca5c to your computer and use it in GitHub Desktop.
DeepSeek V4 Flash on DGX Spark

DeepSeek V4 Flash on DGX Spark

run_deepseek_v4_flash_dgx_spark.sh is a standalone installer and launcher for serving DeepSeek V4 Flash on an NVIDIA DGX Spark. It reproduces the model stack used by the StressingLLMs DeepSeek campaign without piping a changing remote installer directly into Bash.

The script pins and verifies:

  • the Entrpi/ds4 v0.6.2 source archive
  • the DeepSeek V4 Flash 0731 Q2 imatrix base GGUF
  • the matching 0731 DSpark Q2K drafter GGUF
  • the CUDA build target for the DGX Spark GB10, sm_121

Requirements

  • NVIDIA DGX Spark with a GB10 GPU and 128 GB unified memory
  • aarch64 Linux
  • CUDA toolkit 13.x with nvcc available
  • approximately 95 GB of downloads
  • at least 110 GiB of free disk space for a first-time installation
  • curl, make, tar, sha256sum, and standard GNU/Linux utilities

The default installation locations are:

~/code/ds4-v0.6.2
~/gguf

Quick Start

Run the launcher from the repository root:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh

If sharing only the script, run it from the directory where it was copied:

bash run_deepseek_v4_flash_dgx_spark.sh

The first run checks the host, downloads and verifies the source and models, builds the CUDA server, starts it, and sends a small smoke-test request. Subsequent runs reuse verified downloads and a compatible existing build.

The server stays in the foreground. Press Ctrl-C to stop it.

Safe Defaults

Setting Default
API address http://127.0.0.1:8888/v1
Model ID deepseek-v4-flash
Context window 262144 tokens
System memory floor 8 GiB
Speculation Matching DSpark drafter enabled
Network exposure Localhost only

The launcher permits context sizes from 4,096 through 524,288 tokens. It deliberately rejects a 1,000,000-token context on the 128 GB Spark because that setting previously caused unsafe memory pressure.

Preview Without Changes

Print the resolved source, model, paths, endpoint, and memory settings without downloading, compiling, or starting anything:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh --dry-run

Install Without Starting the Server

bash scripts/run_deepseek_v4_flash_dgx_spark.sh --install-only

Run the normal command later to start the server.

Common Options

Option Purpose
--ctx TOKENS Set the context window from 4,096 through 524,288 tokens
--host ADDRESS Select the API listen address
--port PORT Select the API listen port
--mem-floor-gb N Reserve 4–32 GiB of system memory from model admissions
--src-dir PATH Select the source and build directory
--gguf-dir PATH Select the model directory
--jobs N Select the number of parallel compilation jobs
--no-dspark Disable DSpark speculative decoding
--rebuild Force recompilation of the pinned source
--install-only Install and verify without starting the server
--skip-host-check Bypass the supported-hardware check for diagnostics
--skip-smoke-test Start without sending the post-start test request
--dry-run Print the resolved configuration without making changes

Use a smaller context window:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh --ctx 131072

Use different installation directories:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh \
  --src-dir /data/src/ds4-v0.6.2 \
  --gguf-dir /data/models

Run plain decoding without downloading or loading the DSpark drafter:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh --no-dspark

Force a clean recompilation of the pinned source:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh --rebuild

Change the port:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh --port 8000

Show every option:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh --help

Network Access

The default binding is localhost because the ds4 API does not provide authentication. To accept connections from another machine:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh \
  --host 0.0.0.0 \
  --port 8888

Protect the port with a host firewall and a trusted network before using 0.0.0.0. Do not expose the unauthenticated endpoint directly to the internet.

Testing the API

List available models:

curl -sS http://127.0.0.1:8888/v1/models

Send a non-thinking chat request:

curl -sS http://127.0.0.1:8888/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "deepseek-v4-flash",
    "messages": [
      {"role": "user", "content": "What is the capital of France?"}
    ],
    "thinking": {"type": "disabled"},
    "max_tokens": 64
  }'

For the StressingLLMs benchmark, configure an OpenAI-compatible provider with:

kind: openai
model: deepseek-v4-flash
base_url: http://127.0.0.1:8888
concurrency: 1

Mirrors and Offline Copies

The script uses immutable source and Hugging Face revisions rather than moving branches. Download URLs, expected sizes, and SHA-256 digests can be overridden when using a trusted mirror:

DS4_SOURCE_URL=https://mirror.example/ds4-v0.6.2.tar.gz \
DS4_SOURCE_SHA256=<source-sha256> \
DS4_BASE_URL=https://mirror.example/deepseek-v4-flash-0731.gguf \
DS4_BASE_SIZE=<base-size-bytes> \
DS4_BASE_SHA256=<base-sha256> \
DS4_DRAFTER_URL=https://mirror.example/dspark-0731.gguf \
DS4_DRAFTER_SIZE=<drafter-size-bytes> \
DS4_DRAFTER_SHA256=<drafter-sha256> \
bash scripts/run_deepseek_v4_flash_dgx_spark.sh

For already-downloaded files, set DS4_GGUF_DIR or pass --gguf-dir and retain the expected filenames. The launcher verifies their exact sizes and hashes before starting.

Troubleshooting

Host validation fails

Confirm that the GPU and CUDA toolkit are visible:

nvidia-smi --query-gpu=name,compute_cap --format=csv,noheader
nvcc --version

The expected GPU is NVIDIA GB10 with compute capability 12.1, and the expected CUDA toolkit is 13.x. --skip-host-check exists for diagnostics on other systems, but those configurations are unsupported.

A download was interrupted

Run the same command again. Downloads use a .part file and resume with HTTP range requests.

A checksum or size check fails

Do not run an unverified model. Move the named file and its .sha256-ok marker out of the model directory, then rerun the launcher so it downloads and verifies a clean copy.

The source directory is non-empty but incomplete

Choose a new empty location:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh \
  --src-dir "$HOME/code/ds4-v0.6.2-clean"

The server runs out of memory

Stop other large models and GPU workloads, keep the default 8 GiB memory floor, and lower the context window:

bash scripts/run_deepseek_v4_flash_dgx_spark.sh --ctx 131072

Do not bypass the launcher's context guard through additional server arguments.

Sources and Licensing

The runtime and published GGUF repositories identify their artifacts as MIT-licensed. DeepSeek retains the base-model copyright and release terms. Review the upstream licenses before redistributing source archives or model files.

#!/usr/bin/env bash
# Install and run the DeepSeek V4 Flash 0731 Q2 stack on an NVIDIA DGX Spark.
#
# This is a standalone, shareable alternative to piping a remote installer into
# Bash. It pins the ds4 source release and both GGUF revisions used by the
# StressingLLMs benchmark, verifies every download, builds for GB10/sm_121, and
# starts an OpenAI-compatible server. The source and model artifacts are MIT
# licensed; DeepSeek retains the base-model copyright and release terms.
#
# Quick start:
# bash run_deepseek_v4_flash_dgx_spark.sh
#
# The first run needs roughly 95 GB of downloads and 110 GiB of free disk.
# Later runs reuse the verified source, binary, and model files.
set -euo pipefail
readonly DS4_VERSION_DEFAULT="v0.6.2"
readonly DS4_SOURCE_URL_DEFAULT="https://github.com/Entrpi/ds4/archive/refs/tags/v0.6.2.tar.gz"
readonly DS4_SOURCE_SHA256_DEFAULT="cd714cb89522b3b19fe26b01b1718787e00368007d10232aca23bc7889fc3771"
readonly BASE_NAME_DEFAULT="DeepSeek-V4-Flash-IQ2XXS-w2Q2K-AProjQ8-SExpQ8-OutQ8-chat-v2-imatrix-0731.gguf"
readonly BASE_REVISION_DEFAULT="86bb38ce2ba7a98ab0e550359fec5f48859dc723"
readonly BASE_REPOSITORY_DEFAULT="antirez/deepseek-v4-gguf"
readonly BASE_SIZE_DEFAULT="86720111488"
readonly BASE_SHA256_DEFAULT="ca22ae2f838e14077c22bc1c1417b71b45b5e5a3687bd96c2ac6e17fdb6261c0"
readonly DRAFTER_NAME_DEFAULT="DSpark-drafter-Q2K-Q8-0731.gguf"
readonly DRAFTER_REVISION_DEFAULT="81c6fdd38f9582da45ba27f0ed7b63bcd3ea3b62"
readonly DRAFTER_REPOSITORY_DEFAULT="bleysg/DeepSeek-V4-Flash-DSpark-drafter-GGUF"
readonly DRAFTER_SIZE_DEFAULT="6971241504"
readonly DRAFTER_SHA256_DEFAULT="8fa269560dc76fd73e4233ad9b1938b5f65dd363381fd9b1a5c6183f7d12d686"
DS4_VERSION="${DS4_VERSION:-$DS4_VERSION_DEFAULT}"
DS4_SOURCE_URL="${DS4_SOURCE_URL:-$DS4_SOURCE_URL_DEFAULT}"
DS4_SOURCE_SHA256="${DS4_SOURCE_SHA256:-$DS4_SOURCE_SHA256_DEFAULT}"
DS4_SRC_DIR="${DS4_SRC_DIR:-$HOME/code/ds4-$DS4_VERSION}"
DS4_GGUF_DIR="${DS4_GGUF_DIR:-$HOME/gguf}"
BASE_NAME="${GGUF_FILE:-$BASE_NAME_DEFAULT}"
BASE_URL="${DS4_BASE_URL:-https://huggingface.co/$BASE_REPOSITORY_DEFAULT/resolve/$BASE_REVISION_DEFAULT/$BASE_NAME}"
BASE_SIZE="${DS4_BASE_SIZE:-$BASE_SIZE_DEFAULT}"
BASE_SHA256="${DS4_BASE_SHA256:-$BASE_SHA256_DEFAULT}"
DRAFTER_NAME="${DSPARK_FILE:-$DRAFTER_NAME_DEFAULT}"
DRAFTER_URL="${DS4_DRAFTER_URL:-https://huggingface.co/$DRAFTER_REPOSITORY_DEFAULT/resolve/$DRAFTER_REVISION_DEFAULT/$DRAFTER_NAME}"
DRAFTER_SIZE="${DS4_DRAFTER_SIZE:-$DRAFTER_SIZE_DEFAULT}"
DRAFTER_SHA256="${DS4_DRAFTER_SHA256:-$DRAFTER_SHA256_DEFAULT}"
CONTEXT_SIZE=262144
HOST_ADDRESS="127.0.0.1"
PORT=8888
MEMORY_FLOOR_GB=8
JOBS="$(nproc 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || echo 8)"
INSTALL_ONLY=0
DRY_RUN=0
SKIP_HOST_CHECK=0
SKIP_SMOKE_TEST=0
USE_DSPARK=1
REBUILD=0
SERVER_ARGS=()
TEMP_DIR=""
SERVER_PID=""
usage() {
cat <<'EOF'
Install and run DeepSeek V4 Flash on an NVIDIA DGX Spark.
Usage:
run_deepseek_v4_flash_dgx_spark.sh [options] [-- ds4-server options]
Options:
--ctx TOKENS Context window (4096..524288; default: 262144)
--host ADDRESS Listen address (default: 127.0.0.1)
--port PORT Listen port (default: 8888)
--mem-floor-gb N Preserve at least N GiB for the OS (default: 8)
--src-dir PATH ds4 source/build directory
--gguf-dir PATH model download directory
--jobs N parallel build jobs
--no-dspark skip the 6.5 GB drafter and use plain decoding
--rebuild rebuild even when the pinned CUDA build is already present
--install-only download, verify, and build without starting the server
--skip-host-check allow non-GB10/non-aarch64 hosts (unsupported)
--skip-smoke-test do not send the post-start "capital of France" request
--dry-run print the resolved setup without downloading or running
-h, --help show this help
Environment overrides for mirrors/offline copies:
DS4_SOURCE_URL, DS4_SOURCE_SHA256, DS4_SRC_DIR, DS4_GGUF_DIR
DS4_BASE_URL, DS4_BASE_SIZE, DS4_BASE_SHA256, GGUF_FILE
DS4_DRAFTER_URL, DS4_DRAFTER_SIZE, DS4_DRAFTER_SHA256, DSPARK_FILE
API after startup:
http://127.0.0.1:8888/v1
model: deepseek-v4-flash
The server runs in the foreground. Press Ctrl-C to stop it.
EOF
}
die() {
echo "error: $*" >&2
exit 1
}
note() {
echo "==> $*" >&2
}
require_value() {
local option="$1"
local value="${2:-}"
[[ -n "$value" ]] || die "$option requires a value"
}
is_integer() {
[[ "$1" =~ ^[0-9]+$ ]]
}
while (($#)); do
case "$1" in
--ctx)
require_value "$1" "${2:-}"
CONTEXT_SIZE="$2"
shift 2
;;
--host)
require_value "$1" "${2:-}"
HOST_ADDRESS="$2"
shift 2
;;
--port)
require_value "$1" "${2:-}"
PORT="$2"
shift 2
;;
--mem-floor-gb)
require_value "$1" "${2:-}"
MEMORY_FLOOR_GB="$2"
shift 2
;;
--src-dir)
require_value "$1" "${2:-}"
DS4_SRC_DIR="$2"
shift 2
;;
--gguf-dir)
require_value "$1" "${2:-}"
DS4_GGUF_DIR="$2"
shift 2
;;
--jobs)
require_value "$1" "${2:-}"
JOBS="$2"
shift 2
;;
--no-dspark)
USE_DSPARK=0
shift
;;
--rebuild)
REBUILD=1
shift
;;
--install-only)
INSTALL_ONLY=1
shift
;;
--skip-host-check)
SKIP_HOST_CHECK=1
shift
;;
--skip-smoke-test)
SKIP_SMOKE_TEST=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
-h|--help)
usage
exit 0
;;
--)
shift
SERVER_ARGS=("$@")
break
;;
*)
die "unknown option: $1 (use --help)"
;;
esac
done
is_integer "$CONTEXT_SIZE" || die "--ctx must be an integer"
((CONTEXT_SIZE >= 4096 && CONTEXT_SIZE <= 524288)) || \
die "--ctx must be between 4096 and 524288; 1,000,000 is unsafe on a 128 GB Spark"
is_integer "$PORT" || die "--port must be an integer"
((PORT >= 1 && PORT <= 65535)) || die "--port must be between 1 and 65535"
is_integer "$MEMORY_FLOOR_GB" || die "--mem-floor-gb must be an integer"
((MEMORY_FLOOR_GB >= 4 && MEMORY_FLOOR_GB <= 32)) || \
die "--mem-floor-gb must be between 4 and 32"
is_integer "$JOBS" || die "--jobs must be an integer"
((JOBS >= 1)) || die "--jobs must be at least 1"
is_integer "$BASE_SIZE" || die "DS4_BASE_SIZE must be an integer"
is_integer "$DRAFTER_SIZE" || die "DS4_DRAFTER_SIZE must be an integer"
[[ "$DS4_SOURCE_SHA256" =~ ^[0-9a-f]{64}$ ]] || die "DS4_SOURCE_SHA256 must be a lowercase SHA-256 digest"
[[ "$BASE_SHA256" =~ ^[0-9a-f]{64}$ ]] || die "DS4_BASE_SHA256 must be a lowercase SHA-256 digest"
[[ "$DRAFTER_SHA256" =~ ^[0-9a-f]{64}$ ]] || die "DS4_DRAFTER_SHA256 must be a lowercase SHA-256 digest"
for argument in "${SERVER_ARGS[@]}"; do
case "$argument" in
-c|--ctx|--ctx=*|-m|--model|--model=*|--host|--host=*|--port|--port=*|\
--mem-floor-gb|--mem-floor-gb=*|--mtp|--mtp=*|--dspark|--dspark=*|\
--no-mtp|--no-dspark|--no-spec)
die "server option $argument is managed by this launcher; use its named option instead"
;;
esac
done
DS4_SRC_DIR="$(realpath -m "$DS4_SRC_DIR")"
DS4_GGUF_DIR="$(realpath -m "$DS4_GGUF_DIR")"
BASE_PATH="$DS4_GGUF_DIR/$BASE_NAME"
DRAFTER_PATH="$DS4_GGUF_DIR/$DRAFTER_NAME"
SERVER_PATH="$DS4_SRC_DIR/ds4-server"
if ((DRY_RUN)); then
cat <<EOF
DeepSeek V4 Flash DGX Spark dry run
ds4 version: $DS4_VERSION
source URL: $DS4_SOURCE_URL
source dir: $DS4_SRC_DIR
base URL: $BASE_URL
base model: $BASE_PATH
DSpark: $([[ "$USE_DSPARK" == 1 ]] && echo enabled || echo disabled)
drafter URL: $DRAFTER_URL
drafter model: $DRAFTER_PATH
endpoint: http://$HOST_ADDRESS:$PORT/v1
context: $CONTEXT_SIZE
memory floor: $MEMORY_FLOOR_GB GiB
install only: $INSTALL_ONLY
EOF
exit 0
fi
for command in curl make tar sha256sum stat df awk realpath nvidia-smi nvcc find; do
command -v "$command" >/dev/null 2>&1 || die "required command not found: $command"
done
check_host() {
local architecture
local gpu_data
local cuda_release
local memory_kib
architecture="$(uname -m)"
gpu_data="$(nvidia-smi --query-gpu=name,compute_cap --format=csv,noheader 2>/dev/null || true)"
cuda_release="$(nvcc --version 2>/dev/null | awk '/release/{gsub(/,/, "", $5); print $5; exit}')"
memory_kib="$(awk '/^MemTotal:/{print $2}' /proc/meminfo)"
note "host: architecture=$architecture gpu=${gpu_data:-unknown} CUDA=${cuda_release:-unknown}"
if ((SKIP_HOST_CHECK)); then
note "host compatibility checks skipped by request"
return
fi
[[ "$architecture" == "aarch64" ]] || die "DGX Spark requires aarch64 (found $architecture)"
[[ "$gpu_data" == *"GB10"* && "$gpu_data" == *"12.1"* ]] || \
die "expected NVIDIA GB10 compute capability 12.1 (found ${gpu_data:-none})"
[[ "$cuda_release" == 13.* ]] || die "CUDA toolkit 13.x is required (found ${cuda_release:-none})"
[[ -n "$memory_kib" && "$memory_kib" -ge 120000000 ]] || \
die "at least 120,000,000 KiB system/unified memory is required"
}
check_disk_space() {
local needed=10737418240
local available_kib
local available
mkdir -p "$DS4_GGUF_DIR"
[[ -f "$BASE_PATH" ]] || needed=$((needed + BASE_SIZE))
if ((USE_DSPARK)) && [[ ! -f "$DRAFTER_PATH" ]]; then
needed=$((needed + DRAFTER_SIZE))
fi
available_kib="$(df -Pk "$DS4_GGUF_DIR" | awk 'NR==2 {print $4}')"
available=$((available_kib * 1024))
((available >= needed)) || \
die "insufficient disk space in $DS4_GGUF_DIR: need $((needed / 1073741824)) GiB including safety margin, have $((available / 1073741824)) GiB"
}
download_file() {
local url="$1"
local destination="$2"
local partial="$destination.part"
if [[ -e "$destination" ]]; then
return 0
fi
note "downloading $(basename "$destination") (resumable)"
curl -fL --progress-meter --retry 5 --retry-all-errors -C - -o "$partial" "$url"
mv "$partial" "$destination"
}
verify_file() {
local path="$1"
local expected_size="$2"
local expected_hash="$3"
local marker="$path.sha256-ok"
local actual_size
local actual_hash
local fingerprint
local expected_marker
[[ -f "$path" ]] || die "missing downloaded file: $path"
actual_size="$(stat -Lc %s "$path")"
[[ "$actual_size" == "$expected_size" ]] || \
die "wrong size for $path: expected $expected_size bytes, found $actual_size; move it aside and rerun"
fingerprint="$(stat -Lc '%s:%Y:%i' "$path")"
expected_marker="$expected_hash $fingerprint"
if [[ -f "$marker" ]] && [[ "$(<"$marker")" == "$expected_marker" ]]; then
note "verified marker: $(basename "$path")"
return
fi
note "verifying SHA-256: $(basename "$path")"
actual_hash="$(sha256sum "$path" | awk '{print $1}')"
[[ "$actual_hash" == "$expected_hash" ]] || \
die "checksum mismatch for $path: expected $expected_hash, found $actual_hash"
printf '%s\n' "$expected_marker" >"$marker"
}
install_source() {
local source_marker="$DS4_SRC_DIR/.source-archive-sha256"
local archive
if [[ -f "$source_marker" && "$(<"$source_marker")" == "$DS4_SOURCE_SHA256" ]]; then
note "reusing ds4 $DS4_VERSION source at $DS4_SRC_DIR"
return
fi
if [[ -d "$DS4_SRC_DIR" && -n "$(find "$DS4_SRC_DIR" -mindepth 1 -maxdepth 1 -print -quit)" ]]; then
die "$DS4_SRC_DIR is non-empty but is not a complete ds4 $DS4_VERSION build; choose --src-dir"
fi
TEMP_DIR="$(mktemp -d)"
archive="$TEMP_DIR/ds4.tar.gz"
note "downloading pinned ds4 source $DS4_VERSION"
curl -fL --progress-meter --retry 5 --retry-all-errors -o "$archive" "$DS4_SOURCE_URL"
echo "$DS4_SOURCE_SHA256 $archive" | sha256sum --check --status || \
die "ds4 source archive checksum mismatch"
mkdir -p "$DS4_SRC_DIR"
tar -xzf "$archive" -C "$DS4_SRC_DIR" --strip-components=1
printf '%s\n' "$DS4_SOURCE_SHA256" >"$source_marker"
}
build_server() {
local build_marker="$DS4_SRC_DIR/.cuda-spark-build-identity"
local compiler_identity
local expected_identity
compiler_identity="$(nvcc --version | sha256sum | awk '{print $1}')"
expected_identity="$DS4_SOURCE_SHA256:$compiler_identity"
if ((!REBUILD)) && [[ -x "$SERVER_PATH" && -f "$build_marker" ]] && \
[[ "$(<"$build_marker")" == "$expected_identity" ]]; then
note "reusing verified CUDA sm_121 build at $SERVER_PATH"
return
fi
note "building ds4 for DGX Spark (CUDA sm_121)"
make -C "$DS4_SRC_DIR" -j"$JOBS" cuda-spark
[[ -x "$SERVER_PATH" ]] || die "build completed without creating $SERVER_PATH"
printf '%s\n' "$expected_identity" >"$build_marker"
}
cleanup() {
local exit_status=$?
trap - EXIT INT TERM
if [[ -n "$SERVER_PID" ]] && kill -0 "$SERVER_PID" 2>/dev/null; then
kill "$SERVER_PID" 2>/dev/null || true
wait "$SERVER_PID" 2>/dev/null || true
fi
if [[ -n "$TEMP_DIR" && -d "$TEMP_DIR" && "$TEMP_DIR" == /tmp/* ]]; then
rm -rf -- "$TEMP_DIR"
fi
exit "$exit_status"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
check_host
check_disk_space
install_source
build_server
download_file "$BASE_URL" "$BASE_PATH"
verify_file "$BASE_PATH" "$BASE_SIZE" "$BASE_SHA256"
if ((USE_DSPARK)); then
download_file "$DRAFTER_URL" "$DRAFTER_PATH"
verify_file "$DRAFTER_PATH" "$DRAFTER_SIZE" "$DRAFTER_SHA256"
fi
if ((INSTALL_ONLY)); then
note "installation complete"
echo "Run this script again without --install-only to start the server."
exit 0
fi
launch=(
"$SERVER_PATH"
--cuda
-m "$BASE_PATH"
-c "$CONTEXT_SIZE"
--host "$HOST_ADDRESS"
--port "$PORT"
--mem-floor-gb "$MEMORY_FLOOR_GB"
)
if ((USE_DSPARK)); then
launch=(
env
DS4_CONT_MTP_MODE=2
DS4_CONT_DSPARK=1
"DS4_DSPARK_MODEL=$DRAFTER_PATH"
"${launch[@]}"
)
else
launch+=(--no-spec)
fi
launch+=("${SERVER_ARGS[@]}")
if [[ "$HOST_ADDRESS" == "0.0.0.0" || "$HOST_ADDRESS" == "::" ]]; then
note "warning: ds4 has no API authentication; firewall port $PORT before binding publicly"
fi
note "starting DeepSeek V4 Flash at http://$HOST_ADDRESS:$PORT/v1 with ctx=$CONTEXT_SIZE"
"${launch[@]}" &
SERVER_PID=$!
if ((SKIP_SMOKE_TEST)); then
wait "$SERVER_PID"
exit $?
fi
HEALTH_HOST="$HOST_ADDRESS"
if [[ "$HEALTH_HOST" == "0.0.0.0" || "$HEALTH_HOST" == "::" ]]; then
HEALTH_HOST="127.0.0.1"
fi
HEALTH_URL="http://$HEALTH_HOST:$PORT/v1/models"
CHAT_URL="http://$HEALTH_HOST:$PORT/v1/chat/completions"
for ((attempt = 1; attempt <= 180; attempt++)); do
kill -0 "$SERVER_PID" 2>/dev/null || die "ds4-server exited during startup"
if curl -fsS --max-time 2 "$HEALTH_URL" >/dev/null 2>&1; then
break
fi
if ((attempt == 180)); then
die "server did not become ready within 15 minutes"
fi
sleep 5
done
note "server is ready; running smoke test"
SMOKE_RESPONSE="$(curl -fsS --max-time 300 \
-H 'Content-Type: application/json' \
-d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"What is the capital of France? Answer with the city only."}],"thinking":{"type":"disabled"},"max_tokens":32,"temperature":0}' \
"$CHAT_URL")"
[[ "$SMOKE_RESPONSE" == *"Paris"* ]] || \
die "server responded, but the smoke test did not contain Paris: $SMOKE_RESPONSE"
note "smoke test passed; server PID $SERVER_PID is running (Ctrl-C to stop)"
wait "$SERVER_PID"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment