Skip to content

Add Laguna 2.1 models (XS + S) and DFlash vLLM serving mode to llm template - #77

Merged
EBro912 merged 5 commits into
ed/thor-stock-ollamafrom
ed/laguna-dflash
Jul 31, 2026
Merged

Add Laguna 2.1 models (XS + S) and DFlash vLLM serving mode to llm template#77
EBro912 merged 5 commits into
ed/thor-stock-ollamafrom
ed/laguna-dflash

Conversation

@EBro912

@EBro912 EBro912 commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Stacked on #76 (retarget to main once it merges). Supersedes #79, which will be closed as a duplicate once this merges.

What

Three additions to the python/llm template, aimed at Wendy on NVIDIA hardware:

1. Laguna 2.1 models in the picker — Poolside's open-weight agentic-coding MoEs, both pinned to the registry's q4_K_M tag so a scaffolded project gets a known quantisation (the other published tags are too large for the target devices or MLX-only):

Option Total / active params Context Download Device class
laguna-xs-2.1:q4_K_M 33B / 3B 256K 20 GB AGX Orin 32GB or larger
laguna-s-2.1:q4_K_M 118B / 8B 256K 96 GB Thor 128GB class only

#76 already made Laguna run on Thor (stock Ollama image for the laguna architecture, 20m load timeout); measured ~20.6 tok/s warm for the S model on the current 96GB blob. The per-option comments say explicitly which devices don't fit, so the picker never offers a model the device can't load.

2. DFlash speculative decoding for Laguna S — DFlash (lossless block-diffusion drafting, ~2-4x generation speedup) has no Ollama support; its backends are vLLM/SGLang/Transformers/MLX. So the laguna-s-2.1-dflash picker option swaps the backend at scaffold time: Go-template conditionals in docker-compose.yml/wendy.json replace the ollama service with a vllm one serving poolside/Laguna-S-2.1-NVFP4 + its paired 1B DFlash draft behind an OpenAI-compatible API, with Open WebUI pointed at that. Every other pick renders the exact same topology as today.

