7 Commits

Author SHA1 Message Date
Aodhan Collins
b9196ef5f5 Add structured logging for job queue and workflow prompts
Replace bare print() calls with Python logging module. Job lifecycle
(enqueue, start, ComfyUI acceptance, completion, failure) now emits
timestamped INFO logs to stdout, captured by Docker. Failures use
logger.exception() for full tracebacks. Workflow prompt block logs as
a single INFO entry; LoRA chain details moved to DEBUG level.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 22:55:53 +00:00
Aodhan Collins
a38915b354 Refactor UI, settings, and code quality across all categories
- Fix Replace Cover: routes now read preview_path from form POST instead of session (session writes from background threads were lost)
- Fix batch generation: submit all jobs immediately, poll all in parallel via Promise.all
- Fix label NameError in character generate route
- Fix style detail missing characters context
- Selected Preview pane: click any image to select it; data-preview-path on all images across all 8 detail templates
- Gallery → Library rename across all index page headings and navbar
- Settings: add configurable LoRA/checkpoint directories; default checkpoint selector moved from navbar to settings page
- Consolidate 6 get_available_*_loras() into single get_available_loras(category) reading from Settings
- ComfyUI tooltip shows currently loaded checkpoint name
- Remove navbar checkpoint bar
- Phase 4 cleanup: remove dead _queue_generation(), add session.modified, standardize log prefixes, rename action_type → action

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 22:48:28 +00:00
Aodhan Collins
da55b0889b Add Docker support and refactor prompt/queue internals
- Add Dockerfile, docker-compose.yml, .dockerignore for containerised deployment
- Extract _resolve_character(), _ensure_character_fields(), _append_background() helpers to eliminate repeated inline character-field injection and background-tag patterns across all secondary-category generate routes
- Add _IDENTITY_KEYS / _WARDROBE_KEYS constants
- Fix build_extras_prompt() bug: detailer prompt (a list) was being appended as a single item instead of extended
- Replace all per-route _finalize closures with _make_finalize() factory, reducing duplication across 10 generate routes
- Add _prune_job_history() called each worker loop iteration to prevent unbounded memory growth
- Remove 10 orphaned legacy finalize_generation HTTP routes and check_status route (superseded by job queue API since job-queue branch)
- Remove one-time migration scripts (migrate_actions, migrate_detailers, migrate_lora_weight_range, migrate_wardrobe)
- Update CLAUDE.md and README.md to document new helpers, queue architecture, and Docker deployment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 16:46:36 +00:00
Aodhan Collins
9b143e65b1 Redesign gallery grid layout and update CSS across all index pages
Increase card density with more columns per breakpoint (2→6 across sm/xl).
Refactor style.css for consistent card sizing, spacing, and responsive layout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 21:43:40 +00:00
Aodhan Collins
27d2a70867 Merge branch 'job-queue'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 02:33:04 +00:00
Aodhan Collins
3c828a170f Add background job queue system for generation
- Implements sequential job queue with background worker thread (_enqueue_job, _queue_worker)
- All generate routes now return job_id instead of prompt_id; frontend polls /api/queue/<id>/status
- Queue management UI in navbar with live badge, job list, pause/resume/remove controls
- Fix: replaced url_for() calls inside finalize callbacks with direct string paths (url_for raises RuntimeError without request context in background threads)
- Batch cover generation now uses two-phase pattern: queue all jobs upfront, then poll concurrently via Promise.all so page navigation doesn't interrupt the process
- Strengths gallery sweep migrated to same two-phase pattern; sgStop() cancels queued jobs server-side
- LoRA weight randomisation via lora_weight_min/lora_weight_max already present in _resolve_lora_weight

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 02:32:50 +00:00
Aodhan Collins
ae7ba961c1 Add danbooru-mcp auto-start, git sync, status API endpoints, navbar status indicators, and LLM format retry
- app.py: add subprocess import; add _ensure_mcp_repo() to clone/pull
  danbooru-mcp from https://git.liveaodh.com/aodhan/danbooru-mcp into
  tools/danbooru-mcp/ at startup; add ensure_mcp_server_running() which
  calls _ensure_mcp_repo() then starts the Docker container if not running;
  add GET /api/status/comfyui and GET /api/status/mcp health endpoints;
  fix call_llm() to retry up to 3 times on unexpected response format
  (KeyError/IndexError), logging the raw response and prompting the LLM
  to respond with valid JSON before each retry
- templates/layout.html: add ComfyUI and MCP status dot indicators to
  navbar; add polling JS that checks both endpoints on load and every 30s
- static/style.css: add .service-status, .status-dot, .status-ok,
  .status-error, .status-checking styles and status-pulse keyframe animation
- .gitignore: add tools/ to exclude the cloned danbooru-mcp repo
2026-03-03 00:57:27 +00:00
1201 changed files with 18962 additions and 6313 deletions

8
.dockerignore Normal file
View File

@@ -0,0 +1,8 @@
venv/
__pycache__/
*.pyc
instance/
flask_session/
static/uploads/
tools/
.git/

3
.gitignore vendored
View File

@@ -31,3 +31,6 @@ Thumbs.db
# Logs
*.log
# Tools (cloned at runtime — not tracked in this repo)
tools/

445
CLAUDE.md Normal file
View File

