From 8e7e69d50c9032a72dad06e6e0d9db290d6c2180 Mon Sep 17 00:00:00 2001 From: Log-Dog012 <219435222+Log-Dog012@users.noreply.github.com> Date: Thu, 23 Jul 2026 18:45:01 +0800 Subject: [PATCH] fix(ops): dequantize GGUF GGMLTensor weights in cast_bias_weight comfy.ops.cast_bias_weight only dequantized QuantizedTensor weights. GGUF stores quantized weights as a custom GGMLTensor subclass, so it slipped through un-dequantized and its block-packed storage reached F.linear with the wrong shape, crashing generate() on GGUF text encoders (e.g. Qwen2.5-VL). Dequantize any weight exposing a duck-typed dequantize() method so the real (un-packed) shape is what downstream matmul sees. This lets GGUF weights use the same generic cast path as normal and QuantizedTensor weights without core having to import GGUF types. --- comfy/ops.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/comfy/ops.py b/comfy/ops.py index 13c2604fb74..d8c76a58249 100644 --- a/comfy/ops.py +++ b/comfy/ops.py @@ -366,6 +366,21 @@ def format_return(result, offloadable): comfy.model_management.sync_stream(device, offload_stream) + # GGUF quantized weights are stored as a custom GGMLTensor subclass rather + # than ComfyUI's QuantizedTensor, so the isinstance check in the block below + # misses them and the block-packed storage reaches F.linear with the wrong + # shape. The discriminator here is GGUF's own protocol marker (tensor_type, + # the GGUF quant type) -- NOT the presence of a dequantize() method: a plain + # torch.Tensor (including ordinary int8/uint8 weights) also exposes + # dequantize() and would fail at runtime if gated on that alone. tensor_type + # is set by GGMLTensor.__init__ and preserved by to()/new_empty(), and nothing + # else in the codebase assigns it, so only genuine GGMLTensor weights enter + # this branch and get dequantized. This is duck-typed: core never imports GGUF. + # Runs after sync_stream because cast_to above may use an offload stream and + # the async device copy must finish before we read the weight. + if not isinstance(weight, QuantizedTensor) and getattr(weight, "tensor_type", None) is not None: + weight = weight.dequantize() + bias_a = bias weight_a = weight