Initial ComfyUI prompt builder nodes
This commit is contained in:
@@ -0,0 +1,278 @@
|
||||
# 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 Caption Naturalizer`
|
||||
|
||||
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 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`
|
||||
|
||||
## 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.
|
||||
|
||||
`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.
|
||||
Reference in New Issue
Block a user