249 lines
8.7 KiB
Markdown
249 lines
8.7 KiB
Markdown
# ComfyUI-Spectrum-Proper
|
|
|
|
Faithful **ComfyUI FLUX** port of [**Spectrum**](https://github.com/hanjq17/Spectrum) from [*Adaptive Spectral Feature Forecasting for Diffusion Sampling Acceleration*](https://arxiv.org/abs/2603.01623).
|
|
|
|
This repo is intentionally narrow in scope: it implements the **FLUX path properly** instead of trying to be a half-faithful generic accelerator for every backend.
|
|
|
|
## What this node does
|
|
|
|
`Spectrum Apply Flux` patches the native ComfyUI FLUX diffusion model on the **MODEL** path and applies Spectrum-style forecasting to the **final hidden image feature right before `final_layer`**.
|
|
|
|
That matches the official Spectrum FLUX integration much more closely than forecasting the final denoised output tensor.
|
|
|
|
In practice the flow is:
|
|
|
|
1. run a real FLUX forward on selected steps
|
|
2. cache the final pre-head hidden feature
|
|
3. fit a small Chebyshev ridge regressor online over step index
|
|
4. forecast future pre-head features on skipped steps
|
|
5. still apply the original FLUX `final_layer` for the current conditioning
|
|
|
|
## Why this repo exists
|
|
|
|
The currently circulating ComfyUI Spectrum ports are useful experiments, but they miss important invariants from the paper and the official code.
|
|
|
|
The main problems I corrected here are:
|
|
|
|
- **Wrong prediction target** in one SDXL-style port: it forecasts the whole UNet output instead of the final hidden feature at the model-specific integration point.
|
|
- **Runtime leakage across model clones** in one FLUX port: it closes over a specific runtime object when monkey-patching the shared inner FLUX model.
|
|
- **Hard-coded 50-step normalization** without adapting to the actual detected run length.
|
|
- **Heuristic pass resets** based on timestep direction only, which are brittle in real ComfyUI workflows.
|
|
- **No clean fallback path** for models that share the same patched inner FLUX object but are not actually using Spectrum.
|
|
|
|
This implementation installs a **generic wrapper once** on the shared FLUX inner model and looks up the active Spectrum runtime from `transformer_options` per call. That avoids ghost patching across clones and preserves normal behavior for non-Spectrum models.
|
|
|
|
## Current scope
|
|
|
|
Supported:
|
|
|
|
- native **ComfyUI FLUX** models
|
|
- LoRAs on the normal model path
|
|
- standard `transformer_options` patch chains
|
|
- standard FLUX control residuals
|
|
- ComfyUI runs that sometimes split one logical solver step into multiple internal FLUX calls
|
|
|
|
For split-step runs, Spectrum now aggregates actual hidden features across the sub-calls and falls back to the real path for any forecast step whose current call shape no longer matches the cached full-batch history. This avoids false run-wide disables while keeping the forecast path conservative.
|
|
|
|
Not included:
|
|
|
|
- SDXL
|
|
- SD3.5
|
|
- video backends
|
|
|
|
That omission is deliberate. A proper SDXL port in ComfyUI needs either a stable last-block hook in the native UNet path or a maintained fork of the UNet forward. Shipping a brittle pseudo-port would be worse than not shipping one.
|
|
|
|
## Installation
|
|
|
|
Copy this folder into:
|
|
|
|
```text
|
|
ComfyUI/custom_nodes/ComfyUI-Spectrum-Proper
|
|
```
|
|
|
|
Restart ComfyUI.
|
|
|
|
No extra Python dependencies are required beyond what ComfyUI already provides.
|
|
|
|
## Node
|
|
|
|
### Spectrum Apply Flux
|
|
|
|
**Input:** `MODEL`
|
|
|
|
**Output:** `MODEL`
|
|
|
|
Place it on the FLUX model line:
|
|
|
|
```text
|
|
UNETLoader / CheckpointLoader -> LoRA stack -> Spectrum Apply Flux -> CFGGuider / sampler
|
|
```
|
|
|
|
Recommended placement:
|
|
|
|
- after model loading and LoRA application
|
|
- before guider/sampler nodes
|
|
|
|
## Parameters
|
|
|
|
### `blend_weight`
|
|
|
|
Blend between linear local extrapolation and Chebyshev spectral prediction.
|
|
|
|
- `1.0` = pure spectral predictor
|
|
- `0.0` = pure local linear predictor
|
|
- recommended default: `0.5`
|
|
|
|
The official repo notes that a convex blend improves robustness outside the strict paper setting.
|
|
|
|
### `degree`
|
|
|
|
Chebyshev degree `m`.
|
|
|
|
Recommended default: `4`
|
|
|
|
### `ridge_lambda`
|
|
|
|
Ridge regularization `lambda` for the coefficient fit.
|
|
|
|
Recommended default: `0.1`
|
|
|
|
### `window_size`
|
|
|
|
Initial interval size before a real forward is required again.
|
|
|
|
Recommended default: `2.0`
|
|
|
|
### `flex_window`
|
|
|
|
How much the interval grows after each post-warmup real forward.
|
|
|
|
This is the ComfyUI-facing equivalent of the adaptive schedule slope used in the official repo.
|
|
|
|
- `0.75` = paper-style moderate speedup
|
|
- `3.0` = more aggressive speedup
|
|
|
|
### `warmup_steps`
|
|
|
|
Number of initial real forwards before forecasting is allowed.
|
|
|
|
Recommended default: `5`
|
|
|
|
### `tail_actual_steps`
|
|
|
|
Number of final solver steps forced to stay on the real path.
|
|
|
|
Practical default for quality-sensitive runs: `3`
|
|
|
|
This protects the refinement tail where late-step forecast bias tends to show up first as smoother microdetail, especially in edit-conditioned runs.
|
|
|
|
### `max_history`
|
|
|
|
Cap for cached real-forward feature points used for the fit.
|
|
|
|
This is an implementation guard, not a paper hyperparameter. With standard FLUX schedules it is usually far above the number of actual cached points anyway.
|
|
|
|
### `debug`
|
|
|
|
Enables lightweight logging during patch install and a per-run summary of actual vs. forecasted solver steps.
|
|
|
|
## Recommended settings
|
|
|
|
### Safer / closer to the paper's moderate setting
|
|
|
|
- `blend_weight = 0.50`
|
|
- `degree = 4`
|
|
- `ridge_lambda = 0.10`
|
|
- `window_size = 2.0`
|
|
- `flex_window = 0.75`
|
|
- `warmup_steps = 5`
|
|
- `tail_actual_steps = 3`
|
|
|
|
### More aggressive
|
|
|
|
- `blend_weight = 0.75`
|
|
- `degree = 4`
|
|
- `ridge_lambda = 0.10`
|
|
- `window_size = 2.0`
|
|
- `flex_window = 3.0`
|
|
- `warmup_steps = 5`
|
|
- `tail_actual_steps = 3`
|
|
|
|
## Design notes
|
|
|
|
### 1. Forecast target is the final hidden FLUX image feature
|
|
|
|
This repo caches and forecasts the hidden image tokens **after the single-stream blocks and before `final_layer`**.
|
|
|
|
That is the important architectural choice. Forecasting the final model output directly is less faithful to the official FLUX integration and tends to be less stable.
|
|
|
|
### 2. Runtime state is per patched model, not per globally monkey-patched inner model
|
|
|
|
ComfyUI model clones often share the same underlying diffusion model object. If you close over a runtime object when replacing `forward_orig`, the state can leak between clones.
|
|
|
|
This repo avoids that by:
|
|
|
|
- patching the inner FLUX model only once
|
|
- storing the active runtime in each cloned model's `transformer_options`
|
|
- looking up the runtime dynamically on every call
|
|
- falling back to the original `forward_orig` when Spectrum is not active
|
|
|
|
### 3. Step normalization uses detected schedule length
|
|
|
|
The paper and official code mostly benchmark 50-step runs. ComfyUI users do not.
|
|
|
|
This repo normalizes the Chebyshev basis against the detected schedule length from `sample_sigmas` instead of hard-coding 50 steps.
|
|
|
|
## Known limitations
|
|
|
|
- This repo currently targets **native ComfyUI FLUX only**.
|
|
- Forecasting is only enabled for deterministic `sample_euler`; samplers that do not preserve a one-`predict_noise`-per-solver-step contract are treated as unsupported.
|
|
- It depends on current ComfyUI FLUX internals staying broadly compatible with the present `forward_orig` signature.
|
|
- It is designed to coexist with standard transformer patch chains, but it is **not guaranteed** to compose with other custom nodes that also replace FLUX `forward_orig` directly.
|
|
- The scheduler is faithful to the official adaptive-window strategy, but one safety approximation is added: forecasting is held back until enough real points exist to fit the chosen Chebyshev degree.
|
|
- The last few refinement steps can also be reserved as actual-only with `tail_actual_steps` to reduce late-step texture loss.
|
|
- No claims are made here about exact paper speedups inside arbitrary ComfyUI workflows. Sampler choice, guidance path, ControlNet usage, resolution, and other wrappers all affect real wall-clock results.
|
|
|
|
## Validation / smoke test
|
|
|
|
Outside ComfyUI, you can at least validate the scheduler and forecaster math:
|
|
|
|
```bash
|
|
cd ComfyUI/custom_nodes/ComfyUI-Spectrum-Proper
|
|
python tests/smoke_runtime.py
|
|
```
|
|
|
|
Expected output:
|
|
|
|
```text
|
|
ok
|
|
```
|
|
|
|
## Repo structure
|
|
|
|
```text
|
|
ComfyUI-Spectrum-Proper/
|
|
|-- __init__.py
|
|
|-- nodes.py
|
|
|-- pyproject.toml
|
|
|-- LICENSE
|
|
|-- README.md
|
|
|-- comfyui_spectrum/
|
|
| |-- __init__.py
|
|
| |-- config.py
|
|
| |-- forecast.py
|
|
| |-- flux.py
|
|
| `-- runtime.py
|
|
`-- tests/
|
|
`-- smoke_runtime.py
|
|
```
|
|
|
|
## Credits
|
|
|
|
- [Spectrum](https://github.com/hanjq17/Spectrum) official code and the paper [*Adaptive Spectral Feature Forecasting for Diffusion Sampling Acceleration*](https://arxiv.org/abs/2603.01623) by Jiaqi Han et al.
|
|
- [ComfyUI](https://github.com/comfyanonymous/ComfyUI) for the native FLUX integration this custom node builds on.
|
|
- [FLUX](https://blackforestlabs.ai/flux-1-tools/) by Black Forest Labs as the model family targeted by this port.
|
|
|
|
## License
|
|
|
|
GPL-3.0-or-later. This is the safest choice because parts of the FLUX forward-path integration are adapted against ComfyUI core internals.
|