From 38b00ff8e9d6e90ed25bbce68b79dba9dbfc7106 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 4 Sep 2026 18:45:47 +0300 Subject: [PATCH] feat: record the attention backend in the run fingerprint It is not an argument of the sampler node, but it decides whether two runs can be identical at all: comfy_kitchen_int8 costs ~10% of the picture between runs with everything else fixed (quantisation flips buckets, which shows up as eyes and mouth changing while the motion stays put), and pytorch is bit-exact. An A/B unknowingly spanning a backend switch compares two different machines. The override function carries its own name now, so the fingerprint can report which backend was live rather than "something overrode it". --- loaders.py | 5 +++++ samplers.py | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/loaders.py b/loaders.py index 965c3c5f..d834a1c0 100644 --- a/loaders.py +++ b/loaders.py @@ -128,6 +128,11 @@ def attention_override(name): def override(_func, *args, **kwargs): return inner(*args, **kwargs) + # Named, so anything downstream can report WHICH backend is live. The attention backend + # decides whether generation is even reproducible (int8 quantisation flips buckets and + # costs ~10% of the picture between identical runs; pytorch is bit-exact), so an A/B that + # unknowingly spans a backend switch is comparing two different machines. + override.funpack_attention_name = str(name) return override diff --git a/samplers.py b/samplers.py index 032199e4..92397537 100644 --- a/samplers.py +++ b/samplers.py @@ -7279,6 +7279,17 @@ class FunPackLTXAVSceneChainSampler: # repeatability check that is really a prompt change reads as "generation is not # reproducible". Cheap stand-in: per-entry shape + mean + std, which differs between # any two real prompts and costs two reductions on an already-resident tensor. + # The attention backend is not an argument of this node, but it decides whether two + # runs can even be identical, so it belongs in the fingerprint next to the ones that + # are. Unknown when nothing overrode it (whatever ComfyUI was launched with). + try: + _att = (model.model_options.get("transformer_options", {}) + .get("optimized_attention_override")) + _run_settings["attention"] = str(getattr(_att, "funpack_attention_name", + "default (as launched)" if _att is None + else "override")) + except Exception: # noqa: BLE001 + pass # NUMBERS, not a formatted string: a string is only ever equal or not, so float wobble # in the encoder reads identically to the conditioning genuinely moving, and every row # says "prompt changed" with no way to tell which. The reader compares these with a