jcbtc commited on
Commit
eb46b09
·
verified ·
1 Parent(s): b31a987

Add opt-in vision flag, F16 projector, provenance and image smoke validation

Browse files
.gitattributes CHANGED
@@ -6,3 +6,5 @@ assets/qwen38-flash-ciru-strix-iu4.jpg filter=lfs diff=lfs merge=lfs -text
6
  *.png filter=lfs diff=lfs merge=lfs -text
7
 
8
  *.tar.gz filter=lfs diff=lfs merge=lfs -text
 
 
 
6
  *.png filter=lfs diff=lfs merge=lfs -text
7
 
8
  *.tar.gz filter=lfs diff=lfs merge=lfs -text
9
+
10
+ *.mmproj filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -7,7 +7,7 @@ base_model:
7
  - Qwen/Qwen3.8-Flash-Next-FP8
8
  base_model_relation: quantized
9
  library_name: llama.cpp
10
- pipeline_tag: text-generation
11
  inference: false
12
  tags:
13
  - qwen
@@ -28,6 +28,8 @@ tags:
28
  - ple
29
  - long-context
30
  - local-inference
 
 
31
  ---
32
 
33
  [![Qwen3.8 Flash CIRU Strix IU4](https://huggingface.co/jcbtc/Qwen3.8-Flash-CIRU-STRIX-IU4/resolve/v3.0.0/assets/qwen38-flash-ciru-strix-iu4.jpg)](https://llm.ciru.ai/research)
@@ -36,7 +38,7 @@ tags:
36
 
37
  **V3 brings faster long-context serving and the qualified QSA conversation-isolation fixes to the Strix-only runner. Model weights are unchanged.** It adds parallel attention-cell selection, indexed decode attention, cached derived history, guarded PLE lookups and wider prefill. The general profile retains maximum MTP depth 6 and batch/microbatch 1024.
38
 
39
- Use the [v3 source archive](runtime/v3.0.0/ciru-runtime-v3.0.0-source.tar.gz) or [matching GitHub tag](https://github.com/ciru-ai/Qwen3.8-Flash-CIRU-STRIX-IU4/tree/v3.0.0). This text-only package requires the custom CIRU runtime, the target GGUF and all three `ple/` files. The `mtp/` head enables speculative decoding. Stock llama.cpp and Hugging Face hosted inference do not support this package.
40
 
41
  ## V3 serving comparison
42
 
@@ -166,7 +168,7 @@ Including the separate performance probe, the run took **3h 20m 46s**. This is a
166
 
167
  ## Download, build and run
168
 
169
- The unchanged model files total **135,962,881,135 bytes (126.625 GiB)**, excluding runtime and reports. The target is 73.945 GiB, the PLE payload 48.828 GiB and the Q8 MTP head 3.852 GiB. Allow at least 160 GiB for model storage/verification plus SDK and build space. Use fast NVMe and a Strix Halo machine with 128 GiB unified memory.
170
 
171
  On Ubuntu/Debian, install Git and a Python virtual environment, then download the model and build the source:
172
 
@@ -211,6 +213,78 @@ curl http://127.0.0.1:8080/v1/chat/completions \
211
 
212
  These sampling defaults follow the [Qwen model card](https://huggingface.co/Qwen/Qwen3.8-Flash-Next/blob/f5d08274bafd880402bd16f5e3e6c514136ec06c/README.md#best-practices). Ordinary chat can retain prefix caching; the benchmark's cold requests, fixed seed and output cap are measurement controls.
213
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  ## What ships in v3
215
 
216
  V3 combines the previously qualified QSA sequence isolation/indexer-copy fixes with the portable retained hybrid work: wider aligned QSA prefill, J32 expert tiling for supported prefill shapes, radix selection, indexed F16 attention, direct guarded PLE lookup, derived-history caching keyed by sequence and packed tiny F32 gathers. The F32 derived cache adds about 192 MiB at 256K. Hybrid external-GPU ownership, peer transfers, expert splitting, scheduler overlap and experimental compact masks are excluded.
 
7
  - Qwen/Qwen3.8-Flash-Next-FP8
8
  base_model_relation: quantized
9
  library_name: llama.cpp
10
+ pipeline_tag: image-text-to-text
11
  inference: false
12
  tags:
13
  - qwen
 
28
  - ple
29
  - long-context
30
  - local-inference
31
+ - vision
32
+ - image-text-to-text
33
  ---
34
 
35
  [![Qwen3.8 Flash CIRU Strix IU4](https://huggingface.co/jcbtc/Qwen3.8-Flash-CIRU-STRIX-IU4/resolve/v3.0.0/assets/qwen38-flash-ciru-strix-iu4.jpg)](https://llm.ciru.ai/research)
 
38
 
39
  **V3 brings faster long-context serving and the qualified QSA conversation-isolation fixes to the Strix-only runner. Model weights are unchanged.** It adds parallel attention-cell selection, indexed decode attention, cached derived history, guarded PLE lookups and wider prefill. The general profile retains maximum MTP depth 6 and batch/microbatch 1024.
40
 
41
+ Use the [v3 source archive](runtime/v3.0.0/ciru-runtime-v3.0.0-source.tar.gz) or [matching GitHub tag](https://github.com/ciru-ai/Qwen3.8-Flash-CIRU-STRIX-IU4/tree/v3.0.0). This package supports optional image input with the projector and `--vision` launcher below, and requires the custom CIRU runtime, the target GGUF and all three `ple/` files. The `mtp/` head enables speculative decoding. Stock llama.cpp and Hugging Face hosted inference do not support this package.
42
 
43
  ## V3 serving comparison
44
 
 
168
 
169
  ## Download, build and run
170
 
171
+ The unchanged model files total **135,962,881,135 bytes (126.625 GiB)**, excluding runtime, reports, and the optional 904,004,320-byte (0.842 GiB) vision projector. The target is 73.945 GiB, the PLE payload 48.828 GiB and the Q8 MTP head 3.852 GiB. Allow at least 160 GiB for model storage/verification plus SDK and build space. Use fast NVMe and a Strix Halo machine with 128 GiB unified memory.
172
 
173
  On Ubuntu/Debian, install Git and a Python virtual environment, then download the model and build the source:
174
 
 
213
 
214
  These sampling defaults follow the [Qwen model card](https://huggingface.co/Qwen/Qwen3.8-Flash-Next/blob/f5d08274bafd880402bd16f5e3e6c514136ec06c/README.md#best-practices). Ordinary chat can retain prefix caching; the benchmark's cold requests, fixed seed and output cap are measurement controls.
215
 
216
+ ## Enable vision
217
+
218
+ Vision files and the new model-folder launcher are published on `main`; the historical `v3.0.0` tag remains unchanged. After following the build instructions above, return to the directory containing `model/` and `ciru-runtime-v3.0.0/`, then download the additional files:
219
+
220
+ ```bash
221
+ hf download jcbtc/Qwen3.8-Flash-CIRU-STRIX-IU4 \
222
+ --revision main run-server.sh 'vision/*' --local-dir ./model
223
+ (cd model/vision && sha256sum -c SHA256SUMS)
224
+ ```
225
+
226
+ The launcher stays text-only by default. To accept images, add **`--vision`**:
227
+
228
+ ```bash
229
+ RUNTIME_DIR="$PWD/ciru-runtime-v3.0.0" \
230
+ BUILD_DIR="$PWD/ciru-runtime-v3.0.0/build-gfx1151-sdk" \
231
+ bash ./model/run-server.sh --vision
232
+ ```
233
+
234
+ `ENABLE_VISION=1` is equivalent. The flag loads `vision/mmproj-Qwen3.8-Flash-F16.mmproj`; `MMPROJ=/path/to/projector.mmproj` overrides that path. The `.mmproj` file is a **GGUF-format vision projector**, with a filename extension chosen to keep Hub model-size detection focused on the language model. A missing projector produces a clear startup error. Direct runtime launches can pass `--mmproj ./model/vision/mmproj-Qwen3.8-Flash-F16.mmproj` alongside the normal model and PLE arguments.
235
+
236
+ Existing users can download just the updated launcher and vision files:
237
+
238
+ ```bash
239
+ hf download jcbtc/Qwen3.8-Flash-CIRU-STRIX-IU4 \
240
+ run-server.sh 'vision/*' --local-dir ./model
241
+ (cd model/vision && sha256sum -c SHA256SUMS)
242
+ ```
243
+
244
+ Send an image through the server web UI or the OpenAI-compatible chat endpoint. For a local image:
245
+
246
+ ```bash
247
+ python3 - <<'PYIMAGE'
248
+ import base64, json, urllib.request
249
+ from pathlib import Path
250
+ image = base64.b64encode(Path("image.png").read_bytes()).decode()
251
+ payload = {
252
+ "model": "Qwen3.8-Flash-CIRU-STRIX-IU4",
253
+ "messages": [{"role": "user", "content": [
254
+ {"type": "text", "text": "Describe this image."},
255
+ {"type": "image_url", "image_url": {"url": "data:image/png;base64," + image}}
256
+ ]}],
257
+ "chat_template_kwargs": {"enable_thinking": False},
258
+ "max_tokens": 512
259
+ }
260
+ request = urllib.request.Request(
261
+ "http://127.0.0.1:8080/v1/chat/completions",
262
+ data=json.dumps(payload).encode(),
263
+ headers={"Content-Type": "application/json"}
264
+ )
265
+ with urllib.request.urlopen(request, timeout=300) as response:
266
+ print(json.load(response)["choices"][0]["message"]["content"])
267
+ PYIMAGE
268
+ ```
269
+
270
+ The projector was converted to F16 directly from the pinned original Qwen checkpoint using the CIRU v3 converter. It contains 334 tensors. Vision uses additional memory for the projector, image encoding, and image tokens; the text-only performance figures above do not measure vision. [Projector provenance and validation](vision/README.md).
271
+
272
+ ### DeepSeek harness configuration
273
+
274
+ When using this model through the DeepSeek harness, start the server with `--vision` and declare image input in the harness's this model model configuration using `input`:
275
+
276
+ ```yaml
277
+ input:
278
+ - text
279
+ - image
280
+ ```
281
+
282
+ Replace the this model entry's `inputModalities` field with the `input` list above. A user reported that the harness recognized this model image input with this configuration; the native DeepSeek model's `inputModalities` declaration did not work for their this model entry. This is a harness configuration requirement, in addition to loading the projector with `--vision`.
283
+
284
+ ### Image resolution budget
285
+
286
+ The v3 runtime defaults to a maximum of **4,096 visual tokens per image**. Large images are resized to fit while preserving aspect ratio. Each separately submitted image or crop gets its own budget. To allow 8,192 tokens, append `--image-max-tokens 8192` to the vision launch above. `--image-min-tokens 1024` can also be tried for small-detail grounding. Higher budgets consume more memory and context and take longer to process; upscaling cannot recover missing detail. Any resizing performed by the harness before upload still applies.
287
+
288
  ## What ships in v3
289
 
290
  V3 combines the previously qualified QSA sequence isolation/indexer-copy fixes with the portable retained hybrid work: wider aligned QSA prefill, J32 expert tiling for supported prefill shapes, radix selection, indexed F16 attention, direct guarded PLE lookup, derived-history caching keyed by sequence and packed tiny F32 gathers. The F32 derived cache adds about 192 MiB at 256K. Hybrid external-GPU ownership, peer transfers, expert splitting, scheduler overlap and experimental compact masks are excluded.
run-server.sh ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ package_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ repo_root="${RUNTIME_DIR:?Set RUNTIME_DIR to the CIRU v3 source checkout}"
6
+ repo_root="$(cd "$repo_root" && pwd)"
7
+ build_dir="${BUILD_DIR:-${repo_root}/build-gfx1151-sdk}"
8
+ server_bin="${SERVER_BIN:-${build_dir}/bin/llama-server}"
9
+ model_dir="${MODEL_DIR:-${package_root}}"
10
+ model="${model_dir}/Qwen3.8-Flash-CIRU-STRIX-IU4.gguf"
11
+ draft="${model_dir}/mtp/Qwen3.8-Flash-CIRU-STRIX-IU4-MTP-Q8_0.gguf"
12
+ ple_dir="${model_dir}/ple"
13
+ slot_dir="${SLOT_DIR:-${package_root}/slot-state}"
14
+
15
+ # Launcher-only opt-in; remaining arguments are passed to llama-server.
16
+ enable_vision="${ENABLE_VISION:-0}"
17
+ server_args=()
18
+ for arg in "$@"; do
19
+ case "$arg" in
20
+ --vision) enable_vision=1 ;;
21
+ *) server_args+=("$arg") ;;
22
+ esac
23
+ done
24
+ set -- "${server_args[@]}"
25
+ if [[ "$enable_vision" != 0 && "$enable_vision" != 1 ]]; then
26
+ echo "ENABLE_VISION must be 0 or 1." >&2
27
+ exit 2
28
+ fi
29
+ mmproj="${MMPROJ:-${model_dir}/vision/mmproj-Qwen3.8-Flash-F16.mmproj}"
30
+ if [[ "$enable_vision" == 1 && ! -f "$mmproj" ]]; then
31
+ echo "Vision is enabled but its projector is missing: $mmproj" >&2
32
+ echo "Download vision/mmproj-Qwen3.8-Flash-F16.mmproj from the model repository, or set MMPROJ." >&2
33
+ exit 2
34
+ fi
35
+
36
+ # The released shortlist has one shared row map and requires exactly one slot.
37
+ # Include trailing CLI overrides so --parallel/-np cannot bypass this check.
38
+ parallel_slots="${PARALLEL_SLOTS:-1}"
39
+ extra_args=("$@")
40
+ for ((i = 0; i < ${#extra_args[@]}; i++)); do
41
+ case "${extra_args[i]}" in
42
+ --parallel|-np)
43
+ parallel_slots="${extra_args[i+1]:-}"
44
+ ((i += 1))
45
+ ;;
46
+ --parallel=*) parallel_slots="${extra_args[i]#*=}" ;;
47
+ -np=*) parallel_slots="${extra_args[i]#*=}" ;;
48
+ esac
49
+ done
50
+ if [[ "${ENABLE_MTP:-1}" != "0" && "${parallel_slots}" != "1" ]]; then
51
+ echo "The CIRU MTP shortlist requires exactly one slot (--parallel 1)." >&2
52
+ echo "For parallel target-only serving, set ENABLE_MTP=0 and PARALLEL_SLOTS=2." >&2
53
+ echo "See docs/RUNNING.md: Parallel requests and unified KV cache." >&2
54
+ exit 2
55
+ fi
56
+
57
+ for required in "${server_bin}" "${model}" "${ple_dir}/ple.payload.bin" "${ple_dir}/ple.manifest.json" "${ple_dir}/ple.scale.bf16"; do
58
+ if [[ ! -e "${required}" ]]; then
59
+ echo "Required release file is missing: ${required}" >&2
60
+ exit 2
61
+ fi
62
+ done
63
+
64
+ mkdir -p "${slot_dir}"
65
+
66
+ set -a
67
+ # shellcheck source=/dev/null
68
+ source "${repo_root}/profiles/strix-halo-production.env"
69
+ set +a
70
+
71
+ args=(
72
+ --model "${model}"
73
+ --alias Qwen3.8-Flash-CIRU-STRIX-IU4
74
+ --host "${HOST:-127.0.0.1}"
75
+ --port "${PORT:-8080}"
76
+ --jinja
77
+ --ple-sidecar "${ple_dir}"
78
+ --ple-cache-mib "${PLE_CACHE_MIB:-4096}"
79
+ --slot-save-path "${slot_dir}"
80
+ -ngl all
81
+ -sm none
82
+ --fit off
83
+ -c "${CONTEXT_SIZE:-262144}"
84
+ -b "${BATCH_SIZE:-1024}"
85
+ -ub "${UBATCH_SIZE:-1024}"
86
+ --parallel "${PARALLEL_SLOTS:-1}"
87
+ -t "${THREADS:-8}"
88
+ -tb "${BATCH_THREADS:-8}"
89
+ -ctk f16
90
+ -ctv f16
91
+ -fa on
92
+ --cont-batching
93
+ --cache-prompt
94
+ --cache-ram "${PROMPT_CACHE_MIB:-8192}"
95
+ --cache-idle-slots
96
+ --ctx-checkpoints "${CTX_CHECKPOINTS:-32}"
97
+ --checkpoint-min-step "${CHECKPOINT_MIN_STEP:-8192}"
98
+ --temp "${TEMPERATURE:-1.0}"
99
+ --top-p "${TOP_P:-0.95}"
100
+ --top-k "${TOP_K:-20}"
101
+ --min-p "${MIN_P:-0.0}"
102
+ --metrics
103
+ --slots
104
+ )
105
+
106
+ if [[ "$enable_vision" == 1 ]]; then
107
+ args+=(--mmproj "$mmproj")
108
+ fi
109
+
110
+ if [[ "${ENABLE_MTP:-1}" != "0" ]]; then
111
+ if [[ ! -f "${draft}" ]]; then
112
+ echo "MTP is enabled but the draft model is missing: ${draft}" >&2
113
+ exit 2
114
+ fi
115
+ args+=(
116
+ --spec-type draft-mtp
117
+ --spec-draft-model "${draft}"
118
+ --spec-draft-ngl all
119
+ --spec-draft-device "${DRAFT_DEVICE:-ROCm0}"
120
+ --spec-draft-type-k q8_0
121
+ --spec-draft-type-v q8_0
122
+ --spec-draft-threads "${DRAFT_THREADS:-8}"
123
+ --spec-draft-threads-batch "${DRAFT_BATCH_THREADS:-8}"
124
+ --spec-draft-n-max "${MTP_DEPTH:-6}"
125
+ --spec-draft-n-min 0
126
+ --spec-draft-p-min 0.0
127
+ --spec-draft-p-split 0.10
128
+ )
129
+ fi
130
+
131
+ unset GGML_HIP_GRAPH_EXEC_UPDATE CIRU_MTP_GPU_CONFIDENCE CIRU_MTP_GPU_ADAPTIVE CIRU_MTP_GPU_CONF_MIN CIRU_MOE_EXPERT_REUSE CIRU_MTP_TRACE CIRU_MTP_CONF_TRACE LD_PRELOAD
132
+ # Backend discovery must not scan an unrelated working directory.
133
+ cd -- "${repo_root}"
134
+ exec "${server_bin}" "${args[@]}" "$@"
vision/README.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Optional vision projector
2
+
3
+ Enable image input with `bash ./model/run-server.sh --vision` and the same `RUNTIME_DIR` / `BUILD_DIR` used for text serving. `ENABLE_VISION=1` is equivalent. To use a different projector location, set `MMPROJ`.
4
+
5
+ `mmproj-Qwen3.8-Flash-F16.mmproj` is a GGUF-format projector converted directly from [the pinned original Qwen checkpoint](https://huggingface.co/Qwen/Qwen3.8-Flash-Next/tree/f5d08274bafd880402bd16f5e3e6c514136ec06c) with the [CIRU v3 converter](https://github.com/ciru-ai/Qwen3.8-Flash-CIRU-STRIX-IU4/blob/v3.0.0/conversion/qwen4exp.py). Conversion produces 334 tensors, with `clip` architecture, `qwen3vl_merger` projector type, and projection dimension 2560 matching the language model.
6
+
7
+ The `.mmproj` extension avoids confusing Hub model-size detection with a second standalone GGUF model. The runtime reads the GGUF header regardless of filename extension.
8
+
9
+ - Precision: F16 conversion, with converter-selected F32 tensors retained.
10
+ - File size: 904,004,320 bytes.
11
+ - SHA-256: `db643482521c722ff1074afd5018c060ef6ce9b828421c7cfc27b2f235c2569b`.
12
+ - License: the repository's existing Qwen Community License applies.
13
+
14
+ Reproduction, using a local copy of the pinned source checkpoint:
15
+
16
+ ```bash
17
+ python3 ciru-runtime/convert_hf_to_gguf.py /path/to/pinned-qwen-source \
18
+ --mmproj --outtype f16 \
19
+ --outfile mmproj-Qwen3.8-Flash-F16.mmproj
20
+ ```
21
+
22
+ Verify the downloaded file from this directory with `sha256sum -c SHA256SUMS`. [Machine-readable provenance](provenance.json).
23
+
24
+ ## Validation
25
+
26
+ On Ciru (Ryzen AI Max+ 395, gfx1151, 128 GB shared memory, NixOS/ROCm 10), the released launcher loaded this projector with the existing CIRU v3 runtime, a 262,144-token context, one slot, and MTP depth 6. Two separate OpenAI-compatible image requests returned `red square` and `Blue circle` for corresponding synthetic images. These are functional smoke tests, not a vision benchmark or a claim about OCR, detailed reasoning, or video quality. The text-only benchmark tables on the main card remain text-only measurements. [Validation record](validation.json).
27
+
vision/SHA256SUMS ADDED
@@ -0,0 +1 @@
 
 
1
+ db643482521c722ff1074afd5018c060ef6ce9b828421c7cfc27b2f235c2569b mmproj-Qwen3.8-Flash-F16.mmproj
vision/mmproj-Qwen3.8-Flash-F16.mmproj ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:db643482521c722ff1074afd5018c060ef6ce9b828421c7cfc27b2f235c2569b
3
+ size 904003840
vision/provenance.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "source": "Qwen/Qwen3.8-Flash-Next",
3
+ "source_revision": "f5d08274bafd880402bd16f5e3e6c514136ec06c",
4
+ "converter": "CIRU v3 conversion/qwen4exp.py Qwen4ExpVisionModel",
5
+ "outtype": "f16",
6
+ "sha256": "db643482521c722ff1074afd5018c060ef6ce9b828421c7cfc27b2f235c2569b",
7
+ "bytes": 904004320
8
+ }
vision/validation.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "status": "PASS",
3
+ "vision": true,
4
+ "mtp": true,
5
+ "context": 262144,
6
+ "responses": [
7
+ "Red square",
8
+ "Blue circle"
9
+ ],
10
+ "scope": "Two synthetic image grounding smoke tests; not a vision quality benchmark"
11
+ }