Upscale Model Enum Switch 10X (Soze)
Let a String Decide Which Upscaler Your Workflow Uses — the Ten-Way Upscale Router
- UPSCALE_MODEL
- model_name
- matched_index
- status
Upscaling has a menu problem. Most people keep several upscale models around because they serve different jobs - a clean 4x ESRGAN model for pixels, a restoration-leaning model for cleaning up, an anime variant for the other half of your library - and wiring all of them into one workflow means either a pile of loaders or a switch node that carries your whole model library around. Upscale Model Enum Switch 10X is the tidy version: one node, ten upscale model slots, and a single string decides which one actually loads.
It works exactly like the pack's Lora Enum Switch, minus the model/clip plumbing. You supply enum_value - a string from a dropdown, a CSV row, an XY plot, or any upstream node - and the node matches it against up to ten compare_text_N labels. The match is case-insensitive and whitespace-trimmed by default; case_sensitive and strip_whitespace toggles exist if you want strictness. The slot whose label matches loads its model_N (from your models/upscale_models folder), and that's the one you get. If nothing matches, you get no model and a matched_index of 0 - the node hands back nothing rather than a wrong upscaler, which is the right failure mode for a batch.
The allow_none toggle is the sleeper feature: with it on, an enum_value of none (which the pack's "Copy Names to Compare Text" button preps as the first item of the copied array) skips loading entirely. In an XY sweep or a CSV-driven batch, that's how a row says "no upscale for this one" without you building a second, bypassed branch. Same copy-names button as the LoRA variant: pick models in the dropdowns, click it, and every compare_text_N fills with the model's base filename while the whole list lands on your clipboard as JSON you can feed straight into a JSON iterator upstream. That's the entire batch pattern.
Outputs: UPSCALE_MODEL (wire it straight into an ImageUpscaleWithModel or a tiled/Ultimate-style upscale node), model_name so you can log or branch on which one actually loaded, matched_index (1–10, 0 for no match), and status.
When to reach for it
This is a sweep node, not a daily driver. If you hand-load one upscaler, the stock loader is shorter. But the moment you're running an A/B grid across upscale models, or a CSV where each row names the upscaler, or an "auto vs manual" toggle in a shared workflow, this collapses a whole wall of switchers into one input. The KB's upscaling essay is a good reminder of why you'd want to sweep: "which upscaler" is really three different jobs (pixels, restoration, generative), and the right model for one is wrong for another - so being able to swap them by string is genuinely useful, not just tidy.
Install & gotchas
cd ComfyUI/custom_nodes
git clone https://github.com/SozeInc/ComfyUI_Soze.git
pip install -r ComfyUI_Soze/requirements.txt
No keys, no downloads. The label-matching trap is the same as the LoRA variant - labels are matched verbatim after trimming, so use the copy-names button instead of hand-typing, and remember that a blank compare_text_N is always skipped so an empty slot can't accidentally match.
Inputs (24)
| Name | Type | Default | Description |
|---|---|---|---|
| enum_value | STRING | String to match against each compare_text_N. | |
| case_sensitiveopt | BOOLEAN | false | If True, 'A' != 'a'. |
| strip_whitespaceopt | BOOLEAN | true | Trim whitespace before comparing. |
| compare_text_1opt | STRING | Case 1 label. Blank = skip this case. | |
| model_1opt | COMBO | Model loaded when compare_text_1 matches enum_value. Blank = unused. | |
| compare_text_2opt | STRING | Case 2 label. Blank = skip this case. | |
| model_2opt | COMBO | Model loaded when compare_text_2 matches enum_value. Blank = unused. | |
| compare_text_3opt | STRING | Case 3 label. Blank = skip this case. | |
| model_3opt | COMBO | Model loaded when compare_text_3 matches enum_value. Blank = unused. | |
| compare_text_4opt | STRING | Case 4 label. Blank = skip this case. | |
| model_4opt | COMBO | Model loaded when compare_text_4 matches enum_value. Blank = unused. | |
| compare_text_5opt | STRING | Case 5 label. Blank = skip this case. | |
| model_5opt | COMBO | Model loaded when compare_text_5 matches enum_value. Blank = unused. | |
| compare_text_6opt | STRING | Case 6 label. Blank = skip this case. | |
| model_6opt | COMBO | Model loaded when compare_text_6 matches enum_value. Blank = unused. | |
| compare_text_7opt | STRING | Case 7 label. Blank = skip this case. | |
| model_7opt | COMBO | Model loaded when compare_text_7 matches enum_value. Blank = unused. | |
| compare_text_8opt | STRING | Case 8 label. Blank = skip this case. | |
| model_8opt | COMBO | Model loaded when compare_text_8 matches enum_value. Blank = unused. | |
| compare_text_9opt | STRING | Case 9 label. Blank = skip this case. | |
| model_9opt | COMBO | Model loaded when compare_text_9 matches enum_value. Blank = unused. | |
| compare_text_10opt | STRING | Case 10 label. Blank = skip this case. | |
| model_10opt | COMBO | Model loaded when compare_text_10 matches enum_value. Blank = unused. | |
| allow_noneopt | BOOLEAN | false | If enabled, an enum_value of 'none' (the first item in the copied compare-text array) skips loading: the LoRA loader passes (model, clip) through unchanged; the other loaders output nothing for that run. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| UPSCALE_MODEL | UPSCALE_MODEL | — |
| model_name | STRING | — |
| matched_index | INT | — |
| status | STRING | — |