Skip to content

fix(ai): restore mamba SSM dtype, raise context to 148K, add fallback tier - #4520

Merged
Tanguille merged 5 commits into
mainfrom
fix/qwen38-kv-tuning
Aug 17, 2026
Merged

fix(ai): restore mamba SSM dtype, raise context to 148K, add fallback tier#4520
Tanguille merged 5 commits into
mainfrom
fix/qwen38-kv-tuning

Conversation

@Tanguille

@Tanguille Tanguille commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Follow-ups to #4509, found while reconciling it into production. All four
changes measured on the live engine.

--mamba-ssm-cache-dtype is a separate pool (regression fix)

The simplify pass on #4509 dropped this flag on the theory that it inherits from
--mamba-cache-dtype. It does not, and the mechanism is model-specific:
vllm/model_executor/models/config.py has a Qwen3.5 override that rewrites
auto to the checkpoint's mamba_ssm_dtype, which is float32. The generic
"follow the conv-state dtype" path never applies here.

fp32 SSM state forces the attention block_size from 800 up to 1568, and the
coarser block wastes more pool:

KV tokens concurrency @112k CPU offload tier
with the flag 156,493 1.40x 327 blocks
without 149,333 1.33x 167 blocks

Restoring it recovered exactly the 7,160 tokens. It is silently load-bearing —
the comment now says so.

Context 112K -> 148K, so one session can use the whole pool

maxModelLen is the only per-request cap on KV blocks (max_num_seqs reserves
nothing; max_num_batched_tokens is a compute budget), so at 112000 a single
stream could hold at most 72% of the pool.

Measured at 148000: pool 158,073 tokens (+1,580 from better block rounding),
1.07x concurrency, 28.50 GB VRAM used leaving 5.71 GB free — still above
Jellyfin's ~4.6 GB reservation. One stream now reaches 94% of the pool.

The engine refuses to start if the pool cannot hold one full sequence, so an
over-large value fails fast rather than at runtime. The model allows 262,144
(max_position_embeddings); KV memory is the binding limit.

litellm maxInputTokens follows at 148000 - 8192.

Second fallback tier

omniroute fell back only to qwen-3.8-fast — a single-entry chain on the same
node and GPU. That went hard-down on 2026-08-17 when the 27B was scaled to 0
during the cutover. qwen35-2b runs on a different node's dri device, so it
degrades instead of dropping.

Served-model-name alias

llmkube auto-registers a LiteLLMModel under the InferenceService name, but vLLM
only served qwen-3.8, so that route 404'd at the vLLM hop.

Considered and rejected

  • --language-model-only (+31,000 KV tokens, ~1.0 GiB reclaimed): it never
    loads the vision tower, and karakeep's INFERENCE_IMAGE_MODEL plus hermes'
    auxiliary.vision both use it. Product regression traded for context.
  • --prefix-match-unit 100: proposed on a 0.0% prefix-hit reading that turned
    out to be a cold-start artifact — real traffic runs 30-58%. It also hard-couples
    to block_size: 800, so it would turn a future mamba-flag change into a startup
    failure.
  • int4/int8 per_token_head KV (potentially ~2.7x concurrency): the backend
    advertises support, but correctness/perf on gfx1201 is unverified and int4 KV is
    a real quality risk with tool-calling grammar. Needs an eval, not a config edit.

Verification

  • Hermes end-to-end through litellm, no overrides: PIPELINE OK
  • KV numbers above read from the live engine at each setting
  • All affected kustomize trees build

The omniroute fallback chain had a single entry. When qwen36-27b was
scaled to 0 for this cutover, that entry became a dead model group and
omniroute's intermittent 503s ("all upstream accounts are inactive",
free-tier quota exhaustion) turned into hard failures with nowhere left
to go.

qwen35-2b runs on control-2's dri device rather than control-1's GPU, so
it survives the failure mode that took the chain out.
The operator derives a LiteLLMModel from the InferenceService name and
exposes no field to override it, so the generated group sent
model=qwen38-27b-vllm to a server serving only qwen-3.8. Every call to
that group returned "The model `qwen38-27b-vllm` does not exist"
(verified against live litellm) while kubectl still listed it as a
healthy LiteLLMModel -- the same shape of trap as the fallback that
pointed at a scaled-to-zero deployment.

--served-model-name takes a list and reports the first entry as `model`,
so qwen-3.8 stays primary and the alias only widens what is accepted.
A simplify pass dropped this flag on the theory that it inherits from
--mamba-cache-dtype. Production disagreed: KV fell 156,493 -> 149,333
tokens (1.40x -> 1.33x at 112K) and the CPU offload tier halved from 327
to 167 blocks. Conv-state and SSM-state are separate caches and each
needs its dtype set.
@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Tanguille, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 35 minutes

Limit details: You’ve used all 1 included review currently available under your plan.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1dfa061c-3b9e-4998-a9bb-af6c3b8a1b9c

📥 Commits

Reviewing files that changed from the base of the PR and between a7ca26e and 63727e9.

📒 Files selected for processing (3)
  • kubernetes/apps/ai/litellm/instance/models.yaml
  • kubernetes/apps/ai/litellm/instance/proxy.yaml
  • kubernetes/apps/ai/llmkube/models/qwen38-27b-vllm.yaml

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5cdf2fbb-b088-4b95-bbc2-8fa2ca83e57e

📥 Commits

Reviewing files that changed from the base of the PR and between 85a2e4e and a7ca26e.

📒 Files selected for processing (2)
  • kubernetes/apps/ai/litellm/instance/proxy.yaml
  • kubernetes/apps/ai/llmkube/models/qwen38-27b-vllm.yaml

Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The PR adds qwen35-2b to the LiteLLM fallback chain. It also adds a Qwen vLLM served-model alias and explicitly sets the Mamba SSM cache type to bfloat16.