@@ -0,0 +1,445 @@
# GAZE — Character Browser: LLM Development Guide
## What This Project Is
GAZE is a Flask web app for managing AI image generation assets and generating images via ComfyUI. It is a **personal creative tool** for organizing characters, outfits, actions, styles, scenes, and detailers — all of which map to Stable Diffusion LoRAs and prompt fragments — and generating images by wiring those assets into a ComfyUI workflow at runtime.
The app is deployed locally, connects to a local ComfyUI instance at `http://127.0.0.1:8188`, and uses SQLite for persistence. LoRA and model files live on `/mnt/alexander/AITools/Image Models/`.
---
## Architecture
### Entry Point
- `app.py` — Single-file Flask app (~4500+ lines). All routes, helpers, ComfyUI integration, LLM calls, and sync functions live here.
- `models.py` — SQLAlchemy models only.
- `comfy_workflow.json` — ComfyUI workflow template with placeholder strings.
### Database
SQLite at `instance/database.db`, managed by Flask-SQLAlchemy. The DB is a cache of the JSON files on disk — the JSON files are the source of truth.
**Models**: `Character`, `Look`, `Outfit`, `Action`, `Style`, `Scene`, `Detailer`, `Checkpoint`, `Settings`
All category models (except Settings and Checkpoint) share this pattern:
- `{entity}_id` — canonical ID (from JSON, often matches filename without extension)
- `slug` — URL-safe version of the ID (alphanumeric + underscores only, via `re.sub(r'[^a-zA-Z0-9_]', '', id)`)
- `name` — display name
- `filename` — original JSON filename
- `data` — full JSON blob (SQLAlchemy JSON column)
- `default_fields` — list of `section::key` strings saved as the user's preferred prompt fields
- `image_path` — relative path under `static/uploads/`
### Data Flow: JSON → DB → Prompt → ComfyUI
1. **JSON files** in `data/{characters,clothing,actions,styles,scenes,detailers,looks}/` are loaded by `sync_*()` functions into SQLite.
2. At generation time, `build_prompt(data, selected_fields, default_fields, active_outfit)` converts the character JSON blob into `{"main": ..., "face": ..., "hand": ...}` prompt strings.
3. `_prepare_workflow(workflow, character, prompts, ...)` wires prompts and LoRAs into the loaded `comfy_workflow.json`.
4. `queue_prompt(workflow, client_id)` POSTs the workflow to ComfyUI's `/prompt` endpoint.
5. The app polls `get_history(prompt_id)` and retrieves the image via `get_image(filename, subfolder, type)`.
---
## ComfyUI Workflow Node Map
The workflow (`comfy_workflow.json`) uses string node IDs. These are the critical nodes:
| Node | Role |
|------|------|
| `3` | Main KSampler |
| `4` | Checkpoint loader |
| `5` | Empty latent (width/height) |
| `6` | Positive prompt — contains `{{POSITIVE_PROMPT}}` placeholder |
| `7` | Negative prompt |
| `8` | VAE decode |
| `9` | Save image |
| `11` | Face ADetailer |
| `13` | Hand ADetailer |
| `14` | Face detailer prompt — contains `{{FACE_PROMPT}}` placeholder |
| `15` | Hand detailer prompt — contains `{{HAND_PROMPT}}` placeholder |
| `16` | Character LoRA (or Look LoRA when a Look is active) |
| `17` | Outfit LoRA |
| `18` | Action LoRA |
| `19` | Style / Detailer / Scene LoRA (priority: style > detailer > scene) |
LoRA nodes chain: `4 → 16 → 17 → 18 → 19`. Unused LoRA nodes are bypassed by pointing `model_source`/`clip_source` directly to the prior node. All model/clip consumers (nodes 3, 6, 7, 11, 13, 14, 15) are wired to the final `model_source`/`clip_source` at the end of `_prepare_workflow`.
---
## Key Helpers
### `build_prompt(data, selected_fields, default_fields, active_outfit)`
Converts a character (or combined) data dict into `{"main", "face", "hand"}` prompt strings.
Field selection priority:
1. `selected_fields` (from form submission) — if non-empty, use it exclusively
2. `default_fields` (saved in DB per character) — used if no form selection
3. Select all (fallback)
Fields are addressed as `"section::key"` strings (e.g. `"identity::hair"`, `"wardrobe::top"`, `"special::name"`, `"lora::lora_triggers"`).
Wardrobe format: Characters support a **nested** format where `wardrobe` is a dict of outfit names → outfit dicts (e.g. `{"default": {...}, "swimsuit": {...}}`). Legacy characters have a flat `wardrobe` dict. `Character.get_active_wardrobe()` handles both.
### `build_extras_prompt(actions, outfits, scenes, styles, detailers)`
Used by the Generator page. Combines prompt text from all checked items across categories into a single string. LoRA triggers, wardrobe fields, scene fields, style fields, detailer prompts — all concatenated.
### `_prepare_workflow(workflow, character, prompts, checkpoint, custom_negative, outfit, action, style, detailer, scene, width, height, checkpoint_data, look)`
The core workflow wiring function. Mutates the loaded workflow dict in place and returns it. Key behaviours:
- Replaces `{{POSITIVE_PROMPT}}`, `{{FACE_PROMPT}}`, `{{HAND_PROMPT}}` in node inputs.
- If `look` is provided, uses the Look's LoRA in node 16 instead of the character's LoRA, and prepends the Look's negative to node 7.
- Chains LoRA nodes dynamically — only active LoRAs participate in the chain.
- Randomises seeds for nodes 3, 11, 13.
- Applies checkpoint-specific settings (steps, cfg, sampler, VAE, base prompts) via `_apply_checkpoint_settings`.
- Runs `_cross_dedup_prompts` on nodes 6 and 7 as the final step before returning.
### `_cross_dedup_prompts(positive, negative)`
Cross-deduplicates tags between the positive and negative prompt strings. For each tag present in both, repeatedly removes the first occurrence from each side until the tag exists on only one side (or neither). Equal counts cancel completely; any excess on one side is retained. This allows deliberate overrides: adding a tag twice in positive while it appears once in negative leaves one copy in positive.
Called as the last step of `_prepare_workflow`, after `_apply_checkpoint_settings` has added `base_positive`/`base_negative`, so it operates on fully-assembled prompts.
### `_IDENTITY_KEYS` / `_WARDROBE_KEYS` (module-level constants)
Lists of canonical field names for the `identity` and `wardrobe` sections. Used by `_ensure_character_fields()` to avoid hard-coding key lists in every route.
### `_resolve_character(character_slug)`
Returns a `Character` ORM object for a given slug string. Handles the `"__random__"` sentinel by selecting a random character. Returns `None` if `character_slug` is falsy or no match is found. Every route that accepts an optional character dropdown (outfit, action, style, scene, detailer, checkpoint, look generate routes) uses this instead of an inline if/elif block.
### `_ensure_character_fields(character, selected_fields, include_wardrobe=True, include_defaults=False)`
Mutates `selected_fields` in place, appending any populated identity, wardrobe, and optional defaults keys that are not already present. Ensures `"special::name"` is always included. Called in every secondary-category generate route immediately after `_resolve_character()` to guarantee the character's essential fields are sent to `build_prompt`.
### `_append_background(prompts, character=None)`
Appends a `"<primary_color> simple background"` tag (or plain `"simple background"` if no primary color) to `prompts['main']`. Called in outfit, action, style, detailer, and checkpoint generate routes instead of repeating the same inline string construction.
### `_make_finalize(category, slug, db_model_class=None, action=None)`
Factory function that returns a `_finalize(comfy_prompt_id, job)` callback closure. The closure:
1. Calls `get_history()` and `get_image()` to retrieve the generated image from ComfyUI.
2. Saves the image to `static/uploads/<category>/<slug>/gen_<timestamp>.png`.
3. Sets `job['result']` with `image_url` and `relative_path`.
4. If `db_model_class` is provided **and** (`action` is `None` or `action == 'replace'`), updates the ORM object's `image_path` and commits.
All `generate` routes pass a `_make_finalize(...)` call as the finalize argument to `_enqueue_job()` instead of defining an inline closure.
### `_prune_job_history(max_age_seconds=3600)`
Removes entries from `_job_history` that are in a terminal state (`done`, `failed`, `removed`) and older than `max_age_seconds`. Called at the end of every worker loop iteration to prevent unbounded memory growth.
### `_queue_generation(character, action, selected_fields, client_id)`
Convenience wrapper for character detail page generation. Loads workflow, calls `build_prompt`, calls `_prepare_workflow`, calls `queue_prompt`.
### `_queue_detailer_generation(detailer_obj, character, selected_fields, client_id, action, extra_positive, extra_negative)`
Generation helper for the detailer detail page. Merges the detailer's `prompt` list (flattened — `prompt` may be a list or string) and LoRA triggers into the character data before calling `build_prompt`. Appends `extra_positive` to `prompts["main"]` and passes `extra_negative` as `custom_negative` to `_prepare_workflow`. Accepts an optional `action` (Action model object) passed through to `_prepare_workflow` for node 18 LoRA wiring.
### `_get_default_checkpoint()`
Returns `(checkpoint_path, checkpoint_data)` from the Flask session's `default_checkpoint` key. The global default checkpoint is set via the navbar dropdown and stored server-side in the filesystem session.
### `call_llm(prompt, system_prompt)`
OpenAI-compatible chat completion call supporting:
- **OpenRouter** (cloud, configured API key + model)
- **Ollama** / **LMStudio** (local, configured base URL + model)
Implements a tool-calling loop (up to 10 turns) using `DANBOORU_TOOLS` (search_tags, validate_tags, suggest_tags) via an MCP Docker container (`danbooru-mcp:latest`). If the provider rejects tools (HTTP 400), retries without tools.
---
## JSON Data Schemas
### Character (`data/characters/*.json`)
```json
{
"character_id": "tifa_lockhart",
"character_name": "Tifa Lockhart",
"identity": { "base_specs": "", "hair": "", "eyes": "", "hands": "", "arms": "", "torso": "", "pelvis": "", "legs": "", "feet": "", "extra": "" },
"defaults": { "expression": "", "pose": "", "scene": "" },
"wardrobe": {
"default": { "full_body": "", "headwear": "", "top": "", "bottom": "", "legwear": "", "footwear": "", "hands": "", "gloves": "", "accessories": "" }
},
"styles": { "aesthetic": "", "primary_color": "", "secondary_color": "", "tertiary_color": "" },
"lora": { "lora_name": "Illustrious/Looks/tifa.safetensors", "lora_weight": 0.8, "lora_triggers": "" },
"tags": [],
"participants": { "orientation": "1F", "solo_focus": "true" }
}
```
`participants` is optional; when absent, `(solo:1.2)` is injected. `orientation` is parsed by `parse_orientation()` into Danbooru tags (`1girl`, `hetero`, etc.).
### Outfit (`data/clothing/*.json`)
```json
{
"outfit_id": "french_maid_01",
"outfit_name": "French Maid",
"wardrobe": { "full_body": "", "headwear": "", "top": "", "bottom": "", "legwear": "", "footwear": "", "hands": "", "accessories": "" },
"lora": { "lora_name": "Illustrious/Clothing/maid.safetensors", "lora_weight": 0.8, "lora_triggers": "" },
"tags": []
}
```
### Action (`data/actions/*.json`)
```json
{
"action_id": "sitting",
"action_name": "Sitting",
"action": { "full_body": "", "additional": "", "head": "", "eyes": "", "arms": "", "hands": "" },
"lora": { "lora_name": "", "lora_weight": 1.0, "lora_triggers": "" },
"tags": []
}
```
### Scene (`data/scenes/*.json`)
```json
{
"scene_id": "beach",
"scene_name": "Beach",
"scene": { "background": "", "foreground": "", "furniture": "", "colors": "", "lighting": "", "theme": "" },
"lora": { "lora_name": "", "lora_weight": 1.0, "lora_triggers": "" },
"tags": []
}
```
### Style (`data/styles/*.json`)
```json
{
"style_id": "watercolor",
"style_name": "Watercolor",
"style": { "artist_name": "", "artistic_style": "" },
"lora": { "lora_name": "", "lora_weight": 1.0, "lora_triggers": "" }
}
```
### Detailer (`data/detailers/*.json`)
```json
{
"detailer_id": "detailed_skin",
"detailer_name": "Detailed Skin",
"prompt": ["detailed skin", "pores"],
"focus": { "face": true, "hands": true },
"lora": { "lora_name": "", "lora_weight": 1.0, "lora_triggers": "" }
}
```
### Look (`data/looks/*.json`)
```json
{
"look_id": "tifa_casual",
"look_name": "Tifa Casual",
"character_id": "tifa_lockhart",
"positive": "casual clothes, jeans",
"negative": "revealing",
"lora": { "lora_name": "Illustrious/Looks/tifa_casual.safetensors", "lora_weight": 0.85, "lora_triggers": "" },
"tags": []
}
```
Looks occupy LoRA node 16, overriding the character's own LoRA. The Look's `negative` is prepended to the workflow's negative prompt.
### Checkpoint (`data/checkpoints/*.json`)
```json
{
"checkpoint_path": "Illustrious/model.safetensors",
"checkpoint_name": "Model Display Name",
"base_positive": "anime",
"base_negative": "text, logo",
"steps": 25,
"cfg": 5,
"sampler_name": "euler_ancestral",
"scheduler": "normal",
"vae": "integrated"
}
```
Checkpoint JSONs are keyed by `checkpoint_path`. If no JSON exists for a discovered model file, `_default_checkpoint_data()` provides defaults.
---
## URL Routes
### Characters
- `GET /` — character gallery (index)
- `GET /character/<slug>` — character detail with generation UI
- `POST /character/<slug>/generate` — queue generation (AJAX or form); returns `{"job_id": ...}`
- `POST /character/<slug>/replace_cover_from_preview` — promote preview to cover
- `GET/POST /character/<slug>/edit` — edit character data
- `POST /character/<slug>/upload` — upload cover image
- `POST /character/<slug>/save_defaults` — save default field selection
- `POST /character/<slug>/outfit/switch|add|delete|rename` — manage per-character wardrobe outfits
- `GET/POST /create` — create new character (blank or LLM-generated)
- `POST /rescan` — sync DB from JSON files
### Category Pattern (Outfits, Actions, Styles, Scenes, Detailers)
Each category follows the same URL pattern:
- `GET /<category>/` — gallery
- `GET /<category>/<slug>` — detail + generation UI
- `POST /<category>/<slug>/generate` — queue generation; returns `{"job_id": ...}`
- `POST /<category>/<slug>/replace_cover_from_preview`
- `GET/POST /<category>/<slug>/edit`
- `POST /<category>/<slug>/upload`
- `POST /<category>/<slug>/save_defaults`
- `POST /<category>/<slug>/clone` — duplicate entry
- `POST /<category>/<slug>/save_json` — save raw JSON (from modal editor)
- `POST /<category>/rescan`
- `POST /<category>/bulk_create` — LLM-generate entries from LoRA files on disk
### Looks
- `GET /looks` — gallery
- `GET /look/<slug>` — detail
- `GET/POST /look/<slug>/edit`
- `POST /look/<slug>/generate` — queue generation; returns `{"job_id": ...}`
- `POST /look/<slug>/replace_cover_from_preview`
- `GET/POST /look/create`
- `POST /looks/rescan`
### Generator (Mix & Match)
- `GET/POST /generator` — freeform generator with multi-select accordion UI
- `POST /generator/preview_prompt` — AJAX: preview composed prompt without generating
### Checkpoints
- `GET /checkpoints` — gallery
- `GET /checkpoint/<slug>` — detail + generation settings editor
- `POST /checkpoint/<slug>/save_json`
- `POST /checkpoints/rescan`
### Job Queue API
All generation routes use the background job queue. Frontend polls:
- `GET /api/queue/<job_id>/status` — returns `{"status": "pending"|"running"|"done"|"failed", "result": {...}}`
Image retrieval is handled server-side by the `_make_finalize()` callback; there are no separate client-facing finalize routes.
### Utilities
- `POST /set_default_checkpoint` — save default checkpoint to session
- `GET /get_missing_{characters,outfits,actions,scenes}` — AJAX: list items without cover images
- `POST /generate_missing` — batch generate covers for all characters missing one (uses job queue)
- `POST /clear_all_covers` / `clear_all_{outfit,action,scene}_covers`
- `GET /gallery` — global image gallery browsing `static/uploads/`
- `GET/POST /settings` — LLM provider configuration
- `POST /resource/<category>/<slug>/delete` — soft (JSON only) or hard (JSON + safetensors) delete
---
## Frontend
- Bootstrap 5.3 (CDN). Custom styles in `static/style.css`.
- All templates extend `templates/layout.html`. The base layout provides:
- `{% block content %}` — main page content
- `{% block scripts %}` — additional JS at end of body
- Navbar with links to all sections
- Global default checkpoint selector (saves to session via AJAX)
- Resource delete modal (soft/hard) shared across gallery pages
- `initJsonEditor(saveUrl)` — shared JSON editor modal (simple form + raw textarea tabs)
- Context processors inject `all_checkpoints`, `default_checkpoint_path`, and `COMFYUI_WS_URL` into every template.
- **No `{% block head %}` exists** in layout.html — do not try to use it.
- Generation is async: JS submits the form via AJAX (`X-Requested-With: XMLHttpRequest`), receives a `{"job_id": ...}` response, then polls `/api/queue/<job_id>/status` every ~1.5 seconds until `status == "done"`. The server-side worker handles all ComfyUI polling and image saving via the `_make_finalize()` callback. There are no client-facing finalize HTTP routes.
---
## LLM Integration
### System Prompts
Text files in `data/prompts/` define JSON output schemas for LLM-generated entries:
- `character_system.txt` — character JSON schema
- `outfit_system.txt` — outfit JSON schema
- `action_system.txt`, `scene_system.txt`, `style_system.txt`, `detailer_system.txt`, `look_system.txt`, `checkpoint_system.txt`
Used by: character/outfit/action/scene/style create forms, and bulk_create routes.
### Danbooru MCP Tools
The LLM loop in `call_llm()` provides three tools via a Docker-based MCP server (`danbooru-mcp:latest`):
- `search_tags(query, limit, category)` — prefix search
- `validate_tags(tags)` — exact-match validation
- `suggest_tags(partial, limit, category)` — autocomplete
The LLM uses these to verify and discover correct Danbooru-compatible tags for prompts.
All system prompts (`character_system.txt`, `outfit_system.txt`, `action_system.txt`, `scene_system.txt`, `style_system.txt`, `detailer_system.txt`, `look_system.txt`, `checkpoint_system.txt`) instruct the LLM to use these tools before finalising any tag values. `checkpoint_system.txt` applies them specifically to the `base_positive` and `base_negative` fields.
---
## LoRA File Paths
LoRA filenames in JSON are stored as paths relative to ComfyUI's `models/lora/` root:
| Category | Path prefix | Example |
|----------|-------------|---------|
| Character / Look | `Illustrious/Looks/` | `Illustrious/Looks/tifa_v2.safetensors` |
| Outfit | `Illustrious/Clothing/` | `Illustrious/Clothing/maid.safetensors` |
| Action | `Illustrious/Poses/` | `Illustrious/Poses/sitting.safetensors` |
| Style | `Illustrious/Styles/` | `Illustrious/Styles/watercolor.safetensors` |
| Detailer | `Illustrious/Detailers/` | `Illustrious/Detailers/skin.safetensors` |
| Scene | `Illustrious/Backgrounds/` | `Illustrious/Backgrounds/beach.safetensors` |
Checkpoint paths: `Illustrious/<filename>.safetensors` or `Noob/<filename>.safetensors`.
Absolute paths on disk:
- Checkpoints: `/mnt/alexander/AITools/Image Models/Stable-diffusion/{Illustrious,Noob}/`
- LoRAs: `/mnt/alexander/AITools/Image Models/lora/Illustrious/{Looks,Clothing,Poses,Styles,Detailers,Backgrounds}/`
---
## Adding a New Category
To add a new content category (e.g. "Poses" as a separate concept from Actions), the pattern is:
1. **Model** (`models.py`): Add a new SQLAlchemy model with the standard fields.
2. **Sync function** (`app.py`): Add `sync_newcategory()` following the pattern of `sync_outfits()`.
3. **Data directory**: Add `app.config['NEWCATEGORY_DIR'] = 'data/newcategory'`.
4. **Routes**: Implement index, detail, edit, generate, finalize_generation, replace_cover_from_preview, upload, save_defaults, clone, rescan routes. Follow the outfit/scene pattern exactly.
5. **Templates**: Create `templates/newcategory/{index,detail,edit,create}.html` extending `layout.html`.
6. **Nav**: Add link to navbar in `templates/layout.html`.
7. **`with_appcontext`**: Call `sync_newcategory()` in the `with app.app_context()` block at the bottom of `app.py`.
8. **Generator page**: Add to `generator()` route, `build_extras_prompt()`, and `templates/generator.html` accordion.
---
## Session Keys
The Flask filesystem session stores:
- `default_checkpoint` — checkpoint_path string for the global default
- `prefs_{slug}` — selected_fields list for character detail page
- `preview_{slug}` — relative image path of last character preview
- `prefs_outfit_{slug}`, `preview_outfit_{slug}`, `char_outfit_{slug}` — outfit detail state
- `prefs_action_{slug}`, `preview_action_{slug}`, `char_action_{slug}` — action detail state
- `prefs_scene_{slug}`, `preview_scene_{slug}`, `char_scene_{slug}` — scene detail state
- `prefs_detailer_{slug}`, `preview_detailer_{slug}`, `char_detailer_{slug}`, `action_detailer_{slug}`, `extra_pos_detailer_{slug}`, `extra_neg_detailer_{slug}` — detailer detail state (selected fields, preview image, character, action LoRA, extra positive prompt, extra negative prompt)
- `prefs_style_{slug}`, `preview_style_{slug}`, `char_style_{slug}` — style detail state
- `prefs_look_{slug}`, `preview_look_{slug}` — look detail state
---
## Running the App
### Directly (development)
```bash
cd /mnt/alexander/Projects/character-browser
source venv/bin/activate
python app.py
```
The app runs in debug mode on port 5000 by default. ComfyUI must be running at `http://127.0.0.1:8188`.
The DB is initialised and all sync functions are called inside `with app.app_context():` at the bottom of `app.py` before `app.run()`.
### Docker
```bash
docker compose up -d
```
The compose file (`docker-compose.yml`) runs two services:
- **`danbooru-mcp`** — built from `https://git.liveaodh.com/aodhan/danbooru-mcp.git`; the MCP tag-search container used by `call_llm()`.
- **`app`** — the Flask app, exposed on host port **5782** → container port 5000.
Key environment variables set by compose:
- `COMFYUI_URL=http://10.0.0.200:8188` — points at ComfyUI on the Docker host network.
- `SKIP_MCP_AUTOSTART=true` — disables the app's built-in danbooru-mcp launch logic (compose manages it).
Volumes mounted into the app container:
- `./data`, `./static/uploads`, `./instance`, `./flask_session` — persistent app data.
- `/Volumes/ImageModels:/ImageModels:ro` — model files for checkpoint/LoRA scanning (**requires Docker Desktop file sharing enabled for `/Volumes/ImageModels`**).
- `/var/run/docker.sock` — Docker socket so the app can exec danbooru-mcp tool containers.
---
## Common Pitfalls
- **SQLAlchemy JSON mutation**: After modifying a JSON column dict in place, always call `flag_modified(obj, "data")` or the change won't be detected.
- **Dual write**: Every edit route writes back to both the DB (`db.session.commit()`) and the JSON file on disk. Both must be kept in sync.
- **Slug generation**: `re.sub(r'[^a-zA-Z0-9_]', '', id)` — note this removes hyphens and dots, not just replaces them. Character IDs like `yuna_(ff10)` become slug `yunaffx10`. This is intentional.
- **Checkpoint slugs use underscore replacement**: `re.sub(r'[^a-zA-Z0-9_]', '_', ...)` (replaces with `_`, not removes) to preserve readability in paths.
- **LoRA chaining**: If a LoRA node has no LoRA (name is empty/None), the node is skipped and `model_source`/`clip_source` pass through unchanged. Do not set the node inputs for skipped nodes.
- **AJAX detection**: `request.headers.get('X-Requested-With') == 'XMLHttpRequest'` determines whether to return JSON or redirect.
- **Session must be marked modified for JSON responses**: After setting session values in AJAX-responding routes, set `session.modified = True`.
- **Detailer `prompt` is a list**: The `prompt` field in detailer JSON is stored as a list of strings (e.g. `["detailed skin", "pores"]`), not a plain string. When merging into `tags` for `build_prompt`, use `extend` for lists and `append` for strings — never append the list object itself or `", ".join()` will fail on the nested list item.
- **`_make_finalize` action semantics**: Pass `action=None` when the route should always update the DB cover (e.g. batch generate, checkpoint generate). Pass `action=request.form.get('action')` for routes that support both "preview" (no DB update) and "replace" (update DB). The factory skips the DB write when `action` is truthy and not `"replace"`.

