fix(wan/shared): validate DIFFSYNTH_ATTENTION_IMPLEMENTATION - #15
Conversation
initialize_attention_priority() lowercased the override and returned it unchecked, unlike its sibling WAM_ATTENTION_IMPL, which validates against _BACKEND_MAP and warns when the requested library is missing. Three consequences, all reported in #12: - Naming an uninstalled backend crashed at dispatch. flash_attention_3() dereferences the module-level flash_attn_interface that the try/except import never bound, so DIFFSYNTH_ATTENTION_IMPLEMENTATION=flash_attention_3 on a box without FA3 raised NameError from inside the kernel wrapper. - A typo was accepted silently. attention_forward's else-branch ran it as plain SDPA, so a misspelled backend was indistinguishable from a working one and a whole job could train on SDPA while looking like it had a fused kernel. - The empty string was reachable, because the lookup guarded on `is not None` rather than truthiness, and behaved the same way. It is also why the deploy diagnostics logged a blank backend name. Mirror the sibling: strip and lowercase, raise on a name outside KNOWN_ATTENTION_IMPLEMENTATIONS, and fall back to auto-detection with a warning when the named backend's library did not import. Auto-detection order is unchanged and pinned by a test. Rejecting an unknown name raises at import, since ATTENTION_IMPLEMENTATION is resolved at module scope. That is deliberate: a typo should stop the run rather than quietly downgrade it, and the message names the valid choices. _log_attention_backends already catches the import and reports it per subsystem. Closes #12. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Closing in favour of #14, which does the same job and got here first. My mistake: I picked up #12 and wrote this without checking whether a PR was already open. @rakhimovv had pushed #14 forty minutes earlier — and had said in the issue he was ready to send one, so the fault is entirely on me for not looking. For the record, since it's mildly reassuring rather than embarrassing: the two arrived at the same semantics independently. Both mirror Where they differ, #14 is the better change. It leaves the auto-detection if-chain alone; this branch restructured it into a table-driven loop and then had to add a test pinning the priority order to prove the refactor was inert. Less churn for the same fix. Its test file is also slightly broader — I verified #14 on an H200 before saying any of this, and reviewed it there. Nothing here is worth salvaging except possibly one invariant — a loop asserting every known backend degrades to |
Closes #12. Thanks @rakhimovv for the write-up — I reproduced all three modes before fixing, including the
NameError.Semantics
You asked whether an unrecognized value should raise or warn-and-fall-back. Raise, matching
components.py, which is already the answer for the sibling variable:WAM_ATTENTION_IMPLValueErrorDIFFSYNTH_ATTENTION_IMPLEMENTATION(before)DIFFSYNTH_ATTENTION_IMPLEMENTATION(after)ValueErrorTwo env vars in one codebase behaving differently is its own trap, and the compatibility argument is thin: only five values were ever meaningful, so anyone spelling one correctly is unaffected. Anyone who is not is currently training on SDPA without knowing it, which is the outcome worth breaking loudly.
One consequence worth calling out:
ATTENTION_IMPLEMENTATIONis resolved at module scope, so a rejected name now raises at import rather than at first dispatch. That is deliberate — a typo should stop the run rather than quietly downgrade it, and the message names the valid choices._log_attention_backendsalready wraps the import per subsystem, so diagnostics still degrade toWan shared core : ERROR (...)instead of taking the process down.The three modes, before and after
Verified on Python 3.10,
torch 2.7.1+cu128, H200, with and without the officialflash_attn 2.8.3wheel. FA3 and sage are not installed, which is the ordinary case.1. Uninstalled backend — was a crash at dispatch
2. Typo — was accepted silently
3. Empty string — was reachable via the
is not NoneguardThat also settles the cosmetic you and I went back and forth on in #11 — the deploy report now reads
Wan shared core : torchfor a blank override, with nothing added to the logger. Your call to fix the cause instead was the right one.What changed
initialize_attention_priority()now strips and lowercases the override, rejects a name outsideKNOWN_ATTENTION_IMPLEMENTATIONS, and checks the corresponding*_AVAILABLEflag before honouring it. Auto-detection is unchanged — same priority order, now driven by that tuple rather than an if/elif chain, and pinned by a test so this refactor can't have reshuffled it silently.A valid, installed override still wins over auto-detection (
flash_attention_2requested and present →flash_attention_2;torchrequested with flash-attn installed →torch, i.e. opting out still works).Tests
Six cases in
tests/test_attention_backend_dispatch.py, all CPU-only. Againstorigin/main'sattention.pythey fail 4/6 — the other two pin behaviour that was already correct (a valid available override is honoured; the auto-detection order).🤖 Generated with Claude Code