Tried running the 118B code-specialized MoE "Laguna S 2.1" on DGX Spark

Tried running the 118B code-specialized MoE "Laguna S 2.1" on DGX Spark

We ran Poolside's agentic coding-specialized model "Laguna S 2.1" on DGX Spark and verified its capabilities in speculative decoding, tool calling, and code editing. Here we report the results, along with the pitfalls in the official recipe and the fastest configuration based on actual measurements.
2026.07.23

This page has been translated by machine translation. View original

Introduction

Hello, I'm Morishige from Classmethod's Manufacturing Business Technology Department.

Poolside, an AI company specializing in agentic coding, released the open-weight MoE model "Laguna S 2.1" on July 21, 2026. With a configuration of 117.6B total parameters and 8.5B active parameters, what catches the eye is that the announcement specifically names "runs on a single DGX Spark" as the target hardware. This may be the first time a code-specialized model exceeding 100B has officially listed the DGX Spark as a supported target.

https://poolside.ai/blog/introducing-laguna-s-2-1

If the official announcement names the hardware, it's only natural to want to verify whether it actually works as described. The day after the announcement, I loaded the official NVFP4 quantized version onto my DGX Spark and tested it across five perspectives: startup conditions, memory, speed, tool calling, and code correction quality. As a bonus, I also looked at Japanese language responses.

To state the conclusion upfront: the official NVFP4 version starts up as-is with vLLM v0.25.1 at 19.5 tok/s standalone, and adding DFlash speculative decoding pushed it up to a maximum of 31.2 tok/s. However, the --moe-backend triton flag from the official recipe does not work as-is, and the optimal speculative depth in my environment was 3 rather than the official default of 15 — results that differ from the recipe in my setup.

As part of the series searching for a partner LLM for DGX Spark, this follows the first article starting with Qwen3.6-27B (2026-07-06), the Qwen3.6-35B-A3B-NVFP4 comparison article (2026-07-13), and the Gemma 4 NVFP4 comparison article (2026-07-18).

This article introduces the actual conditions for running Laguna S 2.1 NVFP4 on a single DGX Spark, along with measured performance that showcases the capabilities of a code-specialized model. I hope it resonates with people using DGX Spark as a development companion.

What Is Laguna S 2.1?

Laguna S 2.1 is an open-weight model specialized for code generation and agentic coding. The family also includes the locally-oriented XS series (33B/A3B) and the flagship M.1 (225B/A23B), with S 2.1 positioned in between.

The architecture is a MoE that selects top-10 from 256 routed experts, with one shared expert. Of the 48 layers, 36 use sliding window attention (window 512) and 12 use global attention, a 3:1 hybrid. The native context length is 1M, but the NVFP4 model card used this time sets it to 262,144.

Official benchmark claims are 70.2% on Terminal-Bench 2.1 and 78.5% on SWE-bench Multilingual. Poolside's assertion is that it's by far the best agentic coding model in its weight class. Since these are self-reported values, it seems best to verify with hands-on tasks.

https://huggingface.co/poolside/Laguna-S-2.1-NVFP4

The variety of distribution formats is a welcome point. In addition to BF16 (approximately 236GB), official FP8, NVFP4, INT4, GGUF, and MLX versions are available from the start. The NVFP4 version intended for DGX Spark is approximately 71GB — my local disk showed 67GiB, which is essentially the same after unit conversion. Additionally, a draft model "DFlash" (approximately 1B) for speculative decoding is distributed in separate repositories by precision level. Since you don't need to create your own quantized versions, you can jump straight into testing after downloading.

The license is OpenMDW-1.1, a permissive license in the Linux Foundation family that allows commercial use and redistribution. It's the same one NVIDIA uses for the Nemotron family. Note that the flagship M.1 uses Apache 2.0, so licenses differ within the family — be careful not to confuse them.

Test Environment and Measurement Conditions

The test environment is as follows. Conditions are aligned with previous articles in the series.

Item Value
Hardware DGX Spark (GB10, aarch64, 128GB unified memory) single unit
Inference engine vLLM v0.25.1 (vllm/vllm-openai:v0.25.1-aarch64 image)
Model poolside/Laguna-S-2.1-NVFP4 (approximately 71GB, 67GiB on disk)
Drafter poolside/Laguna-S-2.1-DFlash-NVFP4 (2.1GiB)
KV cache fp8
max-model-len 65,536 (262,144 for 262K verification only)
gpu-memory-utilization 0.80