Changes

AI serving configuration

Layer / File(s) Summary
LiteLLM fallback chain
kubernetes/apps/ai/litellm/instance/proxy.yaml
The fallback chain documents provider failure behavior and adds qwen35-2b after qwen-3.8-fast.
Qwen vLLM model and cache settings
kubernetes/apps/ai/llmkube/models/qwen38-27b-vllm.yaml
The service retains qwen-3.8, adds qwen38-27b-vllm as a served-model alias, and explicitly sets the Mamba SSM cache data type to bfloat16.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to a7ca2

The PR restores the separate cache dtype, adds a fallback on another node, and supports both served-model names. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main changes: restoring the Mamba SSM cache dtype and adding a fallback tier.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/qwen38-kv-tuning

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tanguille-cluster

tanguille-cluster Bot commented Aug 17, 2026

Copy link
Copy Markdown
@@ spec.routerSettings.fallbacks.0.omniroute @@
# litellm.home-operations.com/v1alpha1/LiteLLMProxy/ai/litellm
! + one list entry added:
+ - qwen35-2b

@@ spec.info.maxInputTokens @@
# litellm.home-operations.com/v1alpha1/LiteLLMModel/ai/qwen-3.8
! ± value change
- 103808
+ 139808

@@ spec.info.maxInputTokens @@
# litellm.home-operations.com/v1alpha1/LiteLLMModel/ai/qwen-3.8-fast
! ± value change
- 103808
+ 139808

@@ spec.extraArgs @@
# inference.llmkube.dev/v1alpha1/InferenceService/ai/qwen38-27b-vllm
! + three list entries added:
+ - qwen38-27b-vllm
+ - bfloat16
+ - "--mamba-ssm-cache-dtype"

@@ spec.vllmConfig.maxModelLen @@
# inference.llmkube.dev/v1alpha1/InferenceService/ai/qwen38-27b-vllm
! ± value change
- 112000
+ 148000

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown

AI Automated Review (incremental)

Analysis engine: omniroute@http://litellm.ai.svc.cluster.local/v1 (openai)

Recommendation: Approve. The incremental delta is comment-only tightening plus the already-verified --mamba-ssm-cache-dtype restore; no functional regression.

Change-by-change:

  • qwen38-27b-vllm.yaml: maxModelLen: 148000 and the restored --mamba-ssm-cache-dtype bfloat16 are consistent with the PR body's measured pool (158,073 tokens) and the Qwen3.5 fp32-SSM override rationale. The served-model-name alias (qwen-3.8 + qwen38-27b-vllm) matches the InferenceService metadata.name, as the comment requires.
  • models.yaml: both maxInputTokens: 139808 values correctly equal 148000 - 8192; the "re-derive if that changes" note documents the cross-CRD coupling.
  • proxy.yaml: fallback chain omniroute → [qwen-3.8-fast, qwen35-2b]qwen35-2b exists in kubernetes/apps/ai/llmkube/models/qwen35-2b.yaml and is iGPU-pinned (amd.com/igpu), so it does not share control-1's dGPU, matching the comment.

Standards Compliance: No AGENTS.md convention violated; changes are small, focused, and follow existing patterns.

Unknowns / Needs Verification: The live-engine KV numbers (158,073 tokens, 5.71 GB free vs Jellyfin's ~4.6 GB reservation) and the Hermes end-to-end PIPELINE OK run are asserted in the PR body but not independently verifiable from the repo; I did not re-run them. The qwen35-2b LiteLLMModel registration is operator-derived (not in this diff), so its exact modelName/alias wiring is not confirmed here.

github-actions[bot]

This comment was marked as outdated.

maxModelLen is the only per-request cap on KV blocks -- max-num-seqs
reserves nothing and max-num-batched-tokens is a compute budget -- so at
112000 a single stream could only ever hold 72% of the pool.

Measured live at 148000: pool 158,073 tokens (up 1,580 from better block
rounding), 1.07x concurrency, 28.50 GB VRAM used leaving 5.71 GB free --
still above Jellyfin's ~4.6 GB reservation. One stream now reaches 94%.

The engine refuses to start if the pool cannot hold one full sequence,
so an over-large value fails fast rather than at runtime. The model
allows 262,144; KV memory is the binding limit, not the model.

litellm maxInputTokens follows at 148000 - 8192.
@Tanguille Tanguille changed the title fix(ai): restore mamba SSM cache dtype, add fallback tier and served-model alias fix(ai): restore mamba SSM dtype, raise context to 148K, add fallback tier Aug 17, 2026
The fallback comment named control-2 as qwen35-2b's node, but its
selector is amd.com/igpu which matches control-2 and control-3 -- the
guaranteed property is only that it is never on control-1's dGPU, which
is what the tier relies on.

@github-actions github-actions Bot 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.

Inline findings from the automated review (summary in the sticky comment).

# never shares control-1's dGPU. Degraded, not down.
fallbacks:
- omniroute: ["qwen-3.8-fast"]
- omniroute: ["qwen-3.8-fast", "qwen35-2b"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Info (question): The qwen35-2b fallback target relies on an operator-generated LiteLLMModel whose name/alias wiring is not present in this diff; confirm the generated model group resolves to the llama.cpp qwen3.5-2b alias at runtime.

Automated finding from AI PR review.

@Tanguille
Tanguille merged commit 2fbc060 into main Aug 17, 2026
14 checks passed
@Tanguille
Tanguille deleted the fix/qwen38-kv-tuning branch August 17, 2026 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant