346 lines
12 KiB
Markdown
346 lines
12 KiB
Markdown
# ComfyUI Prompt Builder
|
|
|
|
Custom ComfyUI node for building prompts from the existing `generate_prompt_batches.py`
|
|
generator without writing image batches.
|
|
|
|
The node is registered as:
|
|
|
|
- `prompt_builder / SxCP Prompt Builder`
|
|
- `prompt_builder / SxCP Seed Control`
|
|
- `prompt_builder / SxCP Camera Control`
|
|
- `prompt_builder / SxCP Caption Naturalizer`
|
|
- `prompt_builder / SxCP Insta/OF Options`
|
|
- `prompt_builder / SxCP Insta/OF Prompt Pair`
|
|
|
|
It outputs:
|
|
|
|
- `prompt`
|
|
- `negative_prompt`
|
|
- `caption`
|
|
- `metadata_json`
|
|
- `category`
|
|
- `subcategory`
|
|
|
|
`SxCP Seed Control` outputs `seed_config`, which can be connected to the prompt
|
|
builder's optional `seed_config` input.
|
|
|
|
`SxCP Camera Control` outputs `camera_config`, which can be connected to the
|
|
prompt builder or the Insta/OF pair node. It makes camera/framing first-class
|
|
instead of relying on a weak phrase inside the prompt.
|
|
|
|
Camera controls:
|
|
|
|
- `camera_mode`: `standard`, `handheld_selfie`, `mirror_selfie`,
|
|
`phone_tripod`, `creator_pov`, `bed_selfie`, `bathroom_mirror`,
|
|
`phone_flash`, or `action_cam`.
|
|
- `shot_size`: `auto`, `full_body`, `three_quarter`, `waist_up`, `close_up`,
|
|
or `extreme_close_up`.
|
|
- `angle`: `auto`, `eye_level`, `high_angle`, `low_angle`, `overhead`,
|
|
`side_profile`, `rear_view`, or `mirror_reflection`.
|
|
- `lens`: `auto`, `smartphone_wide`, `ultra_wide`, `portrait_lens`,
|
|
`telephoto`, or `macro_detail`.
|
|
- `distance`: `auto`, `arm_length`, `near_body`, `bedside`, or `room_corner`.
|
|
- `orientation`: `auto`, `vertical_story`, `square_feed`, or `horizontal`.
|
|
- `phone_visibility`: `auto`, `phone_visible`, `phone_hidden`,
|
|
`screen_reflection`, or `ring_light_visible`.
|
|
- `priority`: `soft_hint`, `strong`, or `locked`.
|
|
|
|
`SxCP Caption Naturalizer` rewrites tag-like captions or labeled prompts into
|
|
more natural language. Connect the prompt builder's `metadata_json` output to
|
|
`source_text` for the cleanest result. You can also connect `caption` or
|
|
`prompt`; in that case the node falls back to prompt-label parsing or comma-tag
|
|
cleanup.
|
|
|
|
Naturalizer controls:
|
|
|
|
- `input_hint`: `auto`, `metadata_json`, or `caption_or_prompt`.
|
|
- `detail_level`: `concise`, `balanced`, or `dense`.
|
|
- `style_policy`: `drop_style_tail` removes old fixed style tails; `keep_style_terms`
|
|
keeps style descriptions in the rewritten text.
|
|
- `trigger`: defaults to `sxcppnl7`.
|
|
- `include_trigger`: prepends the trigger as its own sentence.
|
|
|
|
It outputs:
|
|
|
|
- `natural_caption`
|
|
- `method`
|
|
|
|
`SxCP Insta/OF Prompt Pair` is a special paired-output mode. It creates one
|
|
shared primary creator descriptor, then returns both a softcore prompt and a
|
|
hardcore prompt from that same descriptor. This is useful when you want the same
|
|
person/look/scene continuity but need two different prompt strengths.
|
|
|
|
It outputs:
|
|
|
|
- `softcore_prompt`
|
|
- `hardcore_prompt`
|
|
- `softcore_negative_prompt`
|
|
- `hardcore_negative_prompt`
|
|
- `softcore_caption`
|
|
- `hardcore_caption`
|
|
- `shared_descriptor`
|
|
- `metadata_json`
|
|
|
|
`SxCP Insta/OF Options` outputs `options_json`, which can be connected to the
|
|
pair node. Defaults are set so the softcore prompt is solo while the hardcore
|
|
prompt can include partners. It also defaults the camera to handheld selfie
|
|
framing. For stronger camera control, connect `SxCP Camera Control` to the pair
|
|
node's optional `camera_config` input.
|
|
|
|
Options:
|
|
|
|
- `softcore_cast`: `solo` or `same_as_hardcore`.
|
|
- `hardcore_cast`: `use_counts`, `couple`, `threesome`, or `group`.
|
|
- `hardcore_women_count` and `hardcore_men_count`: used when `hardcore_cast` is
|
|
`use_counts`. The pair mode always keeps at least one adult woman as the
|
|
primary creator so the shared descriptor remains valid.
|
|
- `softcore_level`: `social_tease`, `lingerie_tease`, `implied_nude`, or
|
|
`explicit_tease`.
|
|
- `hardcore_level`: `explicit` or `hardcore`.
|
|
- `platform_style`: `hybrid`, `instagram`, or `onlyfans`.
|
|
- `continuity`: `same_creator_same_room` keeps the scene/composition aligned;
|
|
`same_creator_new_scene` keeps the same creator descriptor but lets the
|
|
hardcore scene use its own setting.
|
|
- `softcore_camera_mode`: base camera mode for the softcore output.
|
|
- `hardcore_camera_mode`: `same_as_softcore` or a separate base camera mode for
|
|
the hardcore output.
|
|
|
|
## Built-In Categories
|
|
|
|
The node keeps the original generator controls:
|
|
|
|
- `category`: `auto_weighted`, `woman`, `man`, `couple`, `group_or_layout`, or a custom JSON category.
|
|
- `clothing`: `full` or `minimal`.
|
|
- `minimal_clothing_ratio`: `-1` disables mixing; `0.0` to `1.0` mixes minimal/full clothing.
|
|
- `ethnicity`: `any`, `asian`, `white_asian`.
|
|
- `poses`: `standard` or `evocative`.
|
|
- `standard_pose_ratio`: `-1` disables mixing; `0.0` to `1.0` mixes standard/evocative poses.
|
|
- `backside_bias`: `0.0` to `1.0`, applies to evocative single-subject poses.
|
|
- `figure`: `curvy`, `balanced`, `bombshell`.
|
|
- `no_plus_women`: excludes plus-size women.
|
|
- `no_black`: excludes Black/African-coded women from women-focused pools.
|
|
- Optional `camera_config`: connect `SxCP Camera Control` to force selfie,
|
|
phone, lens, angle, distance, crop, and camera-priority behavior. This applies
|
|
to custom categories too, including `Hardcore sexual poses`.
|
|
|
|
`auto_weighted` uses the original batch mix: mostly women, then men, couples, and
|
|
group/layout rows. Direct categories generate only that selected category.
|
|
|
|
## Custom Categories
|
|
|
|
Add or edit JSON files in `categories/*.json`. Each file can define new main
|
|
categories, subcategories, and optional extensions to the built-in pools. Restart
|
|
or reload ComfyUI after changing JSON so dropdown choices are rebuilt.
|
|
|
|
Included JSON categories:
|
|
|
|
- `Casual clothes`
|
|
- `Provocative erotic clothes`
|
|
- `Hardcore sexual poses`
|
|
|
|
Example:
|
|
|
|
```json
|
|
{
|
|
"version": 1,
|
|
"categories": [
|
|
{
|
|
"name": "Casual clothes",
|
|
"slug": "casual_clothes",
|
|
"subject_type": "woman",
|
|
"item_label": "Clothing",
|
|
"style": "tasteful adult fashion-editorial coloured-pencil comic illustration",
|
|
"subcategories": [
|
|
{
|
|
"name": "Streetwear",
|
|
"slug": "streetwear",
|
|
"items": [
|
|
"oversized hoodie with slim jeans and clean sneakers",
|
|
"cropped bomber jacket with cargo pants and chunky trainers"
|
|
],
|
|
"scenes": [
|
|
{
|
|
"slug": "city_crosswalk",
|
|
"prompt": "sunlit city crosswalk with storefront reflections"
|
|
}
|
|
],
|
|
"poses": [
|
|
"standing with one hand in a pocket",
|
|
"walking forward with a casual runway stride"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Custom categories do not need a Python generator. If no `prompt_template` is
|
|
provided, the node uses a generic composer that selects subject appearance,
|
|
scene, pose, expression, composition, and a random item from the selected
|
|
subcategory.
|
|
|
|
For large categories, prefer `item_templates` plus `item_axes` instead of writing
|
|
every final item by hand:
|
|
|
|
```json
|
|
{
|
|
"name": "Example clothes",
|
|
"subject_type": "woman",
|
|
"subcategories": [
|
|
{
|
|
"name": "Lingerie",
|
|
"item_templates": [
|
|
"{color} {fabric} {top} with {bottom} and {stockings}"
|
|
],
|
|
"item_axes": {
|
|
"color": ["black", "red", "ivory"],
|
|
"fabric": ["lace", "satin", "transparent mesh"],
|
|
"top": ["balconette bra", "open-cup bra"],
|
|
"bottom": ["matching thong", "high-cut g-string"],
|
|
"stockings": ["thigh-high stockings", "fishnet stockings"]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
The node chooses one template, fills each placeholder from the matching axis,
|
|
then records the selected axis values in `metadata_json`.
|
|
|
|
Supported `subject_type` values:
|
|
|
|
- `single_any`
|
|
- `woman`
|
|
- `man`
|
|
- `couple`
|
|
- `group`
|
|
- `layout`
|
|
- `scene`
|
|
- `configured_cast`
|
|
|
|
`configured_cast` uses the node's `women_count` and `men_count` inputs. It adds
|
|
template fields for `{women_count}`, `{men_count}`, `{person_count}`,
|
|
`{cast_summary}`, `{scene_kind}`, and `{role_graph}`. This is intended for
|
|
categories where the same prompt generator should support couples, threesomes,
|
|
and larger groups.
|
|
|
|
`{role_graph}` is a generated choreography sentence that assigns roles to the
|
|
cast, such as who penetrates, who receives oral, and who joins from the side.
|
|
It is currently most useful for `Hardcore sexual poses`.
|
|
|
|
Subcategories, templates, and axis values can declare cast constraints:
|
|
|
|
```json
|
|
{
|
|
"name": "Threesomes",
|
|
"min_people": 3,
|
|
"item_axes": {
|
|
"act": [
|
|
{
|
|
"text": "strap-on penetration and cunnilingus",
|
|
"cast": "women_only"
|
|
},
|
|
{
|
|
"text": "male/male oral and anal contact",
|
|
"cast": "men_only"
|
|
},
|
|
{
|
|
"text": "front-and-back penetration",
|
|
"cast": "mixed"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Supported constraints:
|
|
|
|
- `min_women`, `max_women`
|
|
- `min_men`, `max_men`
|
|
- `min_people`, `max_people`
|
|
- `cast` or `requires`: `women_only`, `men_only`, `mixed`, `has_women`,
|
|
`has_men`, `solo`, `couple`, `threesome`, `group`
|
|
|
|
If an exact subcategory is not compatible with `women_count` and `men_count`,
|
|
the node raises a clear error instead of generating an impossible prompt.
|
|
|
|
Use the `subcategory` dropdown to select either `random` or an exact
|
|
`Main category / Subcategory` path. Exact paths override the `category` dropdown,
|
|
which is useful because ComfyUI does not provide dependent dropdowns from Python
|
|
alone.
|
|
|
|
## Seed Control
|
|
|
|
The main `seed` input is still the default master seed. Connect `SxCP Seed
|
|
Control` to `seed_config` when you want to lock or vary specific axes.
|
|
|
|
Seed values:
|
|
|
|
- `-1`: follow the main seed.
|
|
- `0` or higher: override only that axis.
|
|
|
|
Axes:
|
|
|
|
- `category_seed`: custom category selection when `custom_random` is used.
|
|
- `subcategory_seed`: random subcategory selection.
|
|
- `content_seed`: generated item content, such as outfit wording.
|
|
- `person_seed`: appearance/person selection.
|
|
- `scene_seed`: scene/environment selection.
|
|
- `pose_seed`: body pose selection. For `Hardcore sexual poses`, this also drives the generated sexual pose content.
|
|
- `role_seed`: participant choreography for `{role_graph}`. If left at `-1`, it follows `pose_seed`.
|
|
- `expression_seed`: facial expression selection.
|
|
- `composition_seed`: camera/composition selection.
|
|
|
|
Example workflow: if the person and scene are right but the pose is wrong, keep
|
|
`person_seed` and `scene_seed` fixed, then change `pose_seed`. If the cast roles
|
|
are wrong but the act wording is good, change `role_seed`. If the clothing or
|
|
sexual act wording is wrong, change `content_seed`; for pose-driven categories,
|
|
change `pose_seed`.
|
|
|
|
## Pool Extensions
|
|
|
|
Use `pool_extensions` to add new entries to built-in pools without editing
|
|
Python:
|
|
|
|
```json
|
|
{
|
|
"pool_extensions": {
|
|
"women_clothes": ["relaxed high-waist jeans with a fitted ribbed tank top"],
|
|
"men_clothes": ["clean white T-shirt with relaxed jeans and canvas sneakers"],
|
|
"poses": ["standing with a relaxed hand-on-hip pose"],
|
|
"expressions": ["easygoing half-smile"],
|
|
"scenes": [
|
|
{
|
|
"slug": "city_cafe",
|
|
"prompt": "quiet city cafe terrace with morning light and small round tables"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Known extension pools:
|
|
|
|
`women_clothes`, `women_clothes_minimal`, `men_clothes`, `men_clothes_minimal`,
|
|
`couple_outfits`, `couple_outfits_minimal`, `poses`, `evocative_poses`,
|
|
`backside_poses`, `expressions`, `compositions`, `props`, `figure_curvy`,
|
|
`figure_athletic`, `figure_bombshell`, `scenes`, `group_scenes`,
|
|
`layouts_full`, `layouts_minimal`, `group_compositions`, `group_ages`.
|
|
|
|
## Templates
|
|
|
|
A category, subcategory, or individual item can provide `prompt_template` and
|
|
`caption_template`. Templates can use these fields:
|
|
|
|
`{trigger}`, `{main_category}`, `{subcategory}`, `{item}`, `{item_label}`,
|
|
`{subject}`, `{subject_phrase}`, `{age}`, `{body}`, `{body_phrase}`, `{skin}`,
|
|
`{hair}`, `{eyes}`, `{figure}`, `{scene}`, `{pose}`, `{expression}`,
|
|
`{composition}`, `{style}`, `{positive_suffix}`, `{negative_prompt}`,
|
|
`{women_count}`, `{men_count}`, `{person_count}`, `{cast_summary}`,
|
|
`{scene_kind}`, `{role_graph}`.
|
|
|
|
If `prepend_trigger_to_prompt` is enabled, the node prepends the trigger to the
|
|
positive prompt. Disable it for output closer to the original script's `prompt`
|
|
field.
|