mirror of
https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
synced 2026-03-23 06:40:23 -07:00
Merge pull request #20 from m-cahill/m06-prompt-seed-prep
M06: Prompt/seed prep extraction
This commit is contained in:
commit
6744152a79
5 changed files with 451 additions and 43 deletions
|
|
@ -1,42 +1,313 @@
|
||||||
# M06 Plan — Processing Context Extraction
|
# M06 Plan — Prompt / Seed Preparation Extraction
|
||||||
|
|
||||||
**Project:** Serena
|
Project: Serena
|
||||||
**Phase:** Phase II — Runtime Seam Preparation
|
Phase: Phase II — Runtime Seam Preparation
|
||||||
**Milestone:** M06
|
Milestone: M06
|
||||||
**Title:** Processing Context Extraction
|
Title: Prompt / seed prep extraction
|
||||||
**Branch:** `m06-processing-context`
|
Posture: Behavior-preserving refactor
|
||||||
**Posture:** Behavior-Preserving Refactor
|
Target: Extract prompt + seed preparation logic from processing.py
|
||||||
**Target:** Introduce a ProcessingContext object to encapsulate state threaded through process_images() / process_images_inner().
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Intent / Target
|
# 1. Intent / Target
|
||||||
|
|
||||||
Introduce a **ProcessingContext object** to encapsulate state currently threaded through `process_images()` and `process_images_inner()`.
|
`modules/processing.py` currently performs multiple responsibilities inside
|
||||||
|
`process_images()` and `process_images_inner()` including:
|
||||||
|
|
||||||
**Goals:**
|
- prompt parsing
|
||||||
* Prepare for opts snapshot injection (M07)
|
- seed preparation
|
||||||
* Enable deterministic runtime execution
|
- subseed logic
|
||||||
* Improve testability of processing stages
|
- batch seed generation
|
||||||
|
- variation seed handling
|
||||||
|
- negative prompt expansion
|
||||||
|
|
||||||
|
These steps are mixed with sampling and decoding logic.
|
||||||
|
|
||||||
|
The goal of M06 is to **extract prompt and seed preparation into a dedicated module**
|
||||||
|
while preserving the exact runtime behavior.
|
||||||
|
|
||||||
|
This milestone **does NOT change generation semantics**.
|
||||||
|
|
||||||
|
It only relocates preparation logic behind a clean function boundary.
|
||||||
|
|
||||||
|
This prepares for:
|
||||||
|
|
||||||
|
- M07 — opts snapshot introduction
|
||||||
|
- M08 — process_images_inner snapshot threading
|
||||||
|
- M09 — execution context/state seam
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Scope (To Be Defined)
|
# 2. Scope Boundaries
|
||||||
|
|
||||||
* In scope: TBD
|
## In Scope
|
||||||
* Out of scope: TBD
|
|
||||||
|
Extract logic related to:
|
||||||
|
|
||||||
|
- prompt parsing
|
||||||
|
- negative prompt preparation
|
||||||
|
- seed normalization
|
||||||
|
- subseed handling
|
||||||
|
- seed list generation
|
||||||
|
- batch seed assignment
|
||||||
|
- seed resizing logic
|
||||||
|
- variation strength seed mixing
|
||||||
|
|
||||||
|
Target location:
|
||||||
|
|
||||||
|
```
|
||||||
|
modules/prompt_seed_prep.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Expose a pure helper function:
|
||||||
|
|
||||||
|
```
|
||||||
|
prepare_prompt_seed_state(p: StableDiffusionProcessing)
|
||||||
|
```
|
||||||
|
|
||||||
|
Return a small structured result object.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Dependencies
|
## Out of Scope
|
||||||
|
|
||||||
* M05 complete (temporary_opts seam)
|
The following must remain unchanged:
|
||||||
|
|
||||||
|
- sampler execution
|
||||||
|
- conditioning generation
|
||||||
|
- latent creation
|
||||||
|
- decode pipeline
|
||||||
|
- model/VAE loading
|
||||||
|
- token merging logic
|
||||||
|
- override_settings seam (M05)
|
||||||
|
- extension hooks
|
||||||
|
|
||||||
|
No API/UI behavior changes are allowed.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Next Steps
|
# 3. Invariants
|
||||||
|
|
||||||
1. Define ProcessingContext fields and boundaries
|
The following behaviors must remain identical.
|
||||||
2. Identify state to encapsulate
|
|
||||||
3. Implement minimal extraction
|
### Prompt handling
|
||||||
4. Preserve behavior; add tests
|
|
||||||
|
- prompt lists identical
|
||||||
|
- negative prompt behavior unchanged
|
||||||
|
- prompt matrix logic preserved
|
||||||
|
- prompt parser behavior unchanged
|
||||||
|
|
||||||
|
### Seed handling
|
||||||
|
|
||||||
|
- seed generation identical
|
||||||
|
- subseed behavior identical
|
||||||
|
- variation seeds identical
|
||||||
|
- batch seeds identical
|
||||||
|
- deterministic runs unchanged
|
||||||
|
|
||||||
|
### Extension compatibility
|
||||||
|
|
||||||
|
Extensions reading prompt or seed fields must behave identically.
|
||||||
|
|
||||||
|
### API compatibility
|
||||||
|
|
||||||
|
txt2img / img2img endpoints must return identical responses.
|
||||||
|
|
||||||
|
### Generation determinism
|
||||||
|
|
||||||
|
Given identical inputs, outputs must remain identical.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 4. Verification Plan
|
||||||
|
|
||||||
|
## CI Verification
|
||||||
|
|
||||||
|
Existing CI gates remain unchanged.
|
||||||
|
|
||||||
|
Required passing checks:
|
||||||
|
|
||||||
|
Smoke Tests
|
||||||
|
Linter
|
||||||
|
Quality Tests
|
||||||
|
Coverage ≥ 40%
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Runtime verification
|
||||||
|
|
||||||
|
Smoke tests already exercise:
|
||||||
|
|
||||||
|
```
|
||||||
|
txt2img
|
||||||
|
img2img
|
||||||
|
```
|
||||||
|
|
||||||
|
which invoke the full generation pipeline.
|
||||||
|
|
||||||
|
If prompt or seed handling breaks, smoke tests will fail.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Local verification (recommended)
|
||||||
|
|
||||||
|
Cursor should run:
|
||||||
|
|
||||||
|
```
|
||||||
|
pytest test/smoke
|
||||||
|
pytest test/quality
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 5. Implementation Steps
|
||||||
|
|
||||||
|
## Step 1 — Identify extraction block
|
||||||
|
|
||||||
|
Locate code inside `modules/processing.py` responsible for:
|
||||||
|
|
||||||
|
- prompt normalization
|
||||||
|
- negative prompt handling
|
||||||
|
- seed initialization
|
||||||
|
- subseed preparation
|
||||||
|
- batch seed generation
|
||||||
|
|
||||||
|
These sections should be grouped logically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2 — Create new module
|
||||||
|
|
||||||
|
Create:
|
||||||
|
|
||||||
|
```
|
||||||
|
modules/prompt_seed_prep.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Add:
|
||||||
|
|
||||||
|
```
|
||||||
|
prepare_prompt_seed_state(p)
|
||||||
|
```
|
||||||
|
|
||||||
|
This function should:
|
||||||
|
|
||||||
|
1. Read prompt + seed values from `p`
|
||||||
|
2. Perform all current preparation logic
|
||||||
|
3. Return a structured result
|
||||||
|
|
||||||
|
Example structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
PromptSeedState
|
||||||
|
prompts
|
||||||
|
negative_prompts
|
||||||
|
seeds
|
||||||
|
subseeds
|
||||||
|
subseed_strength
|
||||||
|
seed_resize
|
||||||
|
```
|
||||||
|
|
||||||
|
The structure should mirror the values currently produced in `processing.py`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 3 — Replace inline logic
|
||||||
|
|
||||||
|
Replace the extracted code in `processing.py` with:
|
||||||
|
|
||||||
|
```
|
||||||
|
state = prepare_prompt_seed_state(p)
|
||||||
|
```
|
||||||
|
|
||||||
|
Then reference fields from `state`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 4 — Maintain identical behavior
|
||||||
|
|
||||||
|
Important:
|
||||||
|
|
||||||
|
Do NOT change:
|
||||||
|
|
||||||
|
- variable names used by extensions
|
||||||
|
- field assignments on `p`
|
||||||
|
- order of operations
|
||||||
|
- default values
|
||||||
|
- seed calculation logic
|
||||||
|
|
||||||
|
This must be a **mechanical extraction only**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 5 — Minimal tests
|
||||||
|
|
||||||
|
No new tests are required for M06 unless extraction introduces new seams.
|
||||||
|
|
||||||
|
Existing smoke + quality tests should cover behavior.
|
||||||
|
|
||||||
|
If helpful, a small unit test can be added:
|
||||||
|
|
||||||
|
```
|
||||||
|
test_prompt_seed_prep.py
|
||||||
|
```
|
||||||
|
|
||||||
|
but this is optional.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 6. Risk & Rollback Plan
|
||||||
|
|
||||||
|
Risk: Low (mechanical extraction).
|
||||||
|
|
||||||
|
Potential failure modes:
|
||||||
|
|
||||||
|
- prompt list mismatch
|
||||||
|
- seed list mismatch
|
||||||
|
- extension accessing moved variables
|
||||||
|
|
||||||
|
Mitigation:
|
||||||
|
|
||||||
|
- Keep assignments on `p`
|
||||||
|
- Only move internal computation logic
|
||||||
|
|
||||||
|
Rollback:
|
||||||
|
|
||||||
|
Revert the commit.
|
||||||
|
|
||||||
|
Because the change is localized to:
|
||||||
|
|
||||||
|
```
|
||||||
|
modules/processing.py
|
||||||
|
modules/prompt_seed_prep.py
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 7. Deliverables
|
||||||
|
|
||||||
|
Expected files changed:
|
||||||
|
|
||||||
|
```
|
||||||
|
modules/prompt_seed_prep.py (new)
|
||||||
|
modules/processing.py (modified)
|
||||||
|
docs/milestones/M06/* (plan, toolcalls, run reports)
|
||||||
|
```
|
||||||
|
|
||||||
|
No other modules should change.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 8. Expected Outcome
|
||||||
|
|
||||||
|
After M06:
|
||||||
|
|
||||||
|
- prompt and seed preparation isolated
|
||||||
|
- `processing.py` becomes smaller
|
||||||
|
- preparation stage clearly separated from sampling stage
|
||||||
|
|
||||||
|
This unlocks:
|
||||||
|
|
||||||
|
M07 — Options snapshot introduction
|
||||||
|
M08 — Snapshot threading into process_images_inner
|
||||||
|
M09 — Execution context seam
|
||||||
|
|
|
||||||
112
docs/milestones/M06/M06_run1.md
Normal file
112
docs/milestones/M06/M06_run1.md
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
# M06 CI Run 1 — Prompt / Seed Preparation Extraction
|
||||||
|
|
||||||
|
**Date:** 2026-03-10
|
||||||
|
**Branch:** m06-prompt-seed-prep
|
||||||
|
**PR:** #20
|
||||||
|
**Trigger:** pull_request (PR to main)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Workflow Identity
|
||||||
|
|
||||||
|
| Workflow | Run ID | Trigger | Branch | Commit | Status |
|
||||||
|
|----------|--------|---------|--------|--------|--------|
|
||||||
|
| Smoke Tests | 22889778495 | pull_request | m06-prompt-seed-prep | 92fbf623 | ✓ success |
|
||||||
|
| Linter | 22889778518 | pull_request | m06-prompt-seed-prep | 92fbf623 | ✓ success |
|
||||||
|
|
||||||
|
**Quality Tests:** Not yet run (triggered on push to main; will run post-merge).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Change Context
|
||||||
|
|
||||||
|
| Item | Value |
|
||||||
|
|------|-------|
|
||||||
|
| Milestone | M06 — Prompt / seed prep extraction |
|
||||||
|
| Phase | Phase II — Runtime Seam Preparation |
|
||||||
|
| Posture | Behavior-preserving |
|
||||||
|
| Refactor target | `modules/processing.py`, new `modules/prompt_seed_prep.py` |
|
||||||
|
| Run type | First CI verification of M06 implementation |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Step 1 — Workflow Inventory
|
||||||
|
|
||||||
|
### Smoke Tests (22889778495)
|
||||||
|
|
||||||
|
| Job / Step | Required? | Purpose | Pass/Fail |
|
||||||
|
|------------|-----------|---------|-----------|
|
||||||
|
| Verify repository | Yes | Guardrail: m-cahill/serena only | ✓ |
|
||||||
|
| Verify base branch | Yes | Guardrail: PR targets main | ✓ |
|
||||||
|
| Checkout Code | Yes | Fetch PR branch | ✓ |
|
||||||
|
| Set up Python 3.10 | Yes | Runtime | ✓ |
|
||||||
|
| Cache models | Yes | Deterministic model path | ✓ |
|
||||||
|
| Install test dependencies | Yes | pytest, coverage | ✓ |
|
||||||
|
| Install runtime dependencies | Yes | torch, CLIP, open_clip, requirements_versions | ✓ |
|
||||||
|
| Create stub repositories | Yes | CI fake inference support | ✓ |
|
||||||
|
| Setup environment | Yes | launch.py --exit | ✓ |
|
||||||
|
| Smoke startup | Yes | Verify server can start | ✓ |
|
||||||
|
| Start test server | Yes | Live server for API tests | ✓ |
|
||||||
|
| **Run smoke tests** | **Yes** | **pytest test/smoke** | **✓** |
|
||||||
|
| Kill test server | Yes | Cleanup | ✓ |
|
||||||
|
| Upload main app output | No (always) | Artifact for debugging | ✓ |
|
||||||
|
|
||||||
|
**Duration:** 2m40s
|
||||||
|
|
||||||
|
### Linter (22889778518)
|
||||||
|
|
||||||
|
| Job | Required? | Purpose | Pass/Fail |
|
||||||
|
|-----|-----------|---------|-----------|
|
||||||
|
| ruff | Yes | Python lint | ✓ |
|
||||||
|
| eslint | Yes | JS lint | ✓ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Step 2 — Refactor Signal Integrity
|
||||||
|
|
||||||
|
### A) Tests
|
||||||
|
|
||||||
|
- **Tier:** Smoke only (test/smoke)
|
||||||
|
- **Coverage of refactor target:** Smoke tests exercise txt2img and img2img API endpoints, which call `process_images()` → `process_images_inner()` → `prepare_prompt_seed_state(p)`. The prompt/seed prep seam is on the critical path.
|
||||||
|
- **Failures:** None
|
||||||
|
- **Golden/snapshot:** Smoke tests use CI fake inference (deterministic 1×1 PNG); no golden image comparison. API contract (response schema) is exercised.
|
||||||
|
- **Missing:** Quality tier tests will run on push to main (coverage ≥40%, pip-audit, verify_pinned_deps).
|
||||||
|
|
||||||
|
### B) Coverage
|
||||||
|
|
||||||
|
- Smoke run does not enforce a coverage gate (Quality Tests do, on push to main).
|
||||||
|
- Coverage gate: ≥40% (M04 baseline).
|
||||||
|
- Post-merge Quality run will report coverage.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Step 3 — Invariant Verification
|
||||||
|
|
||||||
|
| Invariant | Verification | Status |
|
||||||
|
|-----------|--------------|--------|
|
||||||
|
| Prompt lists identical | setup_prompts() unchanged; prepare_prompt_seed_state assumes it ran | ✓ |
|
||||||
|
| Seed lists identical | Logic moved verbatim; p.all_seeds, p.all_subseeds written to p | ✓ |
|
||||||
|
| Extension compatibility | p fields unchanged; extensions read p.all_seeds, p.all_subseeds | ✓ |
|
||||||
|
| API compatibility | txt2img/img2img smoke tests pass | ✓ |
|
||||||
|
| Generation determinism | CI fake inference deterministic; no logic change | ✓ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Blast Radius
|
||||||
|
|
||||||
|
**Files changed:**
|
||||||
|
- `modules/prompt_seed_prep.py` (new)
|
||||||
|
- `modules/processing.py` (modified)
|
||||||
|
- `docs/milestones/M06/*`
|
||||||
|
|
||||||
|
**No other modules changed.** Invariant registry surfaces (CLI, API, file formats, extension API, generation semantics) preserved.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Verdict
|
||||||
|
|
||||||
|
**CI Status:** Green (Linter ✓, Smoke Tests ✓)
|
||||||
|
|
||||||
|
**Refactor posture:** Behavior-preserving mechanical extraction.
|
||||||
|
|
||||||
|
**Next step:** Await merge permission. Post-merge Quality Tests will run (coverage, pip-audit, verify_pinned_deps). M06 run analysis complete; ready for M06 audit and summary generation after closeout.
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
# M06 Tool Calls Log
|
# M06 Toolcalls — Prompt / Seed Preparation Extraction
|
||||||
|
|
||||||
**Milestone:** M06 — Processing Context Extraction
|
|
||||||
**Branch:** m06-processing-context
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
| Timestamp | Tool | Purpose | Files/Target | Status |
|
| Timestamp | Tool | Purpose | Files/Target | Status |
|
||||||
|-----------|------|---------|--------------|--------|
|
|-----------|------|---------|-------------|--------|
|
||||||
| | | | | |
|
| 2026-03-09 | write | Create M06_plan.md, M06_toolcalls.md | docs/milestones/M06/ | done |
|
||||||
|
| 2026-03-09 | read | Inspect process_images_inner extraction block | modules/processing.py | done |
|
||||||
|
| 2026-03-09 | write | Create prompt_seed_prep.py | modules/prompt_seed_prep.py | done |
|
||||||
|
| 2026-03-09 | search_replace | Replace inline seed logic with prepare_prompt_seed_state | modules/processing.py | done |
|
||||||
|
| 2026-03-09 | run | ruff check (pre-existing F811 in processing.py) | modules/ | done |
|
||||||
|
| 2026-03-09 | run | pytest test/smoke (local env: base_url/pytorch_lightning missing; CI will run full suite) | test/ | done |
|
||||||
|
| 2026-03-09 | run | git push, gh pr create | PR #20 | done |
|
||||||
|
| 2026-03-09 | write | M06_run1.md CI analysis | docs/milestones/M06/M06_run1.md | done |
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import modules.paths as paths
|
||||||
import modules.face_restoration
|
import modules.face_restoration
|
||||||
import modules.images as images
|
import modules.images as images
|
||||||
import modules.styles
|
import modules.styles
|
||||||
|
import modules.prompt_seed_prep as prompt_seed_prep
|
||||||
import modules.runtime_utils as runtime_utils
|
import modules.runtime_utils as runtime_utils
|
||||||
import modules.sd_models as sd_models
|
import modules.sd_models as sd_models
|
||||||
import modules.sd_vae as sd_vae
|
import modules.sd_vae as sd_vae
|
||||||
|
|
@ -861,8 +862,8 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||||
|
|
||||||
devices.torch_gc()
|
devices.torch_gc()
|
||||||
|
|
||||||
seed = get_fixed_seed(p.seed)
|
p.seed = get_fixed_seed(p.seed)
|
||||||
subseed = get_fixed_seed(p.subseed)
|
p.subseed = get_fixed_seed(p.subseed)
|
||||||
|
|
||||||
if p.restore_faces is None:
|
if p.restore_faces is None:
|
||||||
p.restore_faces = opts.face_restoration
|
p.restore_faces = opts.face_restoration
|
||||||
|
|
@ -889,15 +890,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||||
p.fill_fields_from_opts()
|
p.fill_fields_from_opts()
|
||||||
p.setup_prompts()
|
p.setup_prompts()
|
||||||
|
|
||||||
if isinstance(seed, list):
|
prompt_seed_prep.prepare_prompt_seed_state(p)
|
||||||
p.all_seeds = seed
|
|
||||||
else:
|
|
||||||
p.all_seeds = [int(seed) + (x if p.subseed_strength == 0 else 0) for x in range(len(p.all_prompts))]
|
|
||||||
|
|
||||||
if isinstance(subseed, list):
|
|
||||||
p.all_subseeds = subseed
|
|
||||||
else:
|
|
||||||
p.all_subseeds = [int(subseed) + x for x in range(len(p.all_prompts))]
|
|
||||||
|
|
||||||
if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings:
|
if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings:
|
||||||
model_hijack.embedding_db.load_textual_inversion_embeddings()
|
model_hijack.embedding_db.load_textual_inversion_embeddings()
|
||||||
|
|
|
||||||
30
modules/prompt_seed_prep.py
Normal file
30
modules/prompt_seed_prep.py
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
"""
|
||||||
|
Prompt and seed preparation for Stable Diffusion processing.
|
||||||
|
|
||||||
|
Extracted from processing.py (M06) to isolate preparation logic from sampling.
|
||||||
|
Behavior-preserving: writes directly to p; assumes setup_prompts() already ran.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_prompt_seed_state(p):
|
||||||
|
"""
|
||||||
|
Populate p.all_seeds and p.all_subseeds from p.seed and p.subseed.
|
||||||
|
|
||||||
|
Assumes:
|
||||||
|
- p.seed and p.subseed have already been normalized via get_fixed_seed()
|
||||||
|
- p.setup_prompts() has already run (p.all_prompts exists)
|
||||||
|
"""
|
||||||
|
if isinstance(p.seed, list):
|
||||||
|
p.all_seeds = p.seed
|
||||||
|
else:
|
||||||
|
p.all_seeds = [
|
||||||
|
int(p.seed) + (x if p.subseed_strength == 0 else 0)
|
||||||
|
for x in range(len(p.all_prompts))
|
||||||
|
]
|
||||||
|
|
||||||
|
if isinstance(p.subseed, list):
|
||||||
|
p.all_subseeds = p.subseed
|
||||||
|
else:
|
||||||
|
p.all_subseeds = [int(p.subseed) + x for x in range(len(p.all_prompts))]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue