Add scene fragments to portrait prompts after clothing.

Thing, room, yard and climate precipitation can contribute a short prompt when they are in frame, with a budget so chairs stay silent.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 23:35:17 +03:00
co-authored by Cursor
parent f046f145ec
commit 3c682a2b74
26 changed files with 1020 additions and 26 deletions
+12 -12
View File
@@ -15,25 +15,25 @@
## Задачи
- [ ] Блок `prompt` на `ThingDef`, `RoomDef` (и территории, если двор — тот же блок) и на осадках
- [x] Блок `prompt` на `ThingDef`, `RoomDef` (и территории, если двор — тот же блок) и на осадках
климата (ясно / дождь / снег). Пустой = нет вклада. Валидация: строка ≤ 120 символов,
вес конечный ≥ 0
- [ ] Ваниль: непустой вклад у доски и у снега; обычный `Chair` без блока или с пустым
- [ ] Сборщик (на работнике, не в Simulation): узел человека → комната/двор + fill + worn/held
- [x] Ваниль: непустой вклад у доски и у снега; обычный `Chair` без блока или с пустым
- [x] Сборщик (на работнике, не в Simulation): узел человека → комната/двор + fill + worn/held
с блоком + погода только на улице. После слоя одежды. Порядок: вес ↓, затем `defName`
- [ ] Бюджет с дефолтом в опциях/профиле: 6 фрагментов, 2 LoRA сцены, 2 embeddings сцены.
- [x] Бюджет с дефолтом в опциях/профиле: 6 фрагментов, 2 LoRA сцены, 2 embeddings сцены.
LoRA — параметры Swarm; embeddings — `<embed:…>` как в фазе 61
- [ ] `GET .../portrait/prompt` включает сцену. Сокет не бампить
- [ ] Живые школы: пустой блок на старых вещах — поведение как вчера
- [x] `GET .../portrait/prompt` включает сцену. Сокет не бампить
- [x] Живые школы: пустой блок на старых вещах — поведение как вчера
## Тесты, без которых фаза не закрыта
- [ ] Каталог: доска даёт positive; Chair не попадает в сборку; строка 121 символ — ошибка загрузки
- [ ] Человек в кабинете с доской: промпт содержит фрагмент доски после одежды; без доски на карте — нет
- [ ] На улице в снег — фрагмент снега; в кабинете в снег — снега нет
- [ ] Больше 6 кандидатов — в тексте только топ-6 по весу; детерминированный тай-брейк по имени
- [ ] LoRA сцены в `loras`, не в тексте; embedding сцены в positive как `<embed:…>`
- [ ] «Показать промпт» / `GET prompt` совпадает со сборкой Generate (без вызова Swarm)
- [x] Каталог: доска даёт positive; Chair не попадает в сборку; строка 121 символ — ошибка загрузки
- [x] Человек в кабинете с доской: промпт содержит фрагмент доски после одежды; без доски на карте — нет
- [x] На улице в снег — фрагмент снега; в кабинете в снег — снега нет
- [x] Больше 6 кандидатов — в тексте только топ-6 по весу; детерминированный тай-брейк по имени
- [x] LoRA сцены в `loras`, не в тексте; embedding сцены в positive как `<embed:…>`
- [x] «Показать промпт» / `GET prompt` совпадает со сборкой Generate (без вызова Swarm)
## Критерий готовности
+8 -3
View File
@@ -507,11 +507,16 @@ land under `saves/{id}.portraits/` and survive until the school is deleted.
### `GET /api/schools/{id}/people/{personId}/portrait/prompt`
Returns the positive and negative prompts SwarmUI would receive, without generating an image.
Same `kind` query as GET portrait. For `kind=custom`, optional query `promptExtra` is appended after
Same `kind` query as GET portrait. POST generate uses this same assembly (scene included) before
calling Swarm. For `kind=custom`, optional query `promptExtra` is appended after
the shot type; when omitted, the last saved custom prompt is used if one exists. Configured
embeddings appear as `<embed:name>` (weight ≠ 1: `<embed:name:w>`); LoRA is not written into the
prompt. Unknown school is `404` `unknown-school`; unknown person is `404` `unknown-person`. Invalid
`kind` is `400` `invalid-query`; custom without a usable prompt is `400` `invalid-body`.
prompt. Scene fragments from the person's room, map fill, worn/held defs and outdoor weather follow
clothing, capped by `Simulation.PortraitSceneFragmentLimit` (default 6). Scene LoRA is merged into
Swarm `loras` / `loraweights` (default 2); scene embeddings use the same `<embed:…>` tags (default 2).
Empty `prompt` blocks are silent. Unknown school is `404` `unknown-school`; unknown person is `404`
`unknown-person`. Invalid `kind` is `400` `invalid-query`; custom without a usable prompt is `400`
`invalid-body`.
```json
{