Speed is measured as single stream decode tok/s with output length fixed at 256 tokens (median of 3 runs) and aggregate tok/s for 8 concurrent requests. Since the official recipe explicitly states vLLM 0.25.0 or later is required and speculative decoding was verified on 0.25.1, I used the stable v0.25.1 image as-is.

Startup Immediately Hit a Trap in the Official Recipe

First, the basic startup. When I started with the official recipe options --tool-call-parser poolside_v1 --reasoning-parser poolside_v1 --enable-auto-tool-choice, it launched without any issues. The fact that the dedicated poolside_v1 parser is already included in stable v0.25.1 is evidence of solid release coordination and left a very good impression. Japanese responses were normal, and the tool calling smoke test passed on the first try.

Where I stumbled was with speculative decoding. The official recipe's speculative decoding command specifies --moe-backend triton, but adding this flag prevents startup.

ValueError: moe_backend='triton' is not supported for NvFP4 MoE. Expected one of
['cutlass', 'flashinfer_trtllm', 'flashinfer_cutlass', 'flashinfer_cutedsl',
 'flashinfer_b12x', 'marlin', 'humming', 'emulation'].

The NVFP4 MoE path in vLLM v0.25.1 does not accept the triton backend, so pasting the recipe flag as-is results in an immediate rejection for the NVFP4 version. The recipe was probably written for the BF16 or FP8 versions and doesn't apply to the NVFP4 version. The fix is simple: remove the --moe-backend specification entirely and let vLLM choose automatically, after which it started normally including speculative decoding.

So which backend is fastest? I tested three configurations — auto, marlin, and explicitly specified triton — with the following results:

moe-backend single decode tok/s Notes
auto 19.87 Internally selects FLASHINFER_CUTLASS
marlin 19.86 Tied with auto
triton Cannot start due to above ValueError

Auto and marlin were essentially tied within margin of error. What's interesting is what auto resolves to — looking at the serve log, Laguna selects FLASHINFER_CUTLASS. When I ran Qwen3.6-35B under the same auto setting, it selected MARLIN, so the automatic selection answer varies depending on the quantization format and expert configuration. All subsequent measurements were done with auto.

How 118B Fits in 128GB

Let me look at the memory side of "runs on a single DGX Spark." Right after startup with gpu-memory-utilization 0.80, the measured values were: total memory visible to the OS is 121GB, with 107GB used. The difference from the catalog's 128GB comes from unit conversion and reserved regions. In addition to the 67GiB of weights, vLLM allocated a KV cache of 27.11 GiB. Combined with fp8 KV, this gives cache capacity for 977,533 tokens, which means a 65,536-token request can hold up to 14.92 parallel requests.

Startup also succeeded with context extended to 262,144. Even with this setting, KV capacity is 1,114,602 tokens, allowing 4.25 full 262K requests to be held in parallel. Decode speed for short prompts is 19.39 tok/s, unchanged from the 65K setting, so regular use with long context in mind is realistic. Immediately after release, community reports said "1M context is unrealistic, practical limit is 262K," and my conclusion is that 262K as an upper limit works with headroom to spare.

DFlash Speculative Decoding Was Fastest at K=3

Now for the main topic. Speculative decoding is a speedup technique where a small draft model predicts K tokens ahead in bulk, and the main model verifies them all in a single step. If the predictions are correct, multiple tokens advance at once; incorrect ones are discarded. The effectiveness depends on the draft's hit rate and the choice of K.

Laguna comes with a dedicated draft model DFlash, and the official recipe suggests num_speculative_tokens=15, i.e., K=15. Meanwhile, on the NVIDIA Developer Forums on the day of the announcement, there were reports that "spec 15 drops to 10-15 tok/s and is unusable, reducing to 7 gives 40-50 tok/s." I swept K = 3 / 5 / 7 / 11 / 15 under identical conditions to find out which is true. The total acceptance rate in the table is the fraction of tokens proposed by the draft that the main model accepted; average acceptance length is the number of tokens accepted per verification round.

Configuration single tok/s vs base 8-concurrent aggregate draft total acceptance avg acceptance length
base (no speculation) 19.5 91.0
DFlash K=3 31.15 1.60x 121.9 52.1% 1.56/3
DFlash K=5 26.47 1.36x 105.4 35.0% 1.75/5
DFlash K=7 30.42 1.56x 106.7 29.0% 2.03/7
DFlash K=11 22.42 1.15x 97.2 26.3% 2.89/11
DFlash K=15 (official) 29.06 1.49x 91.8 (≒base) 13.6% 2.04/15

Note that the base figure of 19.5 tok/s is from a separate run after restarting the server from the 19.87 in the backend verification — this level of run-to-run variation between serve instances is normal.

