NAI Multi-Character Detailer
NAICombinedFaceDetailerTest Is a Ghost Node — Your Old Workflow Just Hasn't Noticed
- image
- detectors
- characterPrompts
- tagger
- vibes
- references
- nai_context
- image
- mask_visualization
- matching_report
Here's the short version: NAICombinedFaceDetailerTest is not a node you go looking for. It's a compatibility shim - a subclass of the real thing, kept around so workflows and saved API graphs written against an earlier prototype still load and still run. The node menu calls it "NAI Multi-Character Detailer", exactly like the current node, so you can't tell them apart by looking at the canvas.
In the pack's __init__.py it's four lines of class definition with DEPRECATED = True and nothing else:
class NAICombinedFaceDetailerTest(NAIMultiCharacterDetailer):
DEPRECATED = True
Because it's a plain subclass with no overrides, it inherits the entire current implementation. Same inputs, same outputs, same behaviour. There is no "test" logic left in it, and nothing you can do here that you can't do on NAIMultiCharacterDetailer.
Why it exists, and the trap it sets
The prototype workflows that shipped in version 2.8.0 and earlier used this class name. Rather than break every saved graph, the author kept the ID alive and wired it to the finished node. When you load one of those old workflows, the node IDs migrate to the stable names on load, custom titles survive, and links into the removed preview_only input are dropped along with the widget.
That removal is the actual trap. preview_only used to mean "detect and match, but don't call NovelAI" - a free way to check which face got assigned which character. It's gone, and the pack states flatly that running a migrated workflow now performs correction. The old flag no longer suppresses the request. If you queued a workflow you last used in June to check it still loads, you may also have just spent Anlas on it.
What it takes and what it gives you
The full schema is the current node's: image and a detectors bundle from the NAI Detection Combine Loader are required, along with prompt, negative_prompt, model, strength and seed. Optional inputs cover character matching (characterPrompts, tagger, matching_mode, match_min_score, match_min_margin), mask behavior (closing, fill_holes, dilation, mask_feather), context inheritance (nai_context, use_context_settings, context_mode, the override_* switches) and reference inputs. It returns image, mask_visualization and matching_report, in that order.
limit_opus_free still defaults to True, so a migrated workflow will usually stop at the guard rather than quietly billing you - but "usually" is doing real work in that sentence, and the check is a preflight, not a billing guarantee.
What to do about it
If you're building something new, don't add this node. Use NAI Multi-Character Detailer (NAIMultiCharacterDetailer). If you're opening an old workflow and want to modernize it, delete the old node and drop the current one in - the sockets are in the same order, so your existing image, detectors and tagger wires reconnect cleanly, and you'll gain the visible input set instead of a migrated legacy node nobody can see the origin of.
If you're driving the pack over the API, note the aliases are still registered in NODE_CLASS_MAPPINGS, so a POST that names NAICombinedFaceDetailerTest as the class will resolve and run. That's intentional backward compatibility, not a second feature.
Install
Shared with the pack, and required either way - this node can't run standalone:
cd ComfyUI/custom_nodes
git clone https://github.com/raspie10032/ComfyUI_RS_NAI_API_Request.git
python -m pip install -r ComfyUI_RS_NAI_API_Request/requirements.txt
You need ComfyUI-Impact-Pack and ComfyUI-Impact-Subpack for the detectors, a .env with NAI_ACCESS_TOKEN in the pack folder, and the optional tagger dependencies if you want automatic per-character matching. Restart ComfyUI after any update, then refresh the browser page - the localized labels and the execution notices are served to the frontend and won't appear until you do.
Inputs (51)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| detectors | NAI_DETECTION_BUNDLE | — | |
| prompt | STRING | smiling face, highly detailed | — |
| negative_prompt | STRING | lowres, bad anatomy | — |
| model | COMBO | NAI Diffusion V5 Full | V5 Full Medium Effort always uses 14 steps, Euler Ancestral, zero CFG Rescale, and fixed Heavy Undesired Content. Custom base/character negative prompts are ignored. Prompt Guidance remains adjustable. Image-to-image and inpainting require limit_opus_free=False and can spend Anlas. |
| strength | FLOAT | 0.550–1 | — |
| seed | INT | -1-1–4294967295 | — |
| show_advancedopt | BOOLEAN | false | — |
| limit_opus_freeopt | BOOLEAN | true | — |
| detail_modeopt | COMBO | all | 2 options: all, first |
| matching_modeopt | COMBO | shared | 2 options: shared, wd14 |
| characterPromptsopt | LIST | — | |
| taggeropt | RS_WD_TAGGER | — | |
| match_min_scoreopt | FLOAT | 0.250.01–1 | — |
| match_min_marginopt | FLOAT | 0.080.01–1 | — |
| match_crop_factoropt | FLOAT | 2.01–5 | — |
| max_regionsopt | INT | 51–64 | Maximum number of regions to process. Quality cannot be guaranteed as the number of processed regions increases. |
| vibesopt | RS_NAI_VIBES | — | |
| referencesopt | RS_NAI_REFERENCES | — | |
| normalize_vibe_strengthsopt | BOOLEAN | true | V4/V4.5 Vibe: scale strengths down if their absolute sum exceeds 1.0. |
| save_formatopt | COMBO | PNG | Autosave format. Preserves NovelAI generation information. No ComfyUI workflow is embedded. |
| webp_qualityopt | INT | 901–100 | Used only for lossy WebP. Lossless WebP preserves pixels. |
| sampleropt | COMBO | k_euler | 7 options: k_dpmpp_2m, k_dpmpp_sde, k_dpmpp_2m_sde, k_dpmpp_2s_ancestral, k_euler_ancestral, k_euler, +1 |
| stepsopt | INT | 281–50 | — |
| cfg_scaleopt | FLOAT | 6.00–30 | — |
| scheduleropt | COMBO | karras | 4 options: native, karras, exponential, polyexponential |
| thresholdopt | FLOAT | 0.300–1 | — |
| crop_factoropt | FLOAT | 3.01–10 | — |
| bbox_thresholdopt | FLOAT | 0.300–1 | — |
| closingopt | BOOLEAN | true | Fill small notches before dilation. |
| fill_holesopt | BOOLEAN | true | Fill enclosed holes within the repair limits, before dilation. |
| dilationopt | INT | 80–128 | Extra editing room in original-image pixels, after hole/notch filling. |
| mask_featheropt | INT | 80–64 | Blend inside the expanded mask. Separate from crop context and dilation. |
| nai_contextopt | NAI_CONTEXT | Connect the previous NAI generation context. Carries prompts, characters and generation settings; seed, size, strength, references and Anlas protection stay local. | |
| request_delay_secondsopt | FLOAT | 0.00–3600 | Wait before each NovelAI request, including each detail region and uncached Vibe encoding. 0 adds no delay. The built-in 2-second gap overlaps this timer; a longer server retry wait still applies. Preview-only runs do not wait. Stop cancels the countdown. |
| use_context_settingsopt | BOOLEAN | true | On: inherit prompts, characters, model and sampling settings from connected NAI context. Off: use this node's manual values. Both modes perform NovelAI correction; the seed stays local. |
| cfg_rescaleopt | FLOAT | 0.000–1 | — |
| prefer_brownianopt | BOOLEAN | false | — |
| variety_boostopt | BOOLEAN | true | — |
| context_modeopt | COMBO | inherit_all | With context enabled, inherit everything or replace only checked fields with this node's values. Unchecked fields still come from context. |
| override_promptopt | BOOLEAN | false | Use this node's prompt in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_negative_promptopt | BOOLEAN | false | Use this node's negative_prompt in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_modelopt | BOOLEAN | false | Use this node's model in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_sampleropt | BOOLEAN | false | Use this node's sampler in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_stepsopt | BOOLEAN | false | Use this node's steps in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_cfg_scaleopt | BOOLEAN | false | Use this node's cfg_scale in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_scheduleropt | BOOLEAN | false | Use this node's scheduler in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_cfg_rescaleopt | BOOLEAN | false | Use this node's cfg_rescale in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_prefer_brownianopt | BOOLEAN | false | Use this node's prefer_brownian in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_variety_boostopt | BOOLEAN | false | Use this node's variety_boost in override_selected mode. An empty string, zero or False is an intentional replacement. |
| override_characterPromptsopt | BOOLEAN | false | Replace the complete character list with characterPrompts, including negatives and positions. No connection clears the list. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask_visualization | IMAGE | — |
| matching_report | STRING | — |