Fix GGUF workflow compatibility and release v1.0.4
This commit is contained in:
+12
-6
@@ -1498,18 +1498,20 @@ class ThinkingLLM_QwenVL_GGUF_Advanced(QwenVLGGUFBase):
|
||||
"frame_count": ("INT", {"default": 16, "min": 1, "max": 64}),
|
||||
"ctx": ("INT", {"default": 32768, "min": 1024, "max": 262144, "step": 512}),
|
||||
"n_batch": ("INT", {"default": 512, "min": 64, "max": 32768, "step": 64}),
|
||||
"n_ubatch": ("INT", {"default": 512, "min": 32, "max": 32768, "step": 32, "tooltip": "Physical batch size. Keep at or below n_batch. Lower values can help throughput or memory stability depending on the backend."}),
|
||||
"gpu_layers": ("INT", {"default": -1, "min": -1, "max": 200}),
|
||||
"image_max_tokens": ("INT", {"default": 4096, "min": 256, "max": 1024000, "step": 256}),
|
||||
"top_k": ("INT", {"default": 20, "min": 0, "max": 32768}),
|
||||
"pool_size": ("INT", {"default": 4194304, "min": 1048576, "max": 10485760, "step": 524288}),
|
||||
"keep_model_loaded": ("BOOLEAN", {"default": False}),
|
||||
"seed": ("INT", {"default": 1, "min": 1, "max": 2**32 - 1}),
|
||||
"legacy_seed_mode": (["fixed", "randomize", "increment", "decrement"], {"default": "fixed", "tooltip": "Legacy workflow compatibility only. This widget is ignored by current ThinkingLLM logic."}),
|
||||
"legacy_unload_after_run": ("BOOLEAN", {"default": False, "tooltip": "Legacy workflow compatibility only. Model unloading is controlled by keep_model_loaded."}),
|
||||
"n_ubatch": ("INT", {"default": 512, "min": 32, "max": 32768, "step": 32, "tooltip": "Physical batch size. Keep at or below n_batch. Lower values can help throughput or memory stability depending on the backend."}),
|
||||
"n_threads": ("INT", {"default": 0, "min": 0, "max": 256, "tooltip": "CPU generation threads. Set 0 to let llama.cpp choose."}),
|
||||
"n_threads_batch": ("INT", {"default": 0, "min": 0, "max": 256, "tooltip": "CPU prompt/batch threads. Set 0 to let llama.cpp choose."}),
|
||||
"flash_attn": ("BOOLEAN", {"default": True, "tooltip": "Enable flash attention when the installed llama.cpp backend supports it."}),
|
||||
"offload_kqv": ("BOOLEAN", {"default": True, "tooltip": "Keep K/Q/V and KV-cache related work on GPU when supported."}),
|
||||
"ctx_checkpoints": ("INT", {"default": 0, "min": 0, "max": 32, "tooltip": "Checkpoint count for multimodal context handling. JamePeng docs recommend 0 for single-turn ComfyUI-style multimodal runs."}),
|
||||
"keep_model_loaded": ("BOOLEAN", {"default": False}),
|
||||
"seed": ("INT", {"default": 1, "min": 1, "max": 2**32 - 1}),
|
||||
"keep_last_prompt": ("BOOLEAN", {"default": False, "tooltip": "Keep the last generated prompt instead of creating a new one"}),
|
||||
"stream_tokens_to_terminal": ("BOOLEAN", {"default": False, "tooltip": "Print every generated token live to the ComfyUI terminal/console"}),
|
||||
"enable_thinking": ("BOOLEAN", {"default": True, "tooltip": "Enable model reasoning/thinking when the backend supports it: True=allow thinking, False=force direct answer. Even when enabled, easy prompts may still get a direct answer, and this node automatically disables thinking when there is not enough output budget left for useful reasoning. For non-Qwen GGUF models this is advisory."}),
|
||||
@@ -1542,18 +1544,20 @@ class ThinkingLLM_QwenVL_GGUF_Advanced(QwenVLGGUFBase):
|
||||
frame_count,
|
||||
ctx,
|
||||
n_batch,
|
||||
n_ubatch,
|
||||
gpu_layers,
|
||||
image_max_tokens,
|
||||
top_k,
|
||||
pool_size,
|
||||
keep_model_loaded,
|
||||
seed,
|
||||
legacy_seed_mode,
|
||||
legacy_unload_after_run,
|
||||
n_ubatch,
|
||||
n_threads,
|
||||
n_threads_batch,
|
||||
flash_attn,
|
||||
offload_kqv,
|
||||
ctx_checkpoints,
|
||||
keep_model_loaded,
|
||||
seed,
|
||||
keep_last_prompt,
|
||||
image=None,
|
||||
video=None,
|
||||
@@ -1562,6 +1566,8 @@ class ThinkingLLM_QwenVL_GGUF_Advanced(QwenVLGGUFBase):
|
||||
stream_tokens_to_terminal=False,
|
||||
enable_thinking=True,
|
||||
):
|
||||
_ = legacy_seed_mode
|
||||
_ = legacy_unload_after_run
|
||||
result = self.run(
|
||||
model_name=model_name,
|
||||
preset_prompt=preset_prompt,
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "ComfyUI-ThinkingLLM"
|
||||
description = "A multimodal ComfyUI AI node with Qwen3.5, Qwen3-VL, Qwen2.5-VL, Qwen3, and Gemma 4 integrations. Features live thinking in the terminal to see what the LLM is doing in real time."
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
license = {file = "LICENSE"}
|
||||
dependencies = ["transformers>=5.2.0", "torch", "huggingface-hub", "hf_xet", "psutil", "numpy", "Pillow", "opencv-python", "bitsandbytes", "accelerate", "sentencepiece", "tiktoken", "llama-cpp-python"]
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ plain shell without ML dependencies.
|
||||
|
||||
import ast
|
||||
import importlib.util
|
||||
import inspect
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
@@ -428,6 +429,68 @@ class TestLegacyNodeNameCompatibility(unittest.TestCase):
|
||||
self.assertIn(node_type, resolved_types)
|
||||
|
||||
|
||||
class TestGGUFAdvancedWorkflowCompatibility(unittest.TestCase):
|
||||
LEGACY_REQUIRED_PREFIX = [
|
||||
"model_name",
|
||||
"device",
|
||||
"preset_prompt",
|
||||
"custom_prompt",
|
||||
"max_tokens",
|
||||
"temperature",
|
||||
"top_p",
|
||||
"repetition_penalty",
|
||||
"frame_count",
|
||||
"ctx",
|
||||
"n_batch",
|
||||
"gpu_layers",
|
||||
"image_max_tokens",
|
||||
"top_k",
|
||||
"pool_size",
|
||||
"keep_model_loaded",
|
||||
"seed",
|
||||
]
|
||||
|
||||
def _load_gguf_advanced_class(self):
|
||||
package = load_thinkingllm_loader_subset(["AILab_QwenVL_GGUF.py"])
|
||||
return package.NODE_CLASS_MAPPINGS["ThinkingLLM_QwenVL_GGUF_Advanced"]
|
||||
|
||||
def test_gguf_advanced_required_widgets_preserve_legacy_order(self):
|
||||
node_cls = self._load_gguf_advanced_class()
|
||||
required_keys = list(node_cls.INPUT_TYPES()["required"].keys())
|
||||
|
||||
self.assertEqual(
|
||||
required_keys[: len(self.LEGACY_REQUIRED_PREFIX)],
|
||||
self.LEGACY_REQUIRED_PREFIX,
|
||||
)
|
||||
self.assertEqual(
|
||||
required_keys[len(self.LEGACY_REQUIRED_PREFIX): len(self.LEGACY_REQUIRED_PREFIX) + 2],
|
||||
["legacy_seed_mode", "legacy_unload_after_run"],
|
||||
)
|
||||
self.assertGreater(required_keys.index("n_ubatch"), required_keys.index("legacy_unload_after_run"))
|
||||
|
||||
def test_gguf_advanced_process_signature_matches_required_widget_order(self):
|
||||
node_cls = self._load_gguf_advanced_class()
|
||||
signature = inspect.signature(node_cls.process)
|
||||
parameter_names = [
|
||||
name
|
||||
for name, parameter in signature.parameters.items()
|
||||
if name != "self" and parameter.kind in (inspect.Parameter.POSITIONAL_OR_KEYWORD, inspect.Parameter.KEYWORD_ONLY)
|
||||
]
|
||||
|
||||
expected_prefix = self.LEGACY_REQUIRED_PREFIX + [
|
||||
"legacy_seed_mode",
|
||||
"legacy_unload_after_run",
|
||||
"n_ubatch",
|
||||
"n_threads",
|
||||
"n_threads_batch",
|
||||
"flash_attn",
|
||||
"offload_kqv",
|
||||
"ctx_checkpoints",
|
||||
"keep_last_prompt",
|
||||
]
|
||||
self.assertEqual(parameter_names[: len(expected_prefix)], expected_prefix)
|
||||
|
||||
|
||||
class _GlobalCheck(ast.NodeVisitor):
|
||||
def __init__(self):
|
||||
self.found = False
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# ComfyUI-QwenVL Update Log
|
||||
|
||||
## Version 1.0.4 (2026/05/16) — GGUF Workflow Compatibility Fix
|
||||
|
||||
### Fixed
|
||||
- Restored legacy widget ordering compatibility for `ThinkingLLM_QwenVL_GGUF_Advanced` so older saved workflows no longer shift values into the wrong advanced GGUF fields.
|
||||
- Added compatibility shims for deprecated legacy fields (`seed_mode` and `unload_after_run`) so old workflows deserialize cleanly without affecting current runtime behavior.
|
||||
- Added regression tests that lock the advanced GGUF widget order and `process()` signature alignment.
|
||||
|
||||
### Validation
|
||||
- Local regression suite passes: `python tests/test_new_features.py`
|
||||
|
||||
## Version 2.2.5-local-locked (2026/05/14) — Complete Feature Parity
|
||||
|
||||
### 🎯 All 6 Nodes Now Have:
|
||||
|
||||
Reference in New Issue
Block a user