Studio: keep K and V equal when the flash-attention retry resets the V cache by danielhanchen · Pull Request #8827 · unslothai/unsloth · GitHub
Skip to content

Studio: keep K and V equal when the flash-attention retry resets the V cache - #8827

Merged
danielhanchen merged 10 commits into
mainfrom
fix-mla-kv-cache-symmetry
Aug 16, 2026
Merged

Studio: keep K and V equal when the flash-attention retry resets the V cache#8827
danielhanchen merged 10 commits into
mainfrom
fix-mla-kv-cache-symmetry

Conversation

@danielhanchen

Copy link
Copy Markdown
Member

The rule

llama-context.cpp rejects different K and V cache types on an MLA model, and that check sits above the V-quantization check, so it decides first:

if ((model->hparams.is_mla() || model->arch == LLM_ARCH_DEEPSEEK4) && params.type_k != params.type_v) {
    LLAMA_LOG_ERROR("%s: model does not support different K (%s) and V (%s) cache types\n", ...);
    return nullptr;
}

if (ggml_is_quantized(params.type_v) && params.flash_attn_type != LLAMA_FLASH_ATTN_TYPE_ENABLED) {
    ...
    LLAMA_LOG_ERROR("%s: quantized V cache requires flash_attn to be enabled\n", __func__);
    return nullptr;
}

is_mla() covers DeepSeek V2/V3/R1, Kimi K2 and GLM-4.7/5.x, all of which Studio already recognises through kv_lora_rank.

What goes wrong

_reset_quantized_v_cache resets a quantized V cache to f16 and leaves K quantized on purpose: a quantized K needs no flash attention, and resetting it enlarges the cache for nothing. That reasoning predates the MLA rule.

On an MLA model the result is K=q8_0 V=f16, which is a hard abort for a different reason than the one being avoided. The crash-recovery rung exists to recover from a flash-attention failure, and now it cannot start either. Someone on DeepSeek or Kimi with a quantized KV cache hits the FA crash the rung was written for, and the recovery attempt dies on the K/V mismatch.

model before after
MLA, quantized KV K=q8_0 V=f16 (abort) K=f16 V=f16
non-MLA, quantized KV K=q8_0 V=f16 unchanged
any, unquantized KV untouched untouched
MLA, quantized K only untouched untouched

Both axes go to f16 together on MLA. Equal is what the rule asks for, and f16 is the only value that also satisfies the V rule. Non-MLA is untouched, and the parameter defaults to the old behaviour so an un-updated caller keeps today's answer.

Reachability, ranked honestly

  • _with_flash_attn_off, pre-existing. This is the reachable one. It has always produced the asymmetry; the upstream rule turned it fatal.
  • The launch-site reset added in Studio: gate --flash-attn, --no-context-shift and --jinja on the binary #8710. Same helper, fixed by the same change. On a genuine binary it is close to unreachable: -fa landed 2024-04-30 and quantized KV support a month later, so no upstream build has ever accepted a quantized -ctv while lacking --flash-attn. It still matters for a wrapper that hides -fa from --help.

So this is not a regression from #8710. It extended a helper whose K-untouched policy had become unsafe upstream.

A test-harness fix this exposed

_flagless_v_cache_fixup bound the class as self, so the block reading self._kv_lora_rank raised AttributeError inside the harness rather than failing on its merits. It now binds a shim that carries instance state and falls through to the class. Any future self.<attr> in that block will work rather than break the harness.

Tests

10 new. 87 pass in the two suites that own this, 2159 across the llama.cpp, flash-attention, cache-type, launch-flag and Metal suites. Coverage includes the inline = spelling, the draft pair, an unquantized KV (nothing moves), a quantized K alone (the MLA branch must not fire, since no V reset happened), and the non-MLA default.

Three failures in test_video_backend.py and test_video_prequant.py are present on main unchanged.

Not verified

No MLA GGUF was launched against a real llama-server. The upstream rule is read from llama-context.cpp and the behaviour is verified against the shipped code executed directly. Worth a real DeepSeek or Kimi launch before this is trusted end to end.

…V cache

