diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..8c556c1 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,28 @@ +name: Publish to Comfy registry +on: + workflow_dispatch: + push: + branches: + - main + - master + paths: + - "pyproject.toml" + +permissions: + issues: write + +jobs: + publish-node: + name: Publish Custom Node to registry + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'erosDiffusion' }} + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + submodules: true + - name: Publish Custom Node + uses: Comfy-Org/publish-node-action@v1 + with: + ## Add your own personal access token to your Github Repository secrets and reference it here. + personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} diff --git a/G62578SWUAAfD2f.jpg b/G62578SWUAAfD2f.jpg new file mode 100644 index 0000000..83effa8 Binary files /dev/null and b/G62578SWUAAfD2f.jpg differ diff --git a/LICENSE.TXT b/LICENSE.TXT index eab4f77..4b62753 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -1 +1,21 @@ -empty...for now \ No newline at end of file +MIT License + +Copyright (c) 2025 erosDiffusion + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 9e04016..c87c7bc 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,29 @@ # FlowMatch Euler Discrete Scheduler for ComfyUI - 9 steps, big res, zero noise. -**FlowMatchEulerDiscrete** seems not exposed in ComfyUI, but it is what the official demo in diffusers use. +**FlowMatchEulerDiscrete** seems not exposed in ComfyUI, but it is what the official Z-Image demo in diffusers use. So: + - I am exposing it in the scheduler section for you to use within KSampler. - On top I provide a node, experimental, to configure the scheduler for use with CustomSampler and play with. In short...if you want **sharper and noise free images**, use this! ## Installation + - use comfy ui manager (search erosDiffusion or ComfyUI-EulerFlowMatchingDiscreteScheduler) - + or -- ```git clone https://github.com/erosDiffusion/ComfyUI-EulerDiscreteScheduler.git``` in your custom nodes folder. +- `git clone https://github.com/erosDiffusion/ComfyUI-EulerDiscreteScheduler.git` in your custom nodes folder. Example output (more below) example ## What you get + - one new scheduler **FlowMatchEulerDiscreteScheduler** registered in the KSampler - a custom node that exposes all parameters of the FlowMatchEulerDiscreteScheduler which Outputs **SIGMAS** for use with **SamplerCustom** node. @@ -36,17 +38,29 @@ Example output (more below) 3. Adjust parameters to control the sampling behavior ## Tech bits: + - https://huggingface.co/docs/diffusers/api/schedulers/flow_match_euler_discrete - https://huggingface.co/Tongyi-MAI/Z-Image-Turbo/blob/main/scheduler/scheduler_config.json ## Find this useful and want to support ? - [Buy me a beer!](https://donate.stripe.com/cNi9ALaASf65clXahPcV201) - +[Buy me a beer!](https://donate.stripe.com/cNi9ALaASf65clXahPcV201) + ComfyUI_00716_ More examples: image image +## Changelog +**1.0.3** + +- node publish action + +**1.0.2** + +- changed the device management in the custom scheduler node to be on gpu (cuda) +- removed flash attention node dependency from the custom scheduler node +- removed flash attention node from init +- added mit licensing diff --git a/__init__.py b/__init__.py index d83f4fb..a258ad0 100644 --- a/__init__.py +++ b/__init__.py @@ -133,6 +133,10 @@ class FlowMatchEulerSchedulerNode: "default": "disable", "tooltip": "Uses Karras noise schedule for smoother results. Similar to DPM++ samplers, often improves quality." }), + "device": (["auto", "cuda", "cpu"], { + "default": "auto", + "tooltip": "Device for sigma computation. 'auto' detects GPU if available, otherwise CPU. Using GPU avoids CPU->GPU transfers." + }), } } @@ -161,6 +165,7 @@ class FlowMatchEulerSchedulerNode: use_dynamic_shifting, use_exponential_sigmas, use_karras_sigmas, + device="auto", ): # Convert string combo values to boolean config = { @@ -184,6 +189,18 @@ class FlowMatchEulerSchedulerNode: # 1. Generate the full sigma schedule scheduler.set_timesteps(steps, device="cpu", mu=0.0) + # Determine device to use for sigma computation + if device == "auto": + # Auto-detect: use CUDA if available, otherwise CPU + target_device = "cuda" if torch.cuda.is_available() else "cpu" + print(f"[FlowMatch Scheduler] Auto-detected device: {target_device.upper()}") + else: + target_device = device + print(f"[FlowMatch Scheduler] Using manually specified device: {target_device.upper()}") + + # Set timesteps and get sigmas for the specified number of steps + # Using the model's device avoids unnecessary CPU->GPU transfers during sampling + scheduler.set_timesteps(steps, device=target_device, mu=0.0) sigmas = scheduler.sigmas # 2. Apply start_at_step and end_at_step (Slicing the sigmas tensor) @@ -203,15 +220,17 @@ class FlowMatchEulerSchedulerNode: # Import Flash Attention node -from .flash_attention_node import NODE_CLASS_MAPPINGS as FLASH_ATTN_MAPPINGS -from .flash_attention_node import NODE_DISPLAY_NAME_MAPPINGS as FLASH_ATTN_DISPLAY_MAPPINGS +# from .flash_attention_node import NODE_CLASS_MAPPINGS as FLASH_ATTN_MAPPINGS +# from .flash_attention_node import NODE_DISPLAY_NAME_MAPPINGS as FLASH_ATTN_DISPLAY_MAPPINGS NODE_CLASS_MAPPINGS = { "FlowMatchEulerDiscreteScheduler (Custom)": FlowMatchEulerSchedulerNode, - **FLASH_ATTN_MAPPINGS + # **FLASH_ATTN_MAPPINGS } NODE_DISPLAY_NAME_MAPPINGS = { "FlowMatchEulerDiscreteScheduler (Custom)": "FlowMatch Euler Discrete Scheduler (Custom)", **FLASH_ATTN_DISPLAY_MAPPINGS -} \ No newline at end of file +} + # **FLASH_ATTN_DISPLAY_MAPPINGS +} diff --git a/pyproject.toml b/pyproject.toml index 4167b27..c2e6c6b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "erosdiffusion-eulerflowmatchingdiscretescheduler" description = "Noise Free images with Euler Discrete Scheduler in ComfyUI with Z-Image or other models" -version = "1.0.1" +version = "1.0.3" license = {file = "LICENSE.TXT"} # classifiers = [ # # For OS-independent nodes (works on all operating systems)