Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,21 @@ docker run --rm --device /dev/kfd --device /dev/dri \
ghcr.io/luce-org/lucebox-hub:rocm
```

The container picks the GPU the model fits on (a discrete card before an integrated one, else the largest) and sizes the context from that GPU's memory. `serve` is the default command, so `luce_server` flags can follow the image name directly (or `serve`); they replace the values the container would pass. `--target-device`, `--max-ctx` and `--profile` all work:

```bash
# Show the GPUs, the model, and the device auto placement would use
docker run --rm <gpu flags> -v ... ghcr.io/luce-org/lucebox-hub:rocm devices

# DeepSeek V4 on Strix Halo with its qualified profile (DSpark drafter in models/draft/)
docker run --rm <gpu flags> -p 8000:8080 -v ... ghcr.io/luce-org/lucebox-hub:rocm --profile ds4-strix

# Pin a device
docker run --rm <gpu flags> -p 8000:8080 -v ... ghcr.io/luce-org/lucebox-hub:rocm --target-device hip:1
```

Environment variables such as `LUCE_TARGET`, `LUCE_TARGET_DEVICE`, `LUCE_MAX_CTX` and `LUCE_ARGS` cover the same settings for compose files; see the header of [`server/scripts/entrypoint.sh`](server/scripts/entrypoint.sh).

## Run the Server

This quick start runs the R9700 profile above. The complete flag reference is in the [server guide](server/README.md#server-parameter-reference).
Expand Down
23 changes: 11 additions & 12 deletions docs/image-input.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,27 @@ hf download Lucebox/DeepSeek-V4-Flash-0731-ROCmFP3 \
hf download Lucebox/DeepSeek-V4-Flash-0731-DSpark-GGUF \
DeepSeek-V4-Flash-0731-DSpark-draft-Q4RMFP4-denseF16.gguf --local-dir models

LUCE_DS4_SPEC=1 \
LUCE_DS4_DRAFT=models/DeepSeek-V4-Flash-0731-DSpark-draft-Q4RMFP4-denseF16.gguf \
LUCE_DS4_SPARSE_DECODE_FLASH=1 \
./server/build-hip/luce_server models/DeepSeek-V4-Flash-Vision-Exp-ROCMFPX-MIX-STRIX.gguf \
--target-device hip:0 --max-ctx 131072 --chunk 8192 \
--cache-type-k q4_0 --cache-type-v q4_0 \
--ds4-fused-decode --ds4-fused-verify-f16-kv \
--ds4-expert-top-k 6 --ds4-prefill sparse \
--draft models/DeepSeek-V4-Flash-0731-DSpark-draft-Q4RMFP4-denseF16.gguf \
--target-device auto --profile ds4-strix \
--mmproj models/DeepSeek-V4-Flash-Vision-Exp-mmproj-BF16.gguf \
--port 8216
```