29
Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
FROM python:3.12-slim
# Install system deps: git (for danbooru-mcp repo clone) + docker CLI
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
curl \
ca-certificates \
&& install -m 0755 -d /etc/apt/keyrings \
&& curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \
&& chmod a+r /etc/apt/keyrings/docker.asc \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
> /etc/apt/sources.list.d/docker.list \
&& apt-get update && apt-get install -y --no-install-recommends docker-ce-cli docker-compose-plugin \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Writable dirs that will typically be bind-mounted at runtime
RUN mkdir -p static/uploads instance flask_session data/characters data/clothing \
data/actions data/styles data/scenes data/detailers data/checkpoints data/looks
EXPOSE 5000
CMD ["python", "app.py"]

View File

@@ -39,6 +39,20 @@ A local web-based GUI for managing character profiles (JSON) and generating cons
## Setup & Installation
### Option A — Docker (recommended)
1. **Clone the repository.**
2. Edit `docker-compose.yml` if needed:
- Set `COMFYUI_URL` to your ComfyUI host/port.
- Adjust the `/Volumes/ImageModels` volume path to your model directory. If you're on Docker Desktop, add the path under **Settings → Resources → File Sharing** first.
3. **Start services:**
```bash
docker compose up -d
```
The app will be available at `http://localhost:5782`.
### Option B — Local (development)
1. **Clone the repository** to your local machine.
2. **Configure Paths**: Open `app.py` and update the following variables to match your system:
```python

3270
app.py

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/3P_SEX-000037.safetensors",
"lora_weight": 0.8,
"lora_triggers": "threesome, group_sex"
"lora_triggers": "threesome, group_sex",
"lora_weight_min": 0.8,
"lora_weight_max": 0.8
},
"tags": [
"threesome",
@@ -27,4 +29,4 @@
"groping",
"sweat"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/4P_sex.safetensors",
"lora_weight": 0.6,
"lora_triggers": "4P_sexV1"
"lora_triggers": "4P_sexV1",
"lora_weight_min": 0.6,
"lora_weight_max": 0.6
},
"tags": [
"4P_sexV1",
@@ -30,4 +32,4 @@
"hetero",
"sex"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/[Malebolgia] Oral Sex Tounge Afterimage Concept 2.0 Illustrious.safetensors",
"lora_weight": 1.0,
"lora_triggers": "[Malebolgia] Oral Sex Tounge Afterimage Concept 2.0 Illustrious"
"lora_triggers": "[Malebolgia] Oral Sex Tounge Afterimage Concept 2.0 Illustrious",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"oral",
@@ -29,4 +31,4 @@
"motion blur",
"surreal"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Actually_Reliable_Penis_Kissing_3_Variants_Illustrious.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Actually_Reliable_Penis_Kissing_3_Variants_Illustrious"
"lora_triggers": "Actually_Reliable_Penis_Kissing_3_Variants_Illustrious",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"penis kissing",
@@ -31,4 +33,4 @@
"tongue",
"close-up"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/after-sex-fellatio-illustriousxl-lora-nochekaiser_r1.safetensors",
"lora_weight": 1.0,
"lora_triggers": "after sex fellatio"
"lora_triggers": "after sex fellatio",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"after_sex",
@@ -34,4 +36,4 @@
"penis",
"cum"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/afterfellatio_ill.safetensors",
"lora_weight": 0.8,
"lora_triggers": "after fellatio, cum in mouth, closed mouth, cum string"
"lora_triggers": "after fellatio, cum in mouth, closed mouth, cum string",
"lora_weight_min": 0.8,
"lora_weight_max": 0.8
},
"tags": [
"after_fellatio",
@@ -30,4 +32,4 @@
"pov",
"handjob"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/afteroral.safetensors",
"lora_weight": 1.0,
"lora_triggers": "after oral, after deepthroat"
"lora_triggers": "after oral, after deepthroat",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"after_fellatio",
@@ -30,4 +32,4 @@
"penis_on_face",
"sweat"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/afterpaizuri.safetensors",
"lora_weight": 1.0,
"lora_triggers": "afterpaizuri"
"lora_triggers": "afterpaizuri",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"after paizuri",
@@ -32,4 +34,4 @@
"sweat",
"disheveled"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/AfterSexBreakV2.safetensors",
"lora_weight": 1.0,
"lora_triggers": "aftersexbreak, after sex, male sitting"
"lora_triggers": "aftersexbreak, after sex, male sitting",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"after_sex",
@@ -38,4 +40,4 @@
"bed_sheet",
"stained_sheets"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Against_glass_bs.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Against_glass_bs"
"lora_triggers": "Against_glass_bs",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"against glass",
@@ -30,4 +32,4 @@
"cheek press",
"distorted view"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/AgressiveChoking-000010.safetensors",
"lora_weight": 1.0,
"lora_triggers": "AgressiveChoking-000010"
"lora_triggers": "AgressiveChoking-000010",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"violence",
@@ -29,4 +31,4 @@
"combat",
"anger"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Ahegao_XL_v3_1278075.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Ahegao_XL_v3_1278075"
"lora_triggers": "Ahegao_XL_v3_1278075",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"ahegao",
@@ -34,4 +36,4 @@
"double peace sign",
"v-sign"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Amateur_POV_Filming.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Homemade_PornV1, recording, pov, prostitution"
"lora_triggers": "Homemade_PornV1, recording, pov, prostitution",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"recording",
@@ -30,4 +32,4 @@
"prostitution",
"indoors"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/arch-back-sex-v1.1-illustriousxl.safetensors",
"lora_weight": 1.0,
"lora_triggers": "kiss, arched_back, sex_from_behind"
"lora_triggers": "kiss, arched_back, sex_from_behind",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"hetero",
@@ -26,4 +28,4 @@
"nude",
"indoors"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/arm_grab_missionary_ill-10.safetensors",
"lora_weight": 1.0,
"lora_triggers": "arm_grab_missionary"
"lora_triggers": "arm_grab_missionary",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"missionary",
@@ -35,4 +37,4 @@
"breasts",
"nipples"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/BallsDeep-IL-V2.2-S.safetensors",
"lora_weight": 1.0,
"lora_triggers": "deep penetration"
"lora_triggers": "deep penetration",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"deep_penetration",
@@ -27,4 +29,4 @@
"vaginal",
"gaping"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/bathingtogether.safetensors",
"lora_weight": 1.0,
"lora_triggers": "bathing together"
"lora_triggers": "bathing together",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"bathing",
@@ -28,4 +30,4 @@
"steam",
"bare_shoulders"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/before_after_1230829.safetensors",
"lora_weight": 0.9,
"lora_triggers": "before_after"
"lora_triggers": "before_after",
"lora_weight_min": 0.9,
"lora_weight_max": 0.9
},
"tags": [
"before_and_after",
@@ -30,4 +32,4 @@
"upper_body",
"split_theme"
]
}
}

View File

@@ -20,10 +20,12 @@
"lora": {
"lora_name": "",
"lora_weight": 1.0,
"lora_triggers": ""
"lora_triggers": "",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"belly dancing",
"dance"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/BentBack.safetensors",
"lora_weight": 1.0,
"lora_triggers": "bentback, kneepits"
"lora_triggers": "bentback, kneepits",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"bent_over",
@@ -26,4 +28,4 @@
"twisted_torso",
"ass_focus"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/BlowjobComicPart2.safetensors",
"lora_weight": 1.0,
"lora_triggers": "bjmcut"
"lora_triggers": "bjmcut",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"3koma",
@@ -29,4 +31,4 @@
"empty_eyes",
"tongue_out"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/BodyBenGirl.safetensors",
"lora_weight": 1.0,
"lora_triggers": "bentstand-front, bentstand-behind"
"lora_triggers": "bentstand-front, bentstand-behind",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"suspended_congress",
@@ -27,4 +29,4 @@
"1boy",
"1girl"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/BodyBenGirlPart2.safetensors",
"lora_weight": 0.9,
"lora_triggers": "bentstand-behind, dangling legs, dangling arms, from_side, arms hanging down, torso_grab, suspended"
"lora_triggers": "bentstand-behind, dangling legs, dangling arms, from_side, arms hanging down, torso_grab, suspended",
"lora_weight_min": 0.9,
"lora_weight_max": 0.9
},
"tags": [
"torso_grab",
@@ -28,4 +30,4 @@
"embarrassed",
"sweat"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Bored_Retrain-000115_1336316.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Bored_Retrain-000115_1336316"
"lora_triggers": "Bored_Retrain-000115_1336316",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"boredom",
@@ -30,4 +32,4 @@
"tired",
"cheek resting on hand"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/breast_pressH.safetensors",
"lora_weight": 0.6,
"lora_triggers": "breast_pressH"
"lora_triggers": "breast_pressH",
"lora_weight_min": 0.6,
"lora_weight_max": 0.6
},
"tags": [
"height_difference",
@@ -30,4 +32,4 @@
"1boy",
"2girls"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/breast-smother-illustriousxl-lora-nochekaiser.safetensors",
"lora_weight": 1.0,
"lora_triggers": "breast-smother-illustriousxl-lora-nochekaiser"
"lora_triggers": "breast-smother-illustriousxl-lora-nochekaiser",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"breast smother",
@@ -33,4 +35,4 @@
"pov",
"large breasts"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/breast-sucking-fingering-illustriousxl-lora-nochekaiser.safetensors",
"lora_weight": 1.0,
"lora_triggers": "breast-sucking-fingering-illustriousxl-lora-nochekaiser"
"lora_triggers": "breast-sucking-fingering-illustriousxl-lora-nochekaiser",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"breast sucking",
@@ -34,4 +36,4 @@
"saliva",
"stimulation"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/BrokenGlass_illusXL_Incrs_v1.safetensors",
"lora_weight": 1.0,
"lora_triggers": "BrokenGlass_illusXL_Incrs_v1"
"lora_triggers": "BrokenGlass_illusXL_Incrs_v1",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"broken glass",
@@ -32,4 +34,4 @@
"cinematic",
"destruction"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Butt_smother_ag-000043.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Butt_smother_ag-000043"
"lora_triggers": "Butt_smother_ag-000043",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"facesitting",
@@ -32,4 +34,4 @@
"suffocation",
"submissive view"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/buttjob.safetensors",
"lora_weight": 1.0,
"lora_triggers": "buttjob"
"lora_triggers": "buttjob",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"buttjob",
@@ -32,4 +34,4 @@
"glutes",
"between buttocks"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/CarWashV2.safetensors",
"lora_weight": 0.8,
"lora_triggers": "w4sh1n, w4sh0ut"
"lora_triggers": "w4sh1n, w4sh0ut",
"lora_weight_min": 0.8,
"lora_weight_max": 0.8
},
"tags": [
"car",
@@ -33,4 +35,4 @@
"outdoors",
"car_interior"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cat_stretchILL.safetensors",
"lora_weight": 0.7,
"lora_triggers": "stretching, cat stretch, downward dog, trembling"
"lora_triggers": "stretching, cat stretch, downward dog, trembling",
"lora_weight_min": 0.7,
"lora_weight_max": 0.7
},
"tags": [
"cat_stretch",
@@ -31,4 +33,4 @@
"cat_ears",
"cat_tail"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Caught_Masturbating_ILLUSTRIOUS.safetensors",
"lora_weight": 0.75,
"lora_triggers": "caught, male pov, male masturbation, girl walking in door, standing in doorway"
"lora_triggers": "caught, male pov, male masturbation, girl walking in door, standing in doorway",
"lora_weight_min": 0.75,
"lora_weight_max": 0.75
},
"tags": [
"pov",
@@ -35,4 +37,4 @@
"wide_shot",
"indoors"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/charm_person_magic.safetensors",
"lora_weight": 0.7,
"lora_triggers": "charm_person_(magic), cham_aura"
"lora_triggers": "charm_person_(magic), cham_aura",
"lora_weight_min": 0.7,
"lora_weight_max": 0.7
},
"tags": [
"casting_spell",
@@ -30,4 +32,4 @@
"cowboy_shot",
"solo"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cheekbulge.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cheek bulge"
"lora_triggers": "cheek bulge",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cheek_bulge",
@@ -27,4 +29,4 @@
"penis",
"pov"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/chokehold.safetensors",
"lora_weight": 1.0,
"lora_triggers": "choke hold"
"lora_triggers": "choke hold",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"choke_hold",
@@ -32,4 +34,4 @@
"saliva",
"ohogao"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/CleavageTeaseDwnsty-000008.safetensors",
"lora_weight": 1.0,
"lora_triggers": "pulling down own clothes, teasing"
"lora_triggers": "pulling down own clothes, teasing",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"clothes_pull",
@@ -34,4 +36,4 @@
"blush",
"one_eye_closed"
]
}
}

View File

@@ -1,22 +1,24 @@
{
"action": {
"additional": "nsfw, semen, cum",
"arms": "",
"eyes": "looking_at_viewer, eyes_open",
"feet": "",
"full_body": "close-up, portrait",
"hands": "",
"head": "facial, open_mouth, tongue, saliva, blush",
"legs": "",
"pelvis": "",
"torso": ""
},
"action_id": "closeup_facial_illus",
"action_name": "Closeup Facial Illus",
"action": {
"full_body": "close-up, portrait",
"head": "facial, open_mouth, tongue, saliva, blush",
"eyes": "looking_at_viewer, eyes_open",
"arms": "out_of_frame",
"hands": "out_of_frame",
"torso": "out_of_frame",
"pelvis": "out_of_frame",
"legs": "out_of_frame",
"feet": "out_of_frame",
"additional": "nsfw, semen, cum"
},
"lora": {
"lora_name": "Illustrious/Poses/Closeup_Facial_iLLus.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Closeup Facial"
"lora_triggers": "Closeup Facial",
"lora_weight": 1,
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"facial",
@@ -28,4 +30,4 @@
"saliva",
"blush"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cof.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cof"
"lora_triggers": "cof",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"standing force",
@@ -30,4 +32,4 @@
"legs wrapped",
"straddling"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cooperative_grinding.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cooperative_grinding"
"lora_triggers": "cooperative_grinding",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"standing sex",
@@ -30,4 +32,4 @@
"grinding",
"lift and carry"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cooperativepaizuri.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cooperative paizuri"
"lora_triggers": "cooperative paizuri",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cooperative_paizuri",
@@ -30,4 +32,4 @@
"from_side",
"large_breasts"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/covering privates_illustrious_V1.0.safetensors",
"lora_weight": 1.0,
"lora_triggers": "covering privates, covering crotch, covering breasts"
"lora_triggers": "covering privates, covering crotch, covering breasts",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"covering_privates",
@@ -27,4 +29,4 @@
"arm_across_chest",
"legs_together"
]
}
}

View File

@@ -16,9 +16,11 @@
"lora": {
"lora_name": "Illustrious/Poses/CoveringOwnMouth_Ill_V1.safetensors",
"lora_weight": 1.0,
"lora_triggers": "covering_own_mouth"
"lora_triggers": "covering_own_mouth",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"covering_own_mouth"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cowgirl-position-breast-press-illustriousxl-lora-nochekaiser.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cowgirl-position-breast-press-illustriousxl-lora-nochekaiser"
"lora_triggers": "cowgirl-position-breast-press-illustriousxl-lora-nochekaiser",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cowgirl position",
@@ -32,4 +34,4 @@
"breast deformation",
"squish"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Cuckold NTR-IL_NAI_PY.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Cuckold NTR-IL_NAI_PY"
"lora_triggers": "Cuckold NTR-IL_NAI_PY",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"ntr",
@@ -30,4 +32,4 @@
"doggy style",
"looking back"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cum_bathIllustrious.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cum_bathIllustrious"
"lora_triggers": "cum_bathIllustrious",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cum_bath",
@@ -31,4 +33,4 @@
"bukkake",
"messy"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cum_in_cleavage_illustrious.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cum_in_cleavage, holding own breasts"
"lora_triggers": "cum_in_cleavage, holding own breasts",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cum_on_breasts",
@@ -30,4 +32,4 @@
"black_hair",
"indoors"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Cum_inside_slime_v0.2.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Cum_inside_slime_v0.2"
"lora_triggers": "Cum_inside_slime_v0.2",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"slime girl",
@@ -32,4 +34,4 @@
"stomach fill",
"viscous"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cum_shot.safetensors",
"lora_weight": 0.8,
"lora_triggers": "cum, facial, ejaculation"
"lora_triggers": "cum, facial, ejaculation",
"lora_weight_min": 0.8,
"lora_weight_max": 0.8
},
"tags": [
"cum",
@@ -40,4 +42,4 @@
"blush",
"ahegao"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Cum_Swap.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Cum_Swap"
"lora_triggers": "Cum_Swap",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cum swap",
@@ -34,4 +36,4 @@
"sharing fluids",
"intimacy"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cumblastfacial.safetensors",
"lora_weight": 1.0,
"lora_triggers": "xcbfacialx"
"lora_triggers": "xcbfacialx",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"facial",
@@ -29,4 +31,4 @@
"cum_in_eye",
"cum_on_hair"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cuminhands.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cum on hands, cupping hands, excessive cum, cum on face, cum in mouth, cum string"
"lora_triggers": "cum on hands, cupping hands, excessive cum, cum on face, cum in mouth, cum string",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cum_on_hands",
@@ -28,4 +30,4 @@
"after_fellatio",
"looking_at_hands"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cumshot.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cumshot"
"lora_triggers": "cumshot",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cum",
@@ -31,4 +33,4 @@
"seminal fluid",
"detailed liquid"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cumtube-000035.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cumtube-000035"
"lora_triggers": "cumtube-000035",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cumtube",
@@ -33,4 +35,4 @@
"open mouth",
"wet skin"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/cunnilingus-on-back-illustriousxl-lora-nochekaiser.safetensors",
"lora_weight": 1.0,
"lora_triggers": "cunnilingus on back"
"lora_triggers": "cunnilingus on back",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cunnilingus",
@@ -34,4 +36,4 @@
"on_bed",
"from_side"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/danglinglegs.safetensors",
"lora_weight": 1.0,
"lora_triggers": "dangling legs, lifted by penis, suspended on penis"
"lora_triggers": "dangling legs, lifted by penis, suspended on penis",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"suspended_congress",
@@ -28,4 +30,4 @@
"barefoot",
"clenched_teeth"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Deep_Kiss-000007.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Deep_Kiss-000007"
"lora_triggers": "Deep_Kiss-000007",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"deep kiss",
@@ -38,4 +40,4 @@
"eyes closed",
"duo"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Deepthroat_PonytailHandle_Anime_IL_V1.safetensors",
"lora_weight": 1.0,
"lora_triggers": "deepthroat_ponytailhandle, grabbing another's hair, ponytail"
"lora_triggers": "deepthroat_ponytailhandle, grabbing another's hair, ponytail",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"irrumatio",
@@ -30,4 +32,4 @@
"penis",
"forced"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Defeat NTR-IL_NAI_PY.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Defeat NTR-IL_NAI_PY"
"lora_triggers": "Defeat NTR-IL_NAI_PY",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"defeat",
@@ -34,4 +36,4 @@
"looking down",
"tears"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Defeat suspension-IL_NAI_PY.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Defeat suspension-IL_NAI_PY"
"lora_triggers": "Defeat suspension-IL_NAI_PY",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"suspension",
@@ -33,4 +35,4 @@
"bdsm",
"bondage"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Defeatspitroast_Illustrious.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Defeatspitroast_Illustrious"
"lora_triggers": "Defeatspitroast_Illustrious",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"doggystyle",
@@ -36,4 +38,4 @@
"",
"1girl"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Disinterested_Sex___Bored_Female.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Disinterested_Sex___Bored_Female"
"lora_triggers": "Disinterested_Sex___Bored_Female",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"bored",
@@ -33,4 +35,4 @@
"indifferent",
"expressionless"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/display_case_bdsm_illus.safetensors",
"lora_weight": 1.0,
"lora_triggers": "display_case_bdsm_illus"
"lora_triggers": "display_case_bdsm_illus",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"glass box",
@@ -30,4 +32,4 @@
"through glass",
"human exhibit"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/display_case_illustr.safetensors",
"lora_weight": 1.0,
"lora_triggers": "display_case_illustr"
"lora_triggers": "display_case_illustr",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"display case",
@@ -33,4 +35,4 @@
"toy",
"transparent"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/DoggyDoubleFingering.safetensors",
"lora_weight": 1.0,
"lora_triggers": "doggydoublefingerfront, from front, 3girls, multiple girls, fingering, sex from behind, doggystyle"
"lora_triggers": "doggydoublefingerfront, from front, 3girls, multiple girls, fingering, sex from behind, doggystyle",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"3girls",
@@ -30,4 +32,4 @@
"harem",
"male_fingering"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Dunking_face_in_a_bowl_of_cum_r1.safetensors",
"lora_weight": 1.0,
"lora_triggers": "face in cum bowl, cum in bowl, cum bubble, excessive cum"
"lora_triggers": "face in cum bowl, cum in bowl, cum bubble, excessive cum",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"1girl",
@@ -33,4 +35,4 @@
"bowl",
"cum"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/ekiben_ill-10.safetensors",
"lora_weight": 1.0,
"lora_triggers": "ekiben_ill-10"
"lora_triggers": "ekiben_ill-10",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"ekiben",
@@ -32,4 +34,4 @@
"duo",
"sex"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Elbow_Squeeze__Concept_Lora-000008.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Elbow_Squeeze__Concept_Lora-000008"
"lora_triggers": "Elbow_Squeeze__Concept_Lora-000008",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"elbow squeeze",
@@ -29,4 +31,4 @@
"squeezing",
"tight clothes"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/extreme-sex-v1.0-illustriousxl.safetensors",
"lora_weight": 1.0,
"lora_triggers": "extreme sex"
"lora_triggers": "extreme sex",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"rolling_eyes",
@@ -31,4 +33,4 @@
"mind_break",
"sex"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/face_grab_illustrious.safetensors",
"lora_weight": 0.5,
"lora_triggers": "fcgrb, face grab, grabbing another's face, pov, pov hand, open mouth, tongue out"
"lora_triggers": "fcgrb, face grab, grabbing another's face, pov, pov hand, open mouth, tongue out",
"lora_weight_min": 0.5,
"lora_weight_max": 0.5
},
"tags": [
"grabbing_another's_face",
@@ -30,4 +32,4 @@
"streaming_tears",
"cheek_pinching"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/facesit-08.safetensors",
"lora_weight": 0.8,
"lora_triggers": "2girls, female pov, close-up, looking at viewer, sitting on face, oral, cunnilingus, spread legs, pussy juice, clitoris"
"lora_triggers": "2girls, female pov, close-up, looking at viewer, sitting on face, oral, cunnilingus, spread legs, pussy juice, clitoris",
"lora_weight_min": 0.8,
"lora_weight_max": 0.8
},
"tags": [
"2girls",
@@ -34,4 +36,4 @@
"head_grab",
"looking_down"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/facial_bukkake.safetensors",
"lora_weight": 1.0,
"lora_triggers": "facial_bukkake"
"lora_triggers": "facial_bukkake",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"bukkake",
@@ -34,4 +36,4 @@
"splatter",
"after sex"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/fellatio-from-below-illustriousxl-lora-nochekaiser.safetensors",
"lora_weight": 1.0,
"lora_triggers": "fellatio from below, fellatio, from below, squatting, hetero, penis, testicles, completely nude, oral"
"lora_triggers": "fellatio from below, fellatio, from below, squatting, hetero, penis, testicles, completely nude, oral",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"fellatio",
@@ -32,4 +34,4 @@
"sweat",
"pussy"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/fellatio-on-couch-illustriousxl-lora-nochekaiser.safetensors",
"lora_weight": 1.0,
"lora_triggers": "fellatio on couch, hetero, penis, oral, sitting, fellatio, testicles, blush, couch, sweat, breast press, nipples, completely nude, uncensored"
"lora_triggers": "fellatio on couch, hetero, penis, oral, sitting, fellatio, testicles, blush, couch, sweat, breast press, nipples, completely nude, uncensored",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"fellatio",
@@ -34,4 +36,4 @@
"uncensored",
"couch"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/femdom_face_between_breasts.safetensors",
"lora_weight": 1.0,
"lora_triggers": "femdom_face_between_breasts"
"lora_triggers": "femdom_face_between_breasts",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"breast smother",
@@ -31,4 +33,4 @@
"big breasts",
"cleavage"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Femdom_Held_Down_Illust.safetensors",
"lora_weight": 0.8,
"lora_triggers": "fdom_held"
"lora_triggers": "fdom_held",
"lora_weight_min": 0.8,
"lora_weight_max": 0.8
},
"tags": [
"femdom",
@@ -29,4 +31,4 @@
"pinned",
"struggling"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/fertilization-illustriousxl-lora-nochekaiser.safetensors",
"lora_weight": 1.0,
"lora_triggers": "fertilization, ovum, impregnation, sperm cell, cross-section, cum in pussy, internal cumshot, uterus, cum, sex, vaginal, ovaries, penis, hetero, ejaculation"
"lora_triggers": "fertilization, ovum, impregnation, sperm cell, cross-section, cum in pussy, internal cumshot, uterus, cum, sex, vaginal, ovaries, penis, hetero, ejaculation",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"fertilization",
@@ -32,4 +34,4 @@
"ahegao",
"on_bed"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/FFF_imminent_masturbation.safetensors",
"lora_weight": 1.0,
"lora_triggers": "FFF_grabbing_own_crotch, trembling, sweat, breath, imminent_masturbation"
"lora_triggers": "FFF_grabbing_own_crotch, trembling, sweat, breath, imminent_masturbation",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"hand_on_own_crotch",
@@ -30,4 +32,4 @@
"aroused",
"rubbing_crotch"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/FFM3SOME-footjob-EFEME3ftfe-IL_1475115.safetensors",
"lora_weight": 1.0,
"lora_triggers": "FFM3SOME-footjob-EFEME3ftfe-IL_1475115"
"lora_triggers": "FFM3SOME-footjob-EFEME3ftfe-IL_1475115",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"footjob",
@@ -34,4 +36,4 @@
"penis",
"sexual"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/FFM_threesome_-_Kiss_and_Fellatio_Illustrious.safetensors",
"lora_weight": 1.0,
"lora_triggers": "ffm_threesome_kiss_and_fellatio"
"lora_triggers": "ffm_threesome_kiss_and_fellatio",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"2girls",
@@ -35,4 +37,4 @@
"saliva",
"sandwich_position"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/FFM_Threesome_doggy_style_front_view_Illustrious.safetensors",
"lora_weight": 1.0,
"lora_triggers": "FFM_Threesome_doggy_style_front_view_Illustrious"
"lora_triggers": "FFM_Threesome_doggy_style_front_view_Illustrious",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"threesome",
@@ -34,4 +36,4 @@
"blush",
"sweat"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/FFM_threesome_girl_sandwichdouble_dip_Illustrious.safetensors",
"lora_weight": 1.0,
"lora_triggers": "ffm_threesome_double_dip"
"lora_triggers": "ffm_threesome_double_dip",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"ffm_threesome",
@@ -37,4 +39,4 @@
"bed_sheet",
"messy_bed"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/FFM_threesome_one_girl_on_top_and_BJ.safetensors",
"lora_weight": 1.0,
"lora_triggers": "ffm_threesome_straddling_fellatio"
"lora_triggers": "ffm_threesome_straddling_fellatio",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"ffm_threesome",
@@ -35,4 +37,4 @@
"erotic",
"cum"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/ffmNursingHandjob_ill_v3.safetensors",
"lora_weight": 1.0,
"lora_triggers": "ffmNursingHandjob_ill_v3"
"lora_triggers": "ffmNursingHandjob_ill_v3",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"threesome",
@@ -36,4 +38,4 @@
"big_breasts",
"kneeling"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/finish_blow_ill_v0.90-000004.safetensors",
"lora_weight": 1.0,
"lora_triggers": "finish_blow_ill_v0.90-000004"
"lora_triggers": "finish_blow_ill_v0.90-000004",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"action shot",
@@ -30,4 +32,4 @@
"intense",
"cinematic composition"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/fixed_perspective_v3_1558768.safetensors",
"lora_weight": 1.0,
"lora_triggers": "fixed_perspective_v3_1558768"
"lora_triggers": "fixed_perspective_v3_1558768",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"foreshortening",
@@ -31,4 +33,4 @@
"portrait",
"depth of field"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/fixed_point_v2.safetensors",
"lora_weight": 0.8,
"lora_triggers": "fxdpt, full room view"
"lora_triggers": "fxdpt, full room view",
"lora_weight_min": 0.8,
"lora_weight_max": 0.8
},
"tags": [
"kneeling",
@@ -28,4 +30,4 @@
"from_above",
"perspective"
]
}
}

View File

@@ -16,7 +16,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Flaccid_After_Cum_Illustrious-000009.safetensors",
"lora_weight": 1.0,
"lora_triggers": "flaccid after cum"
"lora_triggers": "flaccid after cum",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"after_sex",
@@ -29,4 +31,4 @@
"cum_in_mouth",
"after_fellatio"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Fleshlight_Position_Doggystyle_Dangling_Legs_Sex_From_Behind_Hanging_Legs_PonyILSDSDXL.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Fleshlight_Position_Doggystyle_Dangling_Legs_Sex_From_Behind_Hanging_Legs_PonyILSDSDXL"
"lora_triggers": "Fleshlight_Position_Doggystyle_Dangling_Legs_Sex_From_Behind_Hanging_Legs_PonyILSDSDXL",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"doggystyle",
@@ -34,4 +36,4 @@
"feet off ground",
"sex act"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Folded XL illustrious V1.0.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Folded XL illustrious V1.0"
"lora_triggers": "Folded XL illustrious V1.0",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"crossed arms",
@@ -31,4 +33,4 @@
"skeptical",
"upper body"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/Forced_cunnilingus.safetensors",
"lora_weight": 1.0,
"lora_triggers": "Forced_cunnilingus"
"lora_triggers": "Forced_cunnilingus",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"cunnilingus",
@@ -35,4 +37,4 @@
"vaginal",
"sex act"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/foreskin_fellatio-ILXL.safetensors",
"lora_weight": 1.0,
"lora_triggers": "foreskin_fellatio-ILXL"
"lora_triggers": "foreskin_fellatio-ILXL",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"nsfw",
@@ -33,4 +35,4 @@
"male anatomy",
"sexual act"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/foreskinplay_r1.safetensors",
"lora_weight": 1.0,
"lora_triggers": "foreskinplay_r1"
"lora_triggers": "foreskinplay_r1",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"nsfw",
@@ -32,4 +34,4 @@
"penis close-up",
"glans"
]
}
}

View File

@@ -20,7 +20,9 @@
"lora": {
"lora_name": "Illustrious/Poses/FrenchKissV1IL-000010.safetensors",
"lora_weight": 1.0,
"lora_triggers": "FrenchKissV1IL-000010"
"lora_triggers": "FrenchKissV1IL-000010",
"lora_weight_min": 1.0,
"lora_weight_max": 1.0
},
"tags": [
"french kiss",
@@ -34,4 +36,4 @@
"deep kiss",
"profile view"
]
}
}

Some files were not shown because too many files have changed in this diff Show More