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 share the results, along with the pitfalls in the official recipe and the fastest configuration settings 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 an open-weight MoE model called "Laguna S 2.1" on July 21, 2026. With a total parameter count of 117.6B and Active 8.5B, what catches the eye is that the announcement specifically names "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

When the official announcement names specific 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 own DGX Spark and tested it across five dimensions: startup conditions, memory, speed, tool calling, and code correction quality. As a bonus, I also looked at Japanese language responses.

To give 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 doesn't work as-is, and the speculative depth that performed best 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 article 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 presents the actual conditions for running Laguna S 2.1 NVFP4 on a single DGX Spark, along with measured performance that showcases the capabilities unique to a code-specialized model. I hope it resonates with those 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 here sets it to 262,144.

The claimed benchmarks are 70.2% on Terminal-Bench 2.1 and 78.5% on SWE-bench Multilingual. Poolside's claim is that it's by far the best agentic coding model in its weight class. Since these are self-reported values, it's 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 converts to almost exactly the stated size. 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 version, you can jump straight into testing after downloading.

The license is OpenMDW-1.1, a permissive license from the Linux Foundation ecosystem that allows commercial use and redistribution. It's the same one used by NVIDIA for the Nemotron family. Note that the flagship M.1 uses Apache 2.0, so the 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 this series.