Bar chart of single decode speed vs speculative depth K. K=3 is fastest at 31.1 tok/s, with only K=5 and K=11 forming valleys
Single decode speed sweeping K from 3 to 15. Hatched bars indicate configurations where K+1 falls outside CUDA graph capture sizes and padding occurs; only K=5 and K=11 form valleys.

The results differed from both the forum reports and the official recipe. Three things can be said.

First, the official default K=15 doesn't "collapse" entirely, but it's the worst choice among those tested. Single stream shows 29.06 tok/s at 1.49x base, but with 8 concurrent requests, aggregate drops to 91.8 tok/s — nearly identical to the no-speculation baseline of 91.0. The benefit of speculation completely disappears under parallel use. The 10-15 tok/s reported in the forum was not reproduced in my environment, so environmental factors seem significant.

Second, increasing K deeper doesn't meaningfully extend the accepted length. Looking at per-position acceptance rates from /metrics, at K=15 it starts at 67.4% for position 1 and drops below 4.3% from position 8 onward, reaching just 0.8% at position 15. The average acceptance length is essentially flat at 2.03 for K=7 versus 2.04 for K=15, meaning useful accepted depth effectively plateaus at just over 2 tokens. K=11 showed an outlier of 2.89, but its single-stream speed ranked last, so it's not a counterexample. Meanwhile, the cost of one verification step grows proportionally with K, so paying for deeper K without gaining acceptance length is wasteful — increasing throughput with shallower K is more efficient. This is the logic behind K=3 being fastest.

Line chart of per-position draft acceptance rate for K=7 and K=15. Rapid decay from 67% at position 1, nearly zero from position 8 onward
Per-position acceptance rate for K=7 and K=15. Both follow nearly identical curves, with almost no hits from position 8 onward. The structure where deeper K doesn't increase acceptance is clearly visible.

Third, only K=5 and K=11 show unnatural dips. The zigzag pattern of 31.2 (K3) → 26.5 (K5) → 30.4 (K7) → 22.4 (K11) → 29.1 (K15) cannot be explained by acceptance rates alone. The clue was in the serve log. CUDA graphs are a speedup mechanism that pre-records fixed-size computations for replay, and inputs that don't match recorded sizes are padded up to the next recorded size. In vLLM's speculative decoding mode, CUDA graphs run in PIECEWISE mode with capture sizes in the series 1, 2, 4, 8, 16, 24…. The verification step processes draft K tokens plus 1 main model token = K+1 tokens per step, so K=3, 7, and 15 land exactly on capture sizes, while K=5 and 11 waste computation with padding to the next size. This is estimated from config, but it aligns cleanly with the zigzag pattern.

So for using Laguna's DFlash on DGX Spark, it seems best to choose K values where "K+1 lands on a CUDA graph capture size." My recommendation is K=3, with the following startup flags:

vllm serve poolside/Laguna-S-2.1-NVFP4 \
  --speculative-config '{"method":"dflash","model":"poolside/Laguna-S-2.1-DFlash-NVFP4","num_speculative_tokens":3}' \
  --tool-call-parser poolside_v1 --reasoning-parser poolside_v1 --enable-auto-tool-choice \
  --kv-cache-dtype fp8 --max-model-len 65536 --gpu-memory-utilization 0.80

Placed among the models measured in this series, its position looks like this:

Horizontal bar chart of single decode speed on one DGX Spark. Qwen 35B leads at 108.3, Laguna is 5th at 31.1
Comparison with series-measured models. Laguna S 2.1 (★this time) goes from base 19.5 → DFlash K=3 at 31.1 tok/s. vLLM versions differ across measurement periods, ranging from v0.24.0 to v0.25.1.

poolside_v1 Tool Calling Was at a Practical Level

For a model claiming agentic coding, tool calling is critical. I ran 6 single function-call problems and 1 agentic task exploring a pseudo-filesystem with 3 tools, in both thinking and no-thinking modes.

Evaluation item thinking no-thinking
Minimal single call
Selection from 2 tools ❌ tag corruption
Nested args + enum + integer type
Parallel 2 calls in 1 turn ❌ only 1
Japanese instruction + Japanese args
No spurious calls when tools not needed ✅ suppressed ✅ suppressed
Agentic task (bug identification) ✅ 4 turns ✅ 4 turns

Both modes passed 5 of 6 single-call problems. The calls that came back as structured tool_calls all had valid JSON arguments. The one failed case differed by mode: thinking mode reduced parallel 2 calls to just 1, while no-thinking mode had a format error where the calculation tool's call tag corrupted and leaked into the body text. The agentic task correctly reached the bug location in 4 turns in both modes. Since tool_calls arrive structured even in streaming mode, integration into agent frameworks should be straightforward.