llama-context.cpp rejects different K and V cache types on an MLA model,
and that check sits above the V-quantization one, so it decides first:

    if ((model->hparams.is_mla() || model->arch == LLM_ARCH_DEEPSEEK4)
            && params.type_k != params.type_v) {
        LLAMA_LOG_ERROR("model does not support different K (%s) and V (%s)
                         cache types");
        return nullptr;
    }

is_mla() covers DeepSeek V2/V3/R1, Kimi K2 and GLM-4.7/5.x, all of which
Studio already recognises through kv_lora_rank.

_reset_quantized_v_cache resets a quantized V cache to f16 and leaves K
quantized on purpose, because a quantized K needs no flash attention and
resetting it enlarges the cache for no reason. On an MLA model that leaves
K=q8_0 V=f16, which aborts for a different reason than the one being
avoided: the crash-recovery rung that exists to recover from a
flash-attention failure now fails on the K/V mismatch instead of
recovering. Someone on DeepSeek or Kimi with a quantized KV cache hits the
FA crash the rung was written for, and the recovery cannot start either.

Both axes now go to f16 together on an MLA model. Equal is what the rule
asks for, and f16 is the only value that also satisfies the V rule. Non-MLA
launches are untouched: the size argument for leaving K alone still holds
everywhere else, and the parameter defaults to the old behaviour.

The reachable path is the pre-existing one, _with_flash_attn_off. The
launch-site reset added recently shares the helper and is fixed by the same
change, though on a genuine binary it is close to unreachable: -fa landed
2024-04-30 and quantized KV a month later, so no upstream build has ever
accepted a quantized -ctv while lacking --flash-attn.

Also fixes the test harness this exposed. _flagless_v_cache_fixup bound the
class as `self`, so the block reading self._kv_lora_rank raised
AttributeError in the harness rather than failing on its merits. It now
binds a shim carrying the instance state and falling through to the class,
which is what the block actually runs against.

Tests: 10 new. 87 in the two suites that own this, 2159 across the
llama.cpp, flash-attention, cache-type, launch-flag and Metal suites. The
three video failures are in the origin/main baseline.

Not verified: no MLA GGUF was launched against a real llama-server. The
upstream rule is read from llama-context.cpp and the behaviour is verified
against the shipped code executed directly.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b395dc843

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +11918 to +11920
"--cache-type-k-draft",
"--spec-draft-type-k",
"-ctkd",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep non-MLA draft K caches quantized

When an MLA target uses a separate non-MLA drafter, such as the supported Gemma drafter path, mla is derived only from the target's _kv_lora_rank, but this list also rewrites the drafter's K flags. The K/V equality restriction is evaluated against the drafter's own model, so changing its quantized K cache to f16 is unnecessary and can substantially increase memory use during the flash-attention fallback, potentially turning the recovery into an OOM. Determine MLA status separately for the draft model or exclude draft K flags from the target-MLA rewrite.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Correct, and it is worse than stated in the other direction. Fixed in 9328343.

The target and the drafter are separate models with separate contexts and llama.cpp applies the restriction per context, so gating the draft flags on the target's answer was wrong both ways: an MLA target with a non-MLA drafter needlessly doubles the drafter's K cache, which is the OOM the size argument exists to avoid, and a non-MLA target with an MLA drafter leaves the draft K quantized against an f16 draft V and aborts the draft context outright.

Each side is now gated on its own metadata. Studio already reads the drafter's GGUF via _draft_backend_for for KV sizing, so the drafter's own signal was available. When the drafter cannot be read the draft signal is None and falls back to the target, which is the safe direction: an unnecessary reset costs memory, a missing one aborts.

Comment on lines +15644 to +15647
cmd = self._reset_quantized_v_cache(
cmd,
"this build has no --flash-attn",
mla = self._kv_lora_rank is not None,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include DeepSeek4 in the symmetry signal

For a DeepSeek4 GGUF without attention.kv_lora_rank, this passes mla=False even though the upstream restriction quoted in this change explicitly applies when model->arch == LLM_ARCH_DEEPSEEK4 independently of is_mla(). A quantized-K/V launch that reaches the flash-attention fallback therefore still becomes K=q8_0/V=f16 and aborts instead of recovering. Include self._architecture == "deepseek4" when deriving this signal at every call site.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Confirmed against the upstream source and fixed in 9328343.

The arch term is not redundant with is_mla(). is_mla() is n_embd_head_k_mla_impl and n_embd_head_v_mla_impl both being non-zero (llama-hparams.cpp), and only deepseek2, deepseek32, glm-dsa, kimi-k3 and kimi-linear set those. DeepSeek4 has its own KV cache in llama-kv-cache-dsv4.cpp and sets neither, which is exactly why upstream needed the explicit arch clause.

The converter side confirms the kv_lora_rank probe cannot see it: DeepseekV4Model subclasses TextModel rather than DeepseekV2Model, and add_kv_lora_rank is only called in DeepseekV2Model. DeepSeek4 writes q_lora_rank and attention_output_lora_rank and no kv_lora_rank at all.

_requires_symmetric_kv now mirrors the upstream condition. The sweep carries a deepseek4 model and scores llama.cpp's ground truth separately from what Studio infers, and DeepSeek4 picks up the same 8064 fixed launches as the is_mla() models.

Comment on lines +16575 to +16576
self._with_flash_attn_off(
_last_spawn_cmd, mla = self._kv_lora_rank is not None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve MLA symmetry for environment-only cache types

When an MLA launch inherits equal quantized K/V types through LLAMA_ARG_CACHE_TYPE_K and LLAMA_ARG_CACHE_TYPE_V, this call can only rewrite argv; the recovery block immediately afterward drops the quantized V environment variable while preserving K. The retry consequently runs with K=q8_0 and the default V=f16 and hits the same MLA mismatch abort this change is intended to prevent. On MLA retries, clear the corresponding quantized K environment variable whenever the V variable is cleared, including the draft pair and the flagless-build path.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Correct. This was already fixed in 191c0c4, which landed after the commit this review is anchored to (2b395dc).

_drop_env_quantized_v_cache now takes the K vars down with the V ones, and the argv reset no longer makes the K rewrite conditional on having just reset V there, which covers the argv-K-only shape: -ctk q8_0 on the command line with LLAMA_ARG_CACHE_TYPE_V in the environment, where nothing quantized appears on argv for V so a V-triggered reset never fires. As of 9328343 the draft var is gated on the drafter's own model rather than the target's.

Found independently by the same sweep before the review landed, which is a good sign for both.

pre-commit-ci Bot and others added 4 commits August 14, 2026 14:32
…-only paths

The first pass only lowered the K cache when it had just lowered a quantized V
on argv. A 43k-scenario sweep over [Windows, Linux, WSL, macOS] x [NVIDIA, AMD,
CPU] x [MLA, non-MLA] x KV combinations x flag spellings x env combinations x
main/draft found two shapes that still reached the "model does not support
different K and V cache types" abort:

  - V quantized only through LLAMA_ARG_CACHE_TYPE_V with -ctk q8_0 on argv.
    llama.cpp applies env before parsing argv, so nothing quantized appears on
    argv for V and the V-triggered K reset never fires. The env drop then takes
    V to f16 and leaves K at q8_0.

  - A quantized K env var inherited by the flash-attn-off retry. The drop helper
    deliberately preserved it, which is right off MLA (a quantized K runs fine
    without flash attention and resetting it enlarges the cache) but reintroduces
    the mismatch on MLA.

On this path V always ends up f16 regardless of where it came from, so on MLA the
K reset is no longer conditional on a V reset having happened, and the env drop
takes the K vars down with the V ones. Non-MLA behaviour is unchanged: the sweep
records zero non-MLA outcome differences across all 43008 scenarios.

Sweep result against the merge base: 8064 launches that aborted now start, zero
regressions, and zero remaining aborts where Studio itself introduced the
asymmetry (the base had 3024). The 1008 that still abort are all a user asking
for bf16 against f16 directly, which MLA rejects regardless of Studio.

Also corrects a test that asserted a lone quantized argv K should be preserved on
MLA. That config is not symmetric: V falls back to the f16 default, so llama.cpp
rejects it. Lowering K is what lets the retry start.
Two follow-ups from review, both confirmed against the upstream source.

DeepSeek4 was missed. The restriction is `is_mla() || arch == LLM_ARCH_DEEPSEEK4`
and the arch term is not redundant: is_mla() is n_embd_head_k_mla_impl and
n_embd_head_v_mla_impl both being set, DeepSeek4 sets neither (it has its own KV
cache in llama-kv-cache-dsv4.cpp), and DeepseekV4Model in the converter subclasses
TextModel rather than DeepseekV2Model, so it writes q_lora_rank and
attention_output_lora_rank but never kv_lora_rank. A kv_lora_rank probe therefore
cannot see it, and a quantized-KV DeepSeek4 launch reaching the flash-attention
fallback still aborted. _requires_symmetric_kv now mirrors the upstream condition.

The target and the drafter are separate models with separate contexts, and
llama.cpp applies the restriction per context, so each side is now gated on its
own metadata via _draft_backend_for. Reusing the target's answer was wrong in both
directions: an MLA target with a non-MLA drafter needlessly doubled the drafter's
K cache, which is the OOM the size argument exists to avoid, and a non-MLA target
with an MLA drafter left the draft K quantized against an f16 draft V and aborted
the draft context. When the drafter's GGUF cannot be read the draft signal is None
and falls back to the target, which is the safe direction: an unnecessary reset
costs memory, a missing one aborts.

The sweep now carries a deepseek4 model and scores llama.cpp's ground truth
separately from what Studio infers, so the gap is measured rather than assumed.
Across 64512 scenarios: 16128 launches that aborted now start (8064 MLA, 8064
DeepSeek4), zero regressions, zero non-MLA outcome differences, and zero remaining
aborts where Studio introduced the asymmetry. The 2016 that still abort are a user
asking for bf16 against f16 directly, which the rule rejects regardless.
@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

1 similar comment
@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5fe2efa89d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

"""
target = self._target_kv_symmetry()
draft: Optional[bool] = None
drafter_path = getattr(self, "_mtp_draft_path", None)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Derive symmetry from the drafter that actually launches

When extra_args supplies its own --model-draft/--hf-repo-draft, that model is the drafter loaded by llama.cpp, but this lookup uses only self._mtp_draft_path, which is assigned from launch_mtp_draft_path and may be absent or point to an auto-resolved sidecar that _build_speculative_flags does not emit. Consequently, a non-MLA target with a user-supplied MLA drafter leaves the draft K cache quantized when V is reset and the recovery still aborts; the inverse combination can unnecessarily expand a non-MLA drafter's K cache. The new per-model gating is fresh evidence beyond the earlier comment, but its signal must be derived from the effective draft flag/path in the launch command rather than this stored managed path.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Correct, and the stored path was wrong for a second reason you did not name. Fixed in 0334942.

self._mtp_draft_path is assigned at the end of the launch path, well after the launch-site reset runs, so at that call site it held whatever the previous load left, or nothing at all. So it was stale there even with no extra_args involved.

The signal now comes from the command being launched rather than any stored path, via the existing _extra_args_mtp_draft_source, which already resolves the local and HF draft flags last-wins and falls back to LLAMA_ARG_SPEC_DRAFT_MODEL. _build_speculative_flags emits --model-draft into that same command, so one source covers the managed sidecar and a user-supplied drafter alike, and every call site passes the command it is about to launch or retry. An HF repo id is not a local file whose metadata can be read, so it returns None and falls back to the target, as does an unreadable or absent drafter.

I removed _kv_symmetry_signals rather than leaving it beside the new path, since a second way to derive the same signal is how the stale source got used to begin with.

…mand

The per-model gating read self._mtp_draft_path, which is the wrong source twice
over. It only ever holds the managed sidecar, so an extra_args --model-draft or
--hf-repo-draft, which is the drafter llama.cpp actually loads, was invisible to
it. It is also not assigned until well after the launch-site reset has already
run, so at that call site it held whatever the previous load left, or nothing.

The signal now comes from the command being launched, via the existing
_extra_args_mtp_draft_source, which already resolves the local and Hugging Face
draft flags last-wins and falls back to LLAMA_ARG_SPEC_DRAFT_MODEL. The managed
path emits --model-draft <sidecar> into that same command, so one source covers
both the managed sidecar and a user-supplied drafter, and every call site now
passes the command it is about to launch or retry. A Hugging Face repo id is not
a local file whose metadata can be read, so it yields None and falls back to the
target, as does an unreadable or absent drafter.

_kv_symmetry_signals is removed rather than left beside the new path: a second
way to derive the same signal is how the stale one got used in the first place.

Sweep unchanged at 64512 scenarios: 16128 fixed, zero regressions, zero non-MLA
outcome differences, zero remaining Studio-created asymmetries.
@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5f22931b8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

cmd,
"this build has no --flash-attn",
mla = self._target_kv_symmetry(),
draft_mla = self._draft_kv_symmetry(cmd, env),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Initialize the child environment before inspecting the drafter

When the capability probe authoritatively reports a build without --flash-attn, _flash_attn_known_off is true and this branch executes before env is assigned at line 15759. Because env is a local variable in load_model, evaluating this argument raises UnboundLocalError, so every load through the flagless-build compatibility path fails before spawning llama-server. Construct the child environment before this fixup or pass an already initialized environment view.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Confirmed and fixed in 7e23c97. This one was mine, introduced in 0334942.

Verified with an AST walk over load_model rather than by eye: exactly one Load of env sits before the first Store, at the line this comment is on. The apparent earlier binding a few lines up is a keyword argument (env = _mem_env inside a call), not an assignment, so there is no earlier binding to save it. On a build whose probe authoritatively reports no --flash-attn the branch does execute, so the flagless-build path would raise before llama-server was ever spawned.

The lookup no longer takes env there. os.environ is the correct source at that point anyway, since Studio never rewrites LLAMA_ARG_SPEC_DRAFT_MODEL and the child env is a copy of it plus loader paths.

Worth recording why the tests missed it: the block-extraction harness the flagless tests use seeds env into its exec scope, so it passed while the real function raised. I replaced that with a static check on load_model itself and confirmed it fails on the broken code and passes on the fix, rather than assuming a new test works.

Comment on lines +11989 to +11990
if draft_mla is None:
draft_mla = mla

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reset draft K conservatively when drafter metadata is unknown

When a non-MLA target launches an MLA drafter through --hf-repo-draft, or a local drafter whose metadata cannot be read, _draft_kv_symmetry returns None and this fallback converts it to the target's False. A flash-attention retry then resets the quantized draft V cache to f16 while leaving draft K quantized, causing the drafter context to abort on the K/V mismatch. Fresh evidence after the earlier thread is that the current implementation explicitly returns None for every remote drafter and still maps that unknown result to the target signal; unknown drafters should take the conservative symmetric path instead.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed, fixed in 7e23c97. The implementation contradicted its own stated rationale: the docstring argued that an unnecessary reset only costs memory while a missing one aborts, and then mapped the unknown case to the target's possibly-False answer.

A named drafter whose metadata cannot be read now resolves to True, covering both the Hugging Face repo id and the unreadable local GGUF. None is returned only when no drafter is named at all, where there are no draft flags to reset and the value cannot matter.

This is consistent with the earlier thread rather than a reversal of it: that one was about a KNOWN non-MLA drafter, where the size argument applies and the draft K is left quantized. Only the unknown case takes the conservative path.

…ervative

Two defects in the previous commit.

The launch-site reset passed env to the drafter lookup, but the child environment
is not built until several lines below, and env is a local of load_model. On a
build whose capability probe authoritatively reports no --flash-attn the branch
does execute, so every load through the flagless-build path would raise
UnboundLocalError before llama-server was ever spawned. The lookup no longer takes
env there and falls back to os.environ, which is the correct source at that point
anyway since Studio never rewrites LLAMA_ARG_SPEC_DRAFT_MODEL.

The block-extraction harness the flagless tests use seeds env into its exec scope,
so it passed while the real function raised. The replacement is a static check on
load_model itself, confirmed to fail on the broken code and pass on the fix.

Second, an unknown drafter now takes the conservative symmetric path instead of
the target's answer. A named drafter whose metadata cannot be read, a Hugging Face
repo id or an unreadable GGUF, resolves to True. The two mistakes are not
symmetric: resetting a non-MLA drafter's K needlessly costs memory, while failing
to reset an MLA drafter's K leaves it quantized against an f16 draft V and aborts
the draft context, which is the failure this path exists to prevent. None is now
returned only when no drafter is named at all, where there are no draft flags to
reset and the value cannot matter.

Sweep unchanged: 64512 scenarios, 16128 fixed, zero regressions, zero non-MLA
outcome differences.
@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

1 similar comment
@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

danielhanchen added a commit to shimmyshimmer/unsloth-staging-4 that referenced this pull request Aug 16, 2026
danielhanchen added a commit to shimmyshimmer/unsloth-staging-4 that referenced this pull request Aug 16, 2026
@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

@danielhanchen
danielhanchen merged commit 71aff04 into main Aug 16, 2026
67 of 73 checks passed
@danielhanchen
danielhanchen deleted the fix-mla-kv-cache-symmetry branch August 16, 2026 11:58
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.

1 participant