`hip:0` must be the Strix Halo; on a host with a discrete GPU too, expose the
Strix Halo alone with `HIP_VISIBLE_DEVICES`. This is the text model's published
launch plus `--mmproj`: the Vision file replaces
The model must run on the Strix Halo. `--target-device auto` picks it when the
discrete GPU cannot hold the model, as with an R9700 (32 GB); with a larger
discrete GPU, name the Strix Halo with `--target-device hip:N` instead
(`luce_server --list-devices` shows the choice).
This is the text model's published launch (`--profile ds4-strix`) plus `--mmproj`: the Vision file replaces
`DeepSeek-V4-Flash-0731-ROCMFPX-MIX-STRIX.gguf` for text as well and decodes
at least as fast (numbers below). For R9700 + Strix Halo see [DS4V](#ds4v) below.

With an R9700 in the same box, run the image encoder there while the model
stays on the Strix Halo: expose both GPUs, point `--target-device` at the Strix
Halo and add `--mmproj-device` with the R9700 (on lucebox6, without
`HIP_VISIBLE_DEVICES`, that is `--target-device hip:1 --mmproj-device hip:0`).
stays on the Strix Halo: expose both GPUs and add `--mmproj-device` with the
R9700. `--target-device auto` already puts the model on the Strix Halo (on
lucebox6, without `HIP_VISIBLE_DEVICES`, that is `hip:1`, so add
`--mmproj-device hip:0`).
The encoder then runs about twice as fast and streams each image into prefill
as soon as it is encoded, so the Strix Halo never waits for the next one:

Expand Down
16 changes: 9 additions & 7 deletions server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ add_library(luce_common STATIC
src/common/backend_factory.cpp
src/common/feature_gate.cpp
src/placement/placement_config.cpp
src/placement/device_select.cpp
src/common/layer_split_utils.cpp
src/common/ddtree.cpp
src/common/peer_access.cpp
Expand Down Expand Up @@ -1966,15 +1967,15 @@ if(LUCE_TESTS)
list(APPEND _raw_unit_test_targets test_moe_input_ready)
endif()

# The production CUDA and ROCm images share this entrypoint. Keep native
# server defaults intact unless an operator explicitly supplies an env
# override; otherwise container launches can silently disable features
# that are enabled by the C++ server itself.
if(UNIX AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/test_entrypoint_cache_defaults.sh")
# The production CUDA and ROCm images share this entrypoint. The test
# drives it against a fake luce_server: native defaults stay with the
# server, operator flags pass through and win, and device, context and
# draft choices follow the probed hardware and model architecture.
if(UNIX AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/test_entrypoint.sh")
add_test(
NAME server_unit_entrypoint_cache_defaults
NAME server_unit_entrypoint
COMMAND bash
"${CMAKE_CURRENT_SOURCE_DIR}/test/test_entrypoint_cache_defaults.sh"
"${CMAKE_CURRENT_SOURCE_DIR}/test/test_entrypoint.sh"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/entrypoint.sh")
endif()

Expand Down Expand Up @@ -2245,6 +2246,7 @@ if(LUCE_TESTS)
add_executable(test_feature_gate test/test_feature_gate.cpp)
target_sources(test_feature_gate PRIVATE
test/test_backend_plan.cpp
test/test_launch_policy.cpp
src/common/backend_plan.cpp
src/common/feature_gate.cpp
src/kv_quant.cpp
Expand Down
15 changes: 10 additions & 5 deletions server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,21 @@ RTX mixed-hardware notes before running long prompts.

The command shape is `luce_server <model.gguf> [options]`. The first positional argument selects the target weights. `--model-name` only changes the name reported by the API; it does not select a model file.

`luce_server --list-devices [model.gguf]` prints every GPU with its `backend:N` index, architecture and memory, and, given a model, the device `--target-device auto` would choose.

`--profile <name>` applies a qualified hardware and model configuration: `ds4-strix` (DeepSeek V4 on Strix Halo) or `ds4-r9700-strix` (DeepSeek V4 with experts split between an R9700 and Strix Halo). Flags on the command line replace the profile's value, and environment variables that are already set keep theirs. The startup log lists what the profile applied.

### Core server

| Option | Default | Purpose |
|---|---|---|
| `--draft <path>` | none | Draft model for speculative decode. |
| `--draft <path>` | none | Draft model for speculative decode: DFlash for Qwen, Gemma and Laguna, DSpark for DeepSeek V4. |
| `--host <addr>` | `0.0.0.0` | Bind address. |
| `--port <N>` | `8080` | Listen port. |
| `--max-ctx <N>` | `131072` | Maximum context length. |
| `--max-ctx <N>` | `8192` | Maximum context length. |
| `--max-tokens <N>` | model card | Legacy alias for `--default-max-tokens`. |
| `--default-max-tokens <N>` | model card or `16000` | Output cap when a request omits a token limit. |
| `--model-name <name>` | `dflash` | API alias returned by `/v1/models` and responses. It does not change the loaded weights. |
| `--model-name <name>` | `luce` | API alias returned by `/v1/models` and responses. It does not change the loaded weights. |
| `--chat-template-file <path>` | model default | Jinja chat-template override. |
| `--no-cors` | CORS enabled | Disable CORS headers. |

Expand All @@ -263,8 +267,9 @@ The command shape is `luce_server <model.gguf> [options]`. The first positional

| Option | Default | Purpose |
|---|---|---|
| `--target-device <backend:gpu>` | `auto:0` | Place the target on a CUDA or HIP device. |
| `--draft-device <backend:gpu>` | `auto:0` | Place the draft on a CUDA or HIP device. |
| `--target-device <backend:gpu\|auto>` | `auto:0` or `LUCE_TARGET_DEVICE` | Place the target on a CUDA or HIP device. `auto` picks a GPU the model fits on (discrete before integrated, then the lowest index), else the largest GPU. |
| `--draft-device <backend:gpu>` | `auto:0` | Place the draft on a CUDA or HIP device. DeepSeek V4 and `--target-device auto` default to the target GPU. |
| `--expert-device <backend:gpu>` | none | DeepSeek V4: keep dense work and hot experts on the target and run the remaining routed experts on this GPU in the same process. |
| `--target-devices <list>` | one device | Select multiple target devices, such as `cuda:0,cuda:1`. |
| `--target-split-mode layer\|tensor` | `layer` | Select the multi-GPU target strategy. |
| `--target-layer-split <weights>` | none | Optional layer-split weights. |
Expand Down
Loading
Loading