One note of caution regarding the reasoning parser: in non-streaming responses, there were cases where thinking content was not separated into reasoning_content and instead mixed into content along with the </think> tag. The impact is limited since tool call extraction works correctly, but apps that display content directly should add preprocessing to be safe.

Code Correction Showdown Against General-Purpose Champion Qwen 35B

Finally, the core task: code correction. Using existing OSS correction tasks risks having answers in the training data, so I created a custom Python mini-repository for this verification. Starting from a 5-file inventory management CLI structure with 3 classic bug types (off-by-one boundary condition, mutable default argument, swallowed exception) — 4 fix locations total — with 5 of 12 pytest tests failing, I gave the model only 3 tools: read_file, write_file, and run_tests, and had it run until all tests passed.

The opponent is Qwen3.6-35B-A3B-NVFP4, which holds the partner LLM position in this series. I ran the same task on the same machine with the same vLLM. Speculative decoding was configured to each model's optimal setup: DFlash K=3 for Laguna, and MTP 3-token lookahead enabled for Qwen. The table shows only thinking mode for Qwen, as I focused on the representative comparison configuration.

Model Result Turns Wall time Generated tokens
Laguna S 2.1 (thinking) 5/5 all fixed 5 41.7 sec 1,176
Laguna S 2.1 (no-thinking) 5/5 all fixed 6 37.4 sec 1,038
Qwen3.6-35B-A3B (thinking) 5/5 all fixed 10 23.4 sec 1,804

For bugs at this scale, both achieved perfect scores. The difference showed in approach. Laguna finished in 5 turns — running tests, reading only the files related to failing tests, fixing all 3 bugs at once, then re-running tests. An efficient, no-waste workflow. Qwen used double the turns (10), with a methodical style of fixing one bug at a time and verifying, but with decode at roughly 88 tok/s — nearly 3x faster than Laguna — it finished in just 23.4 seconds of wall time.

It's a clear contrast: the value of the 118B code-specialized model shows in "fewer steps," while the value of the general-purpose 35B shows in "faster turnaround." For this mini-repo, Qwen won on wall time, but the difference in turns should matter more as tasks grow complex — I can sense a potential reversal for heavy modifications spanning an entire repository. I'd like to verify this in a follow-up with larger-scale tasks.

Incidentally, the infinite loop behavior reported by some immediately after the announcement never occurred once during my testing. I had prepared a 20-turn and 15-minute cutoff guard, but it had no occasion to trigger.

Japanese Works Fine Too

I also checked Japanese proficiency — a series staple — with 4 questions: compliance with a 50-character limit instruction, free-form writing about remote work, code generation for deduplicated sorting, and numerical reasoning about monetary amounts.

Code generation and numerical reasoning were flawless. The free-form writing was natural Japanese at a level suitable for direct business use. On the instruction compliance question, it responded with "東京は日本の首都で、政治・経済の中心地です。世界的な都市として知られています。" (39 characters) and dutifully appended its own "(49 文字)" character count. The count is off, but it properly stayed within the 50-character limit. However, due to the reasoning parser issue mentioned earlier, English thinking text mixed into the content appeared before this correct answer, so mechanical character count checks would produce a false negative. The Japanese capability itself is considerably better than you'd expect from the code-specialized label.

Summary

Laguna S 2.1 NVFP4 ran practically on a single DGX Spark as advertised. The day after the announcement, negative reports about "DFlash acceptance rate being too low" were prominent, but actually getting hands on it revealed that the stumbling points were in recipe details — with proper configuration, it's a model that can hold its own. There's something genuinely moving about a 100B+ code-specialized model fitting on a local machine this easily.

What left the biggest impression while working with it was the efficiency in code correction. Run tests, read only the necessary files, fix everything at once, done. This decisiveness lives up to the code-specialized label, and the prospect of deploying it as a persistent backend for an agent has become realistic.

Next, I'd like to increase the scale of code correction tasks to find the reversal point against Qwen 35B, and try a practical comparison with the reigning resident champion Hermes Agent in real-world use.


AI白書2026 配布中

クラスメソッドが独自に行なったAI診断調査をもとに、企業のAI活用の現在地を調査レポートとしてまとめました。企業規模別の活用度傾向に加え、規模を超えてAI活用を進める企業に共通する取り組みまで、自社の現在地を捉えるためのヒントにぜひ。

AI白書2026

無料でダウンロードする

Share this article