Item Value
Hardware DGX Spark (GB10, aarch64, 128GB unified memory) standalone
Inference engine vLLM v0.25.1 (vllm/vllm-openai:v0.25.1-aarch64 image)
Model poolside/Laguna-S-2.1-NVFP4 (approx. 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 with 8 concurrent requests. Since the official recipe specifies vLLM 0.25.0 or higher, with speculative decoding verified on 0.25.1, I used the stable v0.25.1 image as-is.

Hitting the Official Recipe Trap Right at Startup

First, the basic startup. I added the official recipe flags --tool-call-parser poolside_v1 --reasoning-parser poolside_v1 --enable-auto-tool-choice and the server came up without any issues. The fact that the dedicated poolside_v1 parser is already included in stable v0.25.1 is a sign of solid release coordination and made a very good impression. Japanese responses worked normally, and the tool calling smoke test passed on the first try.

Where things went wrong was with speculative decoding. The official recipe's speculative decoding command includes --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 immediate rejection for the NVFP4 version. The recipe was likely written with BF16 or FP8 versions in mind and doesn't apply to NVFP4. The fix is simple: remove the --moe-backend flag entirely and let vLLM auto-select, which allows startup with speculative decoding enabled.

So which backend is fastest? I tested three options — 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 ValueError above

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

How 118B Fits in 128GB

Let's look at the memory side of "runs on a single DGX Spark." Right after startup with gpu-memory-utilization 0.80, the measured OS-visible total memory was 121GB with 107GB in use. The difference from the catalog's 128GB is due to unit conversion and reserved regions. On top of the 67GiB of weights, vLLM allocated 27.11 GiB for KV cache. Combined with fp8 KV, this gives 977,533 tokens of cache capacity — enough to hold up to 14.92 concurrent requests of 65,536 tokens each.

Startup also succeeded with context extended to 262,144. Even with this setting, KV capacity is 1,114,602 tokens, handling 4.25 concurrent 262K full requests. The decode speed for short prompts is 19.39 tok/s, unchanged from the 65K setting, so regular use with long contexts in mind is realistic. Community reports immediately after launch suggested "1M context is impractical, 262K is the practical limit," and the conclusion from my hands-on testing is that 262K is comfortably achievable.

DFlash Speculative Decoding Was Fastest at K=3

Now for the main event. Speculative decoding is a speedup technique where a small draft model predicts K tokens ahead in a batch, and the main model verifies them all in one step. If the predictions are correct, multiple tokens advance at once; incorrect ones are discarded. The effectiveness depends on the draft's accuracy 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 NVIDIA Developer Forums on launch day, reports were flying around saying "spec 15 drops to 10–15 tok/s and is unusable, reducing to 7 gives 40–50 tok/s." To find out which was true, I tested K = 3 / 5 / 7 / 11 / 15 under identical conditions. The acceptance rate in the table is the proportion of tokens proposed by the draft that were accepted by the main model; the average acceptance length is the number of tokens accepted per verification step.

Configuration single tok/s vs base concurrent 8 aggregate draft acceptance rate avg acceptance length
base (no speculative) 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 19.5 tok/s differs slightly from the 19.87 in the backend verification — this is from a separate serve run, and this level of variation between serves is expected.

Bar chart of single decode speed vs. DFlash depth K. K=3 is fastest at 31.1 tok/s, with dips at K=5 and K=11 only
Single decode speed with K swept 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 show dips.

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" but is the worst choice among those tested. It maintains 29.06 tok/s single (1.49x over base), but with 8 concurrent requests the aggregate drops to 91.8 tok/s — nearly identical to the 91.0 without speculative decoding. Under parallel load, the benefit of speculative decoding disappears entirely. The 10–15 tok/s reported in the forum was not reproducible in my environment, suggesting strong environmental factors.

Second, increasing K barely extends the accepted length. Looking at position-by-position acceptance rates from /metrics, at K=15 it starts at 67.4% for the first token and drops below 4.3% from the 8th token onward, reaching 0.8% at position 15. The average acceptance length is 2.03 for K=7 versus 2.04 for K=15 — essentially flat. K=11 was an outlier at 2.89, but its single-token speed ranked last so it's not a counterexample. Meanwhile, the cost of each verification step scales with K, making deeper K a poor trade-off when acceptance length doesn't grow. This is why K=3 is fastest: high rotation beats deep speculation.

Line graph of position-by-position draft acceptance rate for K=7 and K=15. Both drop sharply from ~67% at position 1 to near zero after position 8
Position-by-position acceptance rate for K=7 and K=15. Both curves follow nearly the same trajectory, with almost no acceptance beyond position 8. The structure where deeper K yields no more acceptances is clearly visible.

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

So when using Laguna's DFlash on DGX Spark, choose K from 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, Laguna's position looks like this:

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

The poolside_v1 Tool Calling Reached Practical Standards

For a model claiming agentic coding, tool calling is everything. I ran 6 single function call questions 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
Selecting from 2 tools ❌ tag corruption
Nested args + enum + integer type
Parallel 2 calls in 1 turn ❌ 1 call only
Japanese instruction + Japanese args
No spurious calls when tools unnecessary ✅ suppressed ✅ suppressed
Agentic task (bug identification) ✅ 4 turns ✅ 4 turns

Both modes succeeded on 5 of 6 single-call questions. The calls that came back as structured tool_calls all had valid argument JSON. The one failure differed by mode: thinking mode reduced two parallel calls to one, while no-thinking mode had a format error where the calculation tool's call tags were corrupted and leaked into the body text. The agentic task reached the correct bug location in 4 turns for both modes. Since tool_calls arrive in structured form even with streaming, integration into agent frameworks should be straightforward.

One caveat: the reasoning parser warrants caution. In non-streaming responses, there were cases where the thinking content wasn't separated into reasoning_content and instead mixed into content along with the </think> tag. Tool call extraction works normally so the impact is limited, but apps that display content directly should add pre-processing to be safe.

Code Correction Showdown Against General-Purpose Champion Qwen 35B

Finally, the main job: code correction. Using existing OSS correction tasks risks the answers being in the training data, so I created a custom Python mini-repository for this evaluation. I set up a 5-file inventory management CLI-style repository with three classic bugs planted (off-by-one boundary condition, mutable default argument, swallowed exception) across 4 locations, starting from a state where 5 of 12 pytest tests fail. The model was given only 3 tools — read_file, write_file, and run_tests — and asked to self-correct until all tests passed.

The opponent is Qwen3.6-35B-A3B-NVFP4, currently holding the partner LLM position in this series. I ran the same task on the same machine with the same vLLM. Speculative decoding used the best configuration for each: DFlash K=3 for Laguna, and the bundled MTP 3-token lookahead for Qwen. The table shows Qwen in thinking mode only, as that's the representative configuration for comparison.

Model Result Turns Wall time Tokens generated
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

At this scale of bug fixing, both models scored perfectly. The difference was in approach. Laguna finished in 5 turns: run tests, read only the files related to failing tests, fix 3 bugs together, rerun — a clean, efficient process. Qwen used twice as many turns (10), fixing one bug at a time and confirming each step in a cautious, methodical style. However, with decode speed around 88 tok/s — nearly 3x faster than Laguna — the wall time came in at 23.4 seconds, making it the fastest overall.

Code-specialized 118B's value shows in "fewer moves"; general-purpose 35B's value shows in "faster throughput" — a clear and intuitive contrast. For this mini-repo, Qwen won on wall time, but the difference in turn count should compound as tasks become more complex. For heavy corrections that span an entire repository, Laguna might take the lead. I'd like to verify this in a follow-up with larger-scale tasks.

The infinite loop behavior reported by some immediately after launch did not occur even once in this evaluation. I had set up guards to cut off after 20 turns and 15 minutes, but they were never needed.

Japanese Works Fine Too

I also checked Japanese language capability with the 4 standard questions from this series: following a 50-character limit instruction, open-ended writing about remote work, code generation for deduplication sort, and numerical reasoning about amounts.

Code generation and numerical reasoning were answered correctly without issue. The open-ended writing was in natural Japanese at a level usable directly as business text. For the instruction-following question, the model produced a 39-character answer — "東京は日本の首都で、政治・経済の中心地です。世界的な都市として知られています。" — and diligently appended "(49 characters)" to its own response. The character count is off, but the response is properly within the 50-character limit. However, due to the reasoning parser issue mentioned earlier, English thinking text was mixed into the content before this correct answer, so mechanical character count checks would misfire. The Japanese capability itself is considerably better than you might expect from a code-specialized model.

Summary

Laguna S 2.1 NVFP4 ran practically on a single DGX Spark, just as the official announcement claimed. On the day after launch, negative reports about "DFlash acceptance rate being too low" were prominent, but actually working through it hands-on revealed that the stumbling blocks were in the recipe details, and my honest assessment is that with the right settings this is a model that can fully hold its own. There's something genuinely moving about a 100B+ code-specialized model fitting on a local machine with this level of ease.

What made the biggest impression while working with it was the efficiency in code correction. Run tests, read only the relevant files, fix everything at once, done. This decisiveness is exactly what you'd expect from a model claiming code specialization, and the option of running it as a resident backend for an agent has become a real possibility.

Next, I'd like to scale up the code correction tasks to find the tipping point against Qwen 35B, and try a practical comparison with Hermes Agent for the resident champion title.


AI白書2026 配布中

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

AI白書2026

無料でダウンロードする

Share this article