Skip to content

Commit de4f129

Browse files
authored
Merge branch 'mit-han-lab:main' into main
2 parents e8a0602 + dba78a9 commit de4f129

File tree

18 files changed

+400
-82
lines changed

18 files changed

+400
-82
lines changed

.github/workflows/auto-merge-main-into-dev.yaml renamed to .github/workflows/merge-main-into-dev.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Auto-merge main into dev
1+
name: Merge main into dev
22
on:
33
workflow_dispatch:
44
push:

.github/workflows/publish.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: Publish to Comfy registry
2+
on:
3+
workflow_dispatch:
4+
jobs:
5+
publish-node:
6+
name: Publish Custom Node to registry
7+
runs-on: ubuntu-latest
8+
steps:
9+
- name: Check out code
10+
uses: actions/checkout@v4
11+
- name: Publish Custom Node
12+
uses: Comfy-Org/publish-node-action@main
13+
with:
14+
personal_access_token: ${{ secrets.COMFYUI_REGISTRY_ACCESS_TOKEN }}

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ Join our user groups on [**Slack**](https://join.slack.com/t/nunchaku/shared_inv
1515

1616
# Nunchaku ComfyUI Node
1717

18-
![comfyui](https://cas-bridge.xethub.hf.co/xet-bridge-us/6809c14d122d22df4c286c5c/75aba8411336c4e6d52636912289086d19a0dc01438b9953e9e6fc40032cd5fc?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=cas%2F20250602%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250602T052600Z&X-Amz-Expires=3600&X-Amz-Signature=bb4114b8cb92ce976305c327a9ff82556bd93557092bbeb4a9daa564ebb0cc79&X-Amz-SignedHeaders=host&X-Xet-Cas-Uid=63129589bbaa385279d1826e&response-content-disposition=inline%3B+filename*%3DUTF-8%27%27comfyui.jpg%3B+filename%3D%22comfyui.jpg%22%3B&response-content-type=image%2Fjpeg&x-id=GetObject&Expires=1748845560&Policy=eyJTdGF0ZW1lbnQiOlt7IkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTc0ODg0NTU2MH19LCJSZXNvdXJjZSI6Imh0dHBzOi8vY2FzLWJyaWRnZS54ZXRodWIuaGYuY28veGV0LWJyaWRnZS11cy82ODA5YzE0ZDEyMmQyMmRmNGMyODZjNWMvNzVhYmE4NDExMzM2YzRlNmQ1MjYzNjkxMjI4OTA4NmQxOWEwZGMwMTQzOGI5OTUzZTllNmZjNDAwMzJjZDVmYyoifV19&Signature=atydH0AEc4QZUDZ1Qz4qkgQ2EiU-34-1tEgw4wN27hbsW1SDyD63RyDFiWphxYDAN74l9hghmHDkma7ddfUox5Ckl9Jw3zFOtW26I0FLSoM7L6czyD5ob0qBvbAY7A5oWHpzUgxR9L-uhFdWuFgIpCvHqe0y%7EEH3dtlmvXzOcltE2XnFRgfJTwtVJxJXqcklHtMPz1pI92KSUiOZUwLjbwnTdKvbl8ysng8tkWkP9N2c9P-vvibMdyolR2zqK3rHCAV709m8wqOKrTpc%7EciQEKTjsJy%7Ek68wUGDjy3usNjMSC9D5xeV7U3456jX6MjyMj%7EEGzzsEUYmqf989Kk%7EF9Q__&Key-Pair-Id=K2L8F4GPSG1IFC)
18+
![comfyui](https://huggingface.co/mit-han-lab/nunchaku-artifacts/resolve/main/ComfyUI-nunchaku/assets/comfyui.jpg)
1919

2020
## News
2121

22+
- **[2025-06-07]** 🚀 **Release Patch v0.3.1!** We bring back **FB Cache** support and fix **4-bit text encoder loading**. PuLID nodes are now optional and won’t interfere with other nodes. We've also added a **NunchakuWheelInstaller** node to help you install the correct [Nunchaku](https://github.com/mit-han-lab/nunchaku) wheel.
2223
- **[2025-06-01]** 🚀 **Release v0.3.0!** This update adds support for multiple-batch inference, [**ControlNet-Union-Pro 2.0**](https://huggingface.co/Shakker-Labs/FLUX.1-dev-ControlNet-Union-Pro-2.0) and initial integration of [**PuLID**](https://github.com/ToTheBeginning/PuLID). You can now load Nunchaku FLUX models as a single file, and our upgraded [**4-bit T5 encoder**](https://huggingface.co/mit-han-lab/nunchaku-t5) now matches **FP8 T5** in quality!
2324
- **[2025-04-16]** 🎥 Released tutorial videos in both [**English**](https://youtu.be/YHAVe-oM7U8?si=cM9zaby_aEHiFXk0) and [**Chinese**](https://www.bilibili.com/video/BV1BTocYjEk5/?share_source=copy_web&vd_source=8926212fef622f25cc95380515ac74ee) to assist installation and usage.
2425
- **[2025-04-09]** 📢 Published the [April roadmap](https://github.com/mit-han-lab/nunchaku/issues/266) and an [FAQ](https://github.com/mit-han-lab/nunchaku/discussions/262) to help the community get started and stay up to date with Nunchaku’s development.
@@ -152,6 +153,11 @@ comfy node registry-install ComfyUI-nunchaku # Install Nunchaku
152153
- Select the CLIP and T5 models to use as `text_encoder1` and `text_encoder2`, following the same convention as in `DualCLIPLoader`. In addition, you may choose to use our enhanced [4-bit T5XXL model](https://huggingface.co/mit-han-lab/nunchaku-t5/resolve/main/awq-int4-flux.1-t5xxl.safetensors) for saving more GPU memory.
153154
- `t5_min_length`: Sets the minimum sequence length for T5 text embeddings. The default in `DualCLIPLoader` is hardcoded to 256, but for better image quality, use 512 here.
154155

156+
- **Nunchaku Wheel Installer**: A utility node for automatically installing the correct version of [Nunchaku](https://github.com/mit-han-lab/nunchaku) wheels. After installation, please **restart ComfyUI** to apply the changes.
157+
158+
- `source`: Select the source of the wheel. Available options include [`GitHub Release`](https://github.com/mit-han-lab/nunchaku/releases), [`HuggingFace`](https://huggingface.co/mit-han-lab/nunchaku), and [`ModelScope`](https://modelscope.cn/models/Lmxyy1999/nunchaku).
159+
- `version`: Choose the compatible [Nunchaku](https://github.com/mit-han-lab/nunchaku) version to install.
160+
155161
- **Nunchaku Text Encoder Loader (will be deprecated in v0.4)**: A node for loading the text encoders.
156162

157163
- For FLUX, use the following files:

__init__.py

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,75 @@
1-
# only import if running as a custom node
2-
from .nodes.lora import NunchakuFluxLoraLoader
3-
from .nodes.models import (
4-
NunchakuFluxDiTLoader,
5-
NunchakuPulidApply,
6-
NunchakuPulidLoader,
7-
NunchakuTextEncoderLoader,
8-
NunchakuTextEncoderLoaderV2,
9-
)
10-
from .nodes.preprocessors import FluxDepthPreprocessor
11-
from .nodes.tools import NunchakuModelMerger
1+
import logging
2+
import os
3+
4+
# Get log level from environment variable (default to INFO)
5+
log_level = os.getenv("LOG_LEVEL", "INFO").upper()
6+
7+
# Configure logging
8+
logging.basicConfig(level=getattr(logging, log_level, logging.INFO), format="%(asctime)s - %(levelname)s - %(message)s")
9+
logger = logging.getLogger(__name__)
10+
11+
logger.info("=" * 40 + " ComfyUI-nunchaku Initialization " + "=" * 40)
12+
13+
from .utils import get_package_version, get_plugin_version, supported_versions
14+
15+
nunchaku_full_version = get_package_version("nunchaku").split("+")[0].strip()
16+
17+
logger.info(f"Nunchaku version: {nunchaku_full_version}")
18+
logger.info(f"ComfyUI-nunchaku version: {get_plugin_version()}")
19+
20+
nunchaku_version = nunchaku_full_version.split("+")[0].strip()
21+
nunchaku_major_minor_patch_version = ".".join(nunchaku_version.split(".")[:3])
22+
if f"v{nunchaku_major_minor_patch_version}" not in supported_versions:
23+
logger.warning(
24+
f"ComfyUI-nunchaku {get_plugin_version()} is not compatible with nunchaku {nunchaku_full_version}. "
25+
f"Please update nunchaku to a supported version in {supported_versions}."
26+
)
27+
28+
from .nodes.lora.flux import NunchakuFluxLoraLoader
29+
from .nodes.models.flux import NunchakuFluxDiTLoader
1230

1331
NODE_CLASS_MAPPINGS = {
1432
"NunchakuFluxDiTLoader": NunchakuFluxDiTLoader,
15-
"NunchakuTextEncoderLoader": NunchakuTextEncoderLoader,
16-
"NunchakuTextEncoderLoaderV2": NunchakuTextEncoderLoaderV2,
1733
"NunchakuFluxLoraLoader": NunchakuFluxLoraLoader,
18-
"NunchakuDepthPreprocessor": FluxDepthPreprocessor,
19-
"NunchakuPulidApply": NunchakuPulidApply,
20-
"NunchakuPulidLoader": NunchakuPulidLoader,
21-
"NunchakuModelMerger": NunchakuModelMerger,
2234
}
35+
36+
try:
37+
from .nodes.models.text_encoder import NunchakuTextEncoderLoader, NunchakuTextEncoderLoaderV2
38+
39+
NODE_CLASS_MAPPINGS["NunchakuTextEncoderLoader"] = NunchakuTextEncoderLoader
40+
NODE_CLASS_MAPPINGS["NunchakuTextEncoderLoaderV2"] = NunchakuTextEncoderLoaderV2
41+
except ImportError:
42+
logger.exception("Optional nodes `NunchakuTextEncoderLoader` and `NunchakuTextEncoderLoaderV2` import failed:")
43+
44+
try:
45+
from .nodes.preprocessors.depth import FluxDepthPreprocessor
46+
47+
NODE_CLASS_MAPPINGS["NunchakuDepthPreprocessor"] = FluxDepthPreprocessor
48+
except ImportError:
49+
logger.exception("Optional node `NunchakuDepthPreprocessor` import failed:")
50+
51+
try:
52+
from .nodes.models.pulid import NunchakuPulidApply, NunchakuPulidLoader
53+
54+
NODE_CLASS_MAPPINGS["NunchakuPulidApply"] = NunchakuPulidApply
55+
NODE_CLASS_MAPPINGS["NunchakuPulidLoader"] = NunchakuPulidLoader
56+
except ImportError:
57+
logger.exception("Optional nodes `NunchakuPulidApply` and `NunchakuPulidLoader` import failed:")
58+
59+
try:
60+
from .nodes.tools.merge_safetensors import NunchakuModelMerger
61+
62+
NODE_CLASS_MAPPINGS["NunchakuModelMerger"] = NunchakuModelMerger
63+
except ImportError:
64+
logger.exception("Optional node `NunchakuModelMerger` import failed:")
65+
66+
try:
67+
from .nodes.tools.installers import NunchakuWheelInstaller
68+
69+
NODE_CLASS_MAPPINGS["NunchakuWheelInstaller"] = NunchakuWheelInstaller
70+
except ImportError:
71+
logger.exception("Optional node `NunchakuWheelInstaller` import failed:")
72+
2373
NODE_DISPLAY_NAME_MAPPINGS = {k: v.TITLE for k, v in NODE_CLASS_MAPPINGS.items()}
2474
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
75+
logger.info("=" * (80 + len(" ComfyUI-nunchaku Initialization ")))
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
{
2+
"id": "e33d94b5-334c-4607-8ef0-6ca542730844",
3+
"revision": 0,
4+
"last_node_id": 3,
5+
"last_link_id": 1,
6+
"nodes": [
7+
{
8+
"id": 2,
9+
"type": "PreviewAny",
10+
"pos": [
11+
659.4140625,
12+
253.45053100585938
13+
],
14+
"size": [
15+
418.6068115234375,
16+
88
17+
],
18+
"flags": {},
19+
"order": 2,
20+
"mode": 0,
21+
"inputs": [
22+
{
23+
"name": "source",
24+
"type": "*",
25+
"link": 1
26+
}
27+
],
28+
"outputs": [],
29+
"properties": {
30+
"cnr_id": "comfy-core",
31+
"ver": "0.3.39",
32+
"Node name for S&R": "PreviewAny"
33+
},
34+
"widgets_values": []
35+
},
36+
{
37+
"id": 1,
38+
"type": "NunchakuWheelInstaller",
39+
"pos": [
40+
299.934814453125,
41+
255.38197326660156
42+
],
43+
"size": [
44+
270,
45+
82
46+
],
47+
"flags": {},
48+
"order": 0,
49+
"mode": 0,
50+
"inputs": [],
51+
"outputs": [
52+
{
53+
"name": "status",
54+
"type": "STRING",
55+
"links": [
56+
1
57+
]
58+
}
59+
],
60+
"properties": {
61+
"Node name for S&R": "NunchakuWheelInstaller"
62+
},
63+
"widgets_values": [
64+
"ModelScope",
65+
"v0.3.0"
66+
]
67+
},
68+
{
69+
"id": 3,
70+
"type": "Note",
71+
"pos": [
72+
310.68572998046875,
73+
429.6354064941406
74+
],
75+
"size": [
76+
250.13458251953125,
77+
121.31512451171875
78+
],
79+
"flags": {},
80+
"order": 1,
81+
"mode": 0,
82+
"inputs": [],
83+
"outputs": [],
84+
"properties": {},
85+
"widgets_values": [
86+
"This workflow will automatically install the compatible Nunchaku wheels from GitHub Releases, Hugging Face, or ModelScope. Once installation is complete, please restart ComfyUI."
87+
],
88+
"color": "#432",
89+
"bgcolor": "#653"
90+
}
91+
],
92+
"links": [
93+
[
94+
1,
95+
1,
96+
0,
97+
2,
98+
0,
99+
"*"
100+
]
101+
],
102+
"groups": [],
103+
"config": {},
104+
"extra": {
105+
"ds": {
106+
"scale": 1,
107+
"offset": [
108+
286.0416564941406,
109+
72.68229675292969
110+
]
111+
},
112+
"frontendVersion": "1.20.7"
113+
},
114+
"version": 0.4
115+
}

nodes/lora/__init__.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
from .flux import NunchakuFluxLoraLoader
2-
3-
__all__ = ["NunchakuFluxLoraLoader"]

nodes/lora/flux.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ def INPUT_TYPES(s):
4848
)
4949

5050
def load_lora(self, model, lora_name: str, lora_strength: float):
51+
if abs(lora_strength) < 1e-5:
52+
return (model,)
5153
model_wrapper = model.model.diffusion_model
5254
assert isinstance(model_wrapper, ComfyFluxWrapper)
5355
from nunchaku.lora.flux import to_diffusers

nodes/models/__init__.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +0,0 @@
1-
from .flux import NunchakuFluxDiTLoader
2-
from .pulid import NunchakuPulidApply, NunchakuPulidLoader
3-
from .text_encoder import NunchakuTextEncoderLoader, NunchakuTextEncoderLoaderV2
4-
5-
__all__ = [
6-
"NunchakuFluxDiTLoader",
7-
"NunchakuTextEncoderLoader",
8-
"NunchakuTextEncoderLoaderV2",
9-
"NunchakuPulidApply",
10-
"NunchakuPulidLoader",
11-
]

nodes/models/flux.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def forward(
104104
# Check if timestamps have changed or are out of valid range
105105
if self._prev_timestep is None:
106106
cache_invalid = True
107-
elif abs(self._prev_timestep - timestep_float) > 1e-5: # Add a tolerance
107+
elif self._prev_timestep < timestep_float + 1e-5: # allow a small tolerance to reuse the cache
108108
cache_invalid = True
109109

110110
if cache_invalid:

0 commit comments

Comments
 (0)