Key decisions

  • Sentinel picker value (no colon) so it can never be mistaken for an Ollama pull tag.
  • Single multi-arch NGC vLLM image (nvcr.io/nvidia/vllm:26.06-py3), no WENDY_GPU_VENDOR/JETPACK build-arg matrix — this path only targets NVIDIA 128GB-class hardware. Note the JetPack CUDA constraint documented in the README: NGC 26.06+ needs CUDA 13.3+, so on JetPack 7.2 the DFlash pick is blocked until a matching JetPack/NGC pairing exists.
  • gpu-memory-utilization=0.70: vLLM's 0.9 default assumes discrete VRAM and would reserve ~110GB of Thor's 122.8GiB unified memory, starving the OS and WebUI.
  • BF16 draft (~2GB) rather than NVFP4, keeping NVFP4-kernel risk off the draft path; swappable via DFLASH_DRAFT_MODEL.
  • Probe-and-fallback: DFlash support is still landing in upstream vLLM (Add Laguna XS.2.1 DFlash drafter support vllm-project/vllm#46853). The entrypoint greps the installed package and, if support is missing (or a DFlash-enabled launch dies fast), demotes to plain vLLM serving with a loud WARNING — the app works either way, and enabling DFlash later is a one-line image-tag bump. DFLASH_DISABLE=1 forces plain serving.
  • Registry-verified metadata (diverges from Add Laguna 2.1 models to the llm template picker #79 where the registry disagrees): both q4_K_M tags have a 256K context window — the 1M figure belongs to other laguna-s-2.1 tags, not the pinned one — and the S blob is 96GB since its upstream re-publish (was 75GB).

Verification

  • Rendered docker-compose.yml + wendy.json through Go text/template for gemma4:e2b, laguna-xs-2.1:q4_K_M, laguna-s-2.1:q4_K_M, and laguna-s-2.1-dflash: all pass docker compose config and JSON validation; the dflash render has no ollama service/volume, all Ollama picks are byte-equivalent to today's output modulo the model value.
  • bash -n on both entrypoints; template.schema.json validates.
  • Tag sizes/context windows confirmed against ollama.com for both Laguna models; all three poolside HF repos confirmed public (no HF_TOKEN needed).
  • On-device (Jetson AGX Thor, WendyOS 0.18.1): laguna-s-2.1:q4_K_M via Ollama loads in ~26s warm-cache and generates ~20.6 tok/s. The DFlash/vLLM path is ecosystem-blocked on JetPack 7.2 (CUDA 13.2 vs NGC 26.06's CUDA 13.3 torch; see README) — verified the probe-and-fallback logic and documented the constraint instead.
  • Not yet done: on-device run of laguna-xs-2.1 on an AGX Orin; dflash end-to-end on CUDA 13.3+ hardware (DGX Spark).

🤖 Generated with Claude Code

https://claude.ai/code/session_01QFzB4dyWDCpxkmY78oEyRy

EBro912 and others added 2 commits July 24, 2026 21:18
Poolside's open-weight coding MoE (118B total / 8B active). The q4_k_m
tag (75GB, same blob as latest) fits 128GB-class unified-memory targets
only — Jetson AGX Thor and DGX Spark. Runs at ~16 tok/s warm on Thor as
verified in the stock-ollama-for-JetPack-7 change this stacks on, which
also raised OLLAMA_LOAD_TIMEOUT to cover its ~9min cold load.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QFzB4dyWDCpxkmY78oEyRy
Ollama cannot do DFlash speculative decoding (supported backends are
vLLM/SGLang/Transformers/MLX), so the new "laguna-s-2.1-dflash" picker
option swaps the inference backend at scaffold time: template
conditionals in docker-compose.yml and wendy.json replace the ollama
service with a vLLM one serving poolside/Laguna-S-2.1-NVFP4 plus its
paired 1B DFlash draft behind an OpenAI-compatible API, and Open WebUI
is pointed at that instead.

Decisions worth recording:
- Sentinel picker value (no colon) so it can never be mistaken for an
  Ollama pull tag; all other picks render byte-equivalent topology to
  before.
- Single multi-arch NGC vLLM image, no WENDY_GPU_VENDOR/JETPACK matrix:
  this path only targets NVIDIA 128GB-class hardware (Thor, DGX Spark).
- BF16 draft rather than NVFP4: draft memory is negligible next to the
  ~60GB target and it keeps NVFP4-kernel risk off the draft path.
- gpu-memory-utilization 0.70: vLLM's 0.9 default assumes discrete
  VRAM and would starve the OS + WebUI on unified memory.
- DFlash support is probed at startup (upstream support is landing via
  vllm-project/vllm#46853); without it, or on fast failure with it, the
  entrypoint demotes to plain vLLM serving with a loud WARNING, so the
  app works either way. DFLASH_DISABLE=1 forces plain serving.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QFzB4dyWDCpxkmY78oEyRy
@EBro912
EBro912 marked this pull request as draft July 25, 2026 01:23
On-Thor verification of the laguna-s-2.1-dflash pick (JetPack 7.2 /
CUDA 13.2, WendyOS 0.18.1) surfaced three entrypoint bugs and two hard
platform constraints:

- Add --trust-remote-code: the poolside repos ship the Laguna
  architecture as HF custom code, so vLLM exits at startup without it.
- Drop --quantization modelopt: Laguna-S-2.1-NVFP4 is packaged as
  compressed-tensors, not ModelOpt; vLLM refuses the mismatch. Auto-
  detection handles every poolside variant, per the model's vLLM recipe.
- Align with recipes.vllm.ai/poolside/Laguna-S-2.1: poolside_v1
  tool/reasoning parsers, --moe-backend triton with DFlash (replacing
  the forced flash_attn attention backend), num_speculative_tokens 15,
  and an explicit MAX_MODEL_LEN (default 131072) so the KV cache fits
  beside 72GB of weights in the 0.70 unified-memory budget.
- Pin NGC 26.06 and document the constraint matrix: 26.05's vLLM
  (0.20.1) predates Laguna support, while 26.06/26.07 ship torch built
  on CUDA 13.3, which segfaults in cuStreamCreateWithPriority on
  CUDA 13.2 Tegra drivers (no forward compatibility). No current NGC
  tag runs Laguna on JetPack 7.2; 26.06 starts working with a CUDA 13.3
  JetPack. DFlash additionally needs vLLM >= 0.25.1 (the Laguna drafter
  arch), so the probe/demotion fallback to plain vLLM is the expected
  mode until then. PyPI vLLM wheels are no workaround (no sm_110
  kernels).
- Correct download sizes: the Ollama q4_k_m blob is now ~96GB upstream
  (re-published since PR #76's testing) and the NVFP4 repo is ~72GB.

The entrypoint's retry loop, DFlash probe, and fast-fail demotion all
behaved as designed on device. The Ollama picker entry was regression-
verified through the conditional compose: warm-volume deploy served
Laguna at 17.8 tok/s generation (PR #76 baseline: 15.9).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QFzB4dyWDCpxkmY78oEyRy
@EBro912
EBro912 marked this pull request as ready for review July 30, 2026 21:45
Brings this branch in line with PR #79 (which will close as a duplicate
once this merges): laguna-xs-2.1:q4_K_M joins the picker as the AGX Orin
32GB-class Poolside option (33B/3B active, 256K context, 20GB download),
and the README documents which devices fit each Laguna entry.

Details verified against the Ollama registry rather than copied verbatim
from #79: the q4_K_M tags are 20GB (XS) and 96GB (S), both with a 256K
context window (#79's 1M figure belongs to other laguna-s-2.1 tags, not
the pinned one). The S entry's tag now uses the registry's published
q4_K_M casing, and stale pre-republish figures (~75GB weights, ~16 tok/s)
are updated to the measured 96GB blob and ~20 tok/s on Thor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dn2o5uFkddcMH2dfQEDgs3
@EBro912 EBro912 changed the title Add Laguna S 2.1 and DFlash vLLM serving mode to llm template Add Laguna 2.1 models (XS + S) and DFlash vLLM serving mode to llm template Jul 30, 2026

@martien-wdy martien-wdy left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the picker changes and the new serving path. The model metadata here is more accurate than in my own pull request 79. I checked the registry and every tag for the larger Laguna model reports 256K context, not the 1M I had written, so this supersedes mine correctly. My own measurement on Thor came out at 20.73 tokens per second against the roughly 20.6 noted here, which is close agreement from two independent runs.

The template conditional approach looks clean. Verifying that every non DFlash choice renders byte equivalent output is exactly the right property to check when adding conditionals to a shared template, and giving each backend its own volume avoids stale data collisions. The memory limit reasoning for unified memory against the usual discrete card default is a genuinely non obvious trap, caught correctly.

One issue is worth blocking on. On the current JetPack the new backend cannot fail cleanly, it retries forever after a large download while the platform still reports the app as healthy. Details are on the line, along with two smaller robustness points in the same file.

Since this path cannot work on any hardware the team currently has, I would also gently question shipping it as an ordinary picker choice rather than landing the plumbing behind a clearly experimental label. That is a product call, not a code one.

Comment thread python/llm/vllm/entrypoint.sh Outdated
Comment thread python/llm/vllm/entrypoint.sh Outdated
Comment thread python/llm/vllm/entrypoint.sh Outdated
Comment thread python/llm/vllm/entrypoint.sh Outdated
Comment thread python/llm/vllm/entrypoint.sh
Comment thread python/llm/template.schema.json Outdated
@martien-wdy

Copy link
Copy Markdown

Benchmarked both Laguna picks from this PR on a Jetson AGX Thor, so the XS entry now has an on device number too. This covers the "not yet done" item for XS, though on Thor rather than an AGX Orin.

Setup

wendystudio-walter, 128 GB, sm_110, CUDA 13.2, Ollama 0.32.5, all other containers stopped. 200 decoded tokens, num_ctx 2048, temperature 0, seed 42, one discarded warm-up, median of five runs. Figures come from Ollama's own eval_count / eval_duration, measured in-process on the device.

Results

Model Total / active params Decode tok/s Prefill tok/s GPU resident stdev
qwen2.5:3b (reference) 3B dense 62.80 3357 2.08 GB 0.10
laguna-xs-2.1:q4_K_M 33B / 3B 58.83 1249 20.35 GB 0.18
laguna-s-2.1:q4_K_M 118B / 8B 20.73 562 95.99 GB 0.02

100% GPU residency verified for both Laguna runs. The S figure agrees with the ~20.6 tok/s in the PR description, from an independent run.

Worth knowing for the picker text

XS is remarkably strong on Thor. It decodes within 7% of a 3B dense model (58.83 against 62.80) while carrying 11x the total parameters, because it activates about the same 3B per token. Together these three rows show decode throughput tracking active parameters while prefill tracks total ones (3357, 1249, 562). On Thor-class hardware XS arguably deserves a recommendation over S for most uses: near-identical decode speed to a tiny model, at a fifth of the download and a fifth of the memory.

Download and load costs, measured. S reported exactly 96.03 GB, confirming the figure in the picker; it took 68 minutes at ~23 MB/s over wireless. Cold load was 45 seconds, comfortably inside the existing 20 minute timeout, though helped by a page cache warm from the download.

One suggestion for both Ollama entries. Pinning num_ctx matters more here than for any other model in the picker. Left unpinned, Ollama sizes the key/value cache from free memory, and at 96 GB of weights on a 131.9 GB device that can tip into a partial CPU offload, which produces a plausible-looking but wrong throughput number. Might be worth a line in the README so people capacity-planning these models do not get caught by it.

… defaults

The vLLM entrypoint could retry forever on a permanently broken platform
(CUDA-mismatched JetPack) while wendy.json readiness — which only probes
the WebUI port — kept reporting the app healthy, and the demotion branch
only fired when DFlash args were present. Now: a CUDA preflight
(torch.zeros on device, 3 attempts) exits non-zero with a README pointer
before the 72GB download, and five consecutive sub-90s crashes with
nothing left to demote also exit non-zero; the vllm service gains
restart: unless-stopped so those exits surface as a restarting container
with backoff instead of a silent loop. Control flow verified with stubbed
python3/vllm binaries (preflight-fail, demote-then-streak-exit, and
clean-serve paths).

Also from review:
- DFlash probe now checks importlib.find_spec for the drafter's model
  class (vllm.model_executor.models.laguna_dflash) instead of grepping
  the package tree — precise, fast, and inside the if-condition so a
  broken install demotes instead of tripping set -e.
- --trust-remote-code is off by default (opt-in TRUST_REMOTE_CODE=1);
  vLLM's native LagunaConfig/LagunaForCausalLM covers the default repos
  despite their auto_map, so remote code is only needed for swapped-in
  unsupported models.
- vLLM now requires the same wendy-local API key compose already hands
  Open WebUI, so the published :8000 no longer answers unauthenticated.
- The dflash picker entry is labeled experimental and discloses that it
  serves 128K of Laguna's 256K context (MAX_MODEL_LEN budget).
- README/schema carry Martien's on-Thor benchmarks: laguna-xs-2.1 at
  ~59 tok/s decode (near-3B-dense speed, active-params effect), plus a
  num_ctx pinning note for capacity planning on 96GB weights.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dn2o5uFkddcMH2dfQEDgs3
@EBro912

EBro912 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

All six inline threads are addressed in ca09d07; replies with the specifics are on each thread. Summary of what changed beyond the line fixes:

Benchmarks folded in. The XS on-Thor number (~59 tok/s) is now in the picker comment and the README's Thor row, the active-vs-total parameter effect and the prefer-XS-on-Thor guidance are in the README's Laguna section, and the num_ctx pinning advisory is there too, framed exactly as a capacity-planning trap (unpinned KV sizing can tip 96GB of weights into partial CPU offload with plausible-looking throughput). The S decode figures now have two independent runs within 1% of each other (20.6 / 20.73), which is as settled as that number needs to be.

On the experimental question: implemented as a label — the picker option now reads laguna-s-2.1 (DFlash • vLLM, experimental) and its comment leads with "Experimental:". The plumbing ships, nothing hides behind a flag, but nobody picks it thinking it's a supported path on current hardware. If the team would rather gate it harder (or drop the label once a CUDA 13.3 JetPack lands), that's a one-line schema change either way — flagging it for Ethan as the final call.

One benchmark follow-up someone with an AGX Orin could close out: XS's numbers above are from Thor; the 32GB Orin class it's actually aimed at is still unmeasured.

@EBro912
EBro912 merged commit dfbbb09 into ed/thor-stock-ollama Jul 31, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants