Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d8ed2c4
Merge pull request #17 from cammo22/feat/klein-upsampler-veloce
cammo22 Oct 21, 2026
46d70f9
engine v2: catalogo con licenza/ruolo/uncensored, guardia di download…
cammo22 Oct 22, 2026
1fff294
GUI v2 (F0+F1): tema Orbita, Studio con i modi Crea/Modifica/Box/Rice…
cammo22 Oct 22, 2026
e85ce35
GUI v2 (F3): modo Box, l'editor regionale con riquadri e disposizioni
cammo22 Oct 22, 2026
cd08e9b
feat(lora): pila ordinabile con pesi e compatibilità
cammo22 Oct 22, 2026
20ad22a
feat(impostazioni): collega laboratorio Uncensored e consenso esplicito
cammo22 Oct 22, 2026
9f359c8
engine v2: nodi DaProdSfondo (BiRefNet, MIT) e DaProdSegmenta (SAM 2.…
cammo22 Oct 22, 2026
03b0d07
engine v2: riconoscimento LoRA per famiglia (loraBase) e regional pro…
cammo22 Oct 22, 2026
37b6f9f
scripts: bench_serie, lettura chiavi safetensors e template
cammo22 Oct 22, 2026
c6a1179
engine v2: FLUX.2 Klein 4B nei grafi, LoRA multipli su Klein, senza s…
cammo22 Oct 22, 2026
9ea978a
LoRA: famiglie compatibili dall'intestazione (Qwen, Klein 3, Klein 4B)
cammo22 Oct 22, 2026
1ca317d
coda: Klein 4B ha la sua chiave VRAM; sfondo e segmenta scaricano BiR…
cammo22 Oct 22, 2026
85f4876
test: grafi v2, regioni, LoRA; npm test; confronto grafi con regioni.ts
cammo22 Oct 22, 2026
25bbd8e
catalogo uncensored: scaricabile solo con licenza valida (motivoLicen…
cammo22 Oct 22, 2026
f531cde
adattatore GUI v2 → motore: box in regioni, sfondo (trasparente/tinta…
cammo22 Oct 22, 2026
557d81b
IPC: modelli.segmentatori e lora.compatibili(famiglia); finto.js alli…
cammo22 Oct 22, 2026
6a72030
docs: contratto engine-GUI; misure_gpu con esbuild e prove di Klein 4B
cammo22 Oct 22, 2026
8c491f2
GUI v2: pannello dei controlli a sinistra nello Studio
cammo22 Oct 22, 2026
f3f21dd
GUI v2: idee in una scheda propria (Modifica)
cammo22 Oct 22, 2026
d7073ae
docs: gui-v2-spec con il pannello dei controlli a sinistra
cammo22 Oct 22, 2026
07752a7
benchmark engine v2: Klein 3 8 passi contro Klein 4B 4 passi (docs/be…
cammo22 Oct 22, 2026
5bc3f5b
CHANGELOG: engine v2 (non rilasciato)
cammo22 Oct 22, 2026
13ec7f0
Merge pull request #19 from cammo22/feat/engine-v2
cammo22 Oct 22, 2026
9563268
Merge main (engine v2) in feat/gui-v2: Uncensored con i booleani del …
cammo22 Oct 22, 2026
1a031fa
GUI v2: le sei ricette (Foglio, Mondi, Mix, Set, Formati, Rinnova) al…
cammo22 Oct 22, 2026
e33edc7
GUI v2: Estrai in due clic (ritaglio fedele con SAM 2, contratto engi…
cammo22 Oct 22, 2026
4ab5113
feat(gui): completa controlli per categoria e scelte modello nello St…
cammo22 Oct 22, 2026
c44d53b
Box: niente blocco pixel né foto di riferimento che il motore ignora;…
cammo22 Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## Non rilasciato — engine v2

Il motore impara cose nuove (la versione dell'app non cambia qui: la alza chi pubblica). `engine/versioni.json`: motore 9, quindi al primo avvio l'app aggiorna il motore da sola. Il contratto con l'interfaccia è in `docs/contratto-engine-gui.md`.

- **FLUX.2 Klein 4B** (Apache-2.0, 4 passi) come quarto modello. Misurato su RTX 4060: Crea 5,4 s contro 6,4 s di Klein 3, zona 21 s contro 25 s, Modifica 9,6 s contro 11,5 s (`docs/bench-engine-v2.md`). Non è il predefinito.
- **LoRA multipli con pesi** su tutti i modelli (Qwen e Klein): in fila, forza da −2 a 2. Il riconoscimento dai nomi dei tensori dice per quale modello è fatto un LoRA (`src/shared/loraBase.ts`); nuovo IPC `lora.compatibili(famiglia)`.
- **Senza sfondo** (BiRefNet, MIT) e **estrai fedele** (SAM 2.1, Apache-2.0): ritagliano dai pixel della tua foto, senza ridisegnarla; i modelli si scaricano al primo uso e girano a parte. Con Klein, «sfondo trasparente» in Crea = disegno + BiRefNet.
- **Riquadri nell'Editor box** (regional prompting): Klein 3 li legge nel suo formato (JSON con le coordinate), Qwen e Klein 4B a parole. Nuovo adattatore dalla richiesta della GUI (`box`, `promptScena`, `sfondo`).
- **Catalogo con licenza e ruolo**, modelli «uncensored» marcati e scaricabili solo su richiesta: interruttore acceso, avviso accettato e licenza valida (Apache, MIT, BSD, CC-BY o Qwen Research con avviso; mai FLUX Kommunity). Un LLM uncensored (Qwen3-VL 4B abliterated) per i testi.
- Correzioni: Klein 4B ha la sua chiave VRAM nella regola «una cosa alla volta»; le parole chiave dei LoRA entrano nel prompt anche con Klein.
- Prove: `npm test` (modelli, catalogo, spazio, lora, regioni, adatta, grafi v2, grafi Qwen identici).

## 1.1.0 — 2026-10-21

Un'app più semplice da usare: tre modelli al posto delle «qualità», una sola scheda per scrivere cosa cambiare (tutta la foto o solo una zona), le ricette dentro Modifica e il testo scritto dal Qwen3-VL 4B anche con Qwen. Il motore passa a ComfyUI 0.42.3.
Expand Down
38 changes: 38 additions & 0 deletions docs/bench-engine-v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Benchmark engine v2 — prima / dopo

Misurato il 22/10/2026 su RTX 4060 8 GB (driver 617.42), ComfyUI 0.42.3 (engine installato, motore 8), tutto 1024×1024, stesso prompt e stessa maschera di `scripts/misure_gpu.mjs`.
Grafi veri dell'app (`grafi.ts` impacchettato con esbuild). GPU libera prima di ogni giro (< 15 %), un benchmark alla volta, ComfyUI di prova sulla porta 8819 (non quello dell'app, non quello degli asset: il 8818 era fermo e vuoto). Dati completi: `docs/bench-engine-v2.json`.
Come si ripete: `node scripts/bench_serie.mjs --repo . --out <cartella> --etichetta <nome> --rip 3 --porta 8819 <prove>` con `MOTORE_OUT` = cartella di output del motore (`node scripts/misure_gpu.mjs --prova elenco` stampa le prove).

**Prima** = Klein 3 veloce, 8 passi (il percorso rapido di prima di engine v2). **Dopo** = FLUX.2 Klein 4B FP8, 4 passi (`Flux2Scheduler` + `CFGGuider`).

## A caldo (mediana di 3 giri dopo un giro di riscaldamento)

| Scenario | Modello | Passi | Totale | s/passo | VRAM picco* | Peggiore |
|---|---|---:|---:|---:|---:|---:|
| Crea | Klein 3 veloce (prima) | 8 | 6,4 s | 0,471 | 6,1 GB | 6,4 s |
| Crea | **Klein 4B (dopo)** | 4 | **5,4 s** | 0,572 | 5,3 GB | 5,4 s |
| Crea | Klein 4B, 8 passi (controllo) | 8 | 8,5 s | 0,711 | 7,1 GB | 8,5 s |
| Modifica zona | Klein 3 veloce (prima) | 8 | 24,9 s | 1,873 | 7,4 GB | 25,7 s |
| Modifica zona | **Klein 4B (dopo)** | 4 | **21,3 s** | 2,258 | 6,1 GB | 21,5 s |
| Modifica tutta la foto | Klein 3 veloce (prima) | 8 | 11,5 s | 1,050 | 6,9 GB | 11,5 s |
| Modifica tutta la foto | **Klein 4B (dopo)** | 4 | **9,6 s** | 1,307 | 7,3 GB | 9,6 s |

## A freddo (1 giro; modelli scaricati con `/free`, i file restano nella cache del disco)

| Scenario | Modello | Passi | Totale | s/passo | VRAM picco* |
|---|---|---:|---:|---:|---:|
| Crea | Klein 3 veloce | 8 | 9,7 s | 0,468 | 6,8 GB |
| Crea | Klein 4B | 4 | 8,6 s | 0,623 | 6,9 GB |
| Crea | Klein 3 Base (CFG 3,5, riferimento) | 50 | 59,4 s | 1,006 | 6,8 GB |
| Crea | Qwen-Image 2.1 Q4_K_M (riferimento) | 40 | 162,9 s | 2,880 | 5,9 GB |

\* picco letto con `nvidia-smi` una volta al secondo (include la cache di PyTorch): serve a vedere che nessun giro va fuori memoria, non a confrontare i megabyte fra modelli. Il primissimo avvio a freddo di Klein 4B (file mai letti dal disco) è costato 15,6 s.

## Che cosa si tiene e che cosa no

- **Tenuto: Klein 4B come quarto modello.** Guadagno reale ma piccolo: −16 % in Crea, −14 % in zona, −17 % in Modifica, perché ogni passo costa di più (0,57 contro 0,47 s) e a 8 passi il 4B non va più veloce di Klein 3 (8,5 contro 6,4 s). Un'immagine di Crea (teiera) e le due modifiche rosse sono pulite a occhio; **non** è stato fatto un confronto di qualità alla cieca con Klein 3. Non diventa il predefinito: il vantaggio vero è la licenza Apache-2.0, non la velocità.
- **Niente altro è stato aggiunto in nome della velocità.** Le ottimizzazioni suggerite dalla ricerca (SageAttention, `torch.compile`, cache approssimate, Nunchaku/SVDQuant) non sono state installate né misurate: richiedono pacchetti esterni nell'engine produttivo (wheel Windows, graph break con l'offload) e la ricerca stessa le classifica «esperimenti separati». Non c'è un numero a loro favore, quindi non entrano.
- Già in 1.1.0 e non rimisurato qui: il 4B che scrive i testi (185,9 → 133,5 s su «Migliora + Crea» con Qwen), vedi `docs/misure-1.1.0.md`.
- BiRefNet e SAM 2 non sono stati cronometrati: i loro nodi (`DaProdSfondo`, `DaProdSegmenta`) arrivano con il motore 9 e il motore installato qui è l'8. Girano a parte, senza il modello che disegna in VRAM.
- Un incidente di misura, scartato: un secondo `bench_serie` partito per errore in parallelo ha sporcato un primo tentativo; i dati sopra vengono da una ripetizione con un solo benchmark vivo (controllato con la lista dei processi).
70 changes: 70 additions & 0 deletions docs/contratto-engine-gui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Contratto engine ↔ GUI (engine v2)

Chi lo usa: la GUI v2 (`feat/gui-v2`). Chi lo possiede: l'engine (`feat/engine-v2`): **`src/shared/tipi.ts`, `src/shared/modelli.ts`, `src/shared/loraBase.ts`, `src/renderer/src/api.ts`, `src/preload/index.ts` sono dell'engine**. La GUI tocca solo pagine e componenti del renderer; se serve un campo nuovo lo chiede (commento sul task), non lo aggiunge.
Tutto passa da `window.daprod` (tipo `Api` in `api.ts`); i canali IPC sono `area:azione` (`gestisci('lavori:accoda', …)` in `src/main/index.ts`).
Provato da: `npm test` (modelli, catalogo, spazio, lora, regioni, adatta, grafi_v2, confronto grafi Qwen) e `npm run typecheck`.

## 1. Modelli (famiglie)

`Famiglia = 'qwen' | 'klein' | 'klein-base' | 'klein4b'`. `IdModello` (`modelli.ts`) ha le stesse chiavi più `qwen-base`; `MODELLI[id]` dà nome, passi, CFG, `lora: true` per tutti.

| Famiglia | Modello | Passi (bozza/alta/massima) | CFG | Licenza pesi |
|---|---|---|---|---|
| `qwen` | Qwen-Image 2.1 GGUF | 20/40/50 | 1 | Qwen Research (solo ricerca) |
| `klein` | FLUX 3 Klein (INT8) | 8/8/16 | 1 | FLUX Kommunity |
| `klein-base` | FLUX 3 Klein Base | 25/50/64 | 3,5 | FLUX Kommunity |
| `klein4b` | FLUX.2 Klein 4B (FP8) | 4/4/8 | 1 | **Apache-2.0** |

`Richiesta.famiglia` (se manca vale `Impostazioni.famiglia`). Tre cose da sapere: Klein 4B usa `Flux2Scheduler` + `CFGGuider`; con Klein i testi (migliora prompt, descrivi…) li scrive il Qwen3-VL 4B; nelle opere in galleria il modello è `«FLUX.2 Klein 4B · file»` (`modelloDaOpera` lo riconosce).

## 2. Richiesta (`lavori.accoda(q): Promise<string[]>` → id dei lavori)

Campi comuni: `modalita`, `famiglia`, `prompt`, `negativo`, `seed` (−1 = casuale), `passi`, `cfg`, `larghezza/altezza`, `megapixel`, `immagini[]` (percorsi; [0] è la foto), `quante`, `uscita`, `lora`.

Modalità: `crea`, `modifica`, `zona` (maschera), `espandi`, `rifinisci`, `varia`, `ingrandisci`, `descrivi` (testo), `traduci`, **`sfondo`**, **`segmenta`**.

### 2.1 LoRA multipli con pesi — `Richiesta.lora: LoraAttiva[]`
`{ file, forza }`, **l'ordine della lista è l'ordine di applicazione**, forza −2…2 (fuori scala si tronca; 0 = ignorato). Vale per **tutte** le famiglie. Il motore mette un `LoraLoaderModelOnly` per ciascuno, in catena. La parola chiave di ogni LoRA acceso entra nel prompt da sola (`conParoleLora`, ora anche con Klein).
Compatibilità: `InfoLora.famiglie: Famiglia[]` (dai nomi dei tensori, `shared/loraBase.ts`) e `InfoLora.compatibile: 'si'|'no'|'?'`. `vaBeneCon(lora, famiglia)` (shared, importabile dal renderer) dice `si|no|?` (`?` = si lascia provare). Un LoRA di Klein 3 **non** va su Klein 4B (e viceversa): sono architetture diverse.
**IPC nuovo:** `lora.compatibili(famiglia): Promise<InfoLora[]>` = solo i `si` e `?` per quel modello. (`lora.elenco()` resta: tutti.)

### 2.2 Senza sfondo
- Foto esistente: `modalita: 'sfondo'`, `immagini: [foto]` → PNG RGBA (BiRefNet, MIT). I pixel del soggetto restano quelli originali, i bordi sono ripuliti dagli aloni. Non serve il modello che disegna.
- In Crea: `trasparente: true` oppure `sfondo: 'trasparente'`. Qwen usa il suo canale alfa; **Klein (tutte) genera e poi toglie lo sfondo con BiRefNet** (la GUI può dire «Klein: sfondo tolto dopo»).
- `sfondo: { tinta: '#rrggbb' }` → una riga in più nel prompt («on a plain solid #rrggbb background»). `sfondo: 'scena'` = niente.
- Il primo uso scarica BiRefNet (~450 MB) da solo; si vede nella `fase` del lavoro («Scarico BiRefNet · 40%»). Stato: `modelli.segmentatori()`.

### 2.3 Estrai personaggi/oggetti (SAM 2)
`modalita: 'segmenta'`, `immagini: [foto]`, `segmenta: { box?: [x0,y0,x1,y1], punti?: {x,y,positivo}[], ritaglia?: boolean }`. Coordinate **0–1 sulla foto**, origine in alto a sinistra. `ritaglia` true (predefinito) = PNG stretto attorno alla cosa (+12 px), false = tela intera col resto trasparente. Senza `box` né `punti` il lavoro fallisce con «dimmi cosa estrarre». Sempre dai pixel originali (nessuna ricreazione). Scarica SAM 2.1 small (~185 MB) al primo uso.
**IPC nuovo:** `modelli.segmentatori(): Promise<StatoVoce[]>` = le voci BiRefNet e SAM 2 con `presente`.

### 2.4 Regional prompting (Editor box) — per `crea` e `modifica`
Due modi equivalenti, il motore normalizza (`adattaRichiesta`, `motore/adatta.ts`):

1. **`box: BoxRegione[]` + `promptScena`** (quello che manda la GUI v2): `{ id, rect:[x0,y0,x1,y1] (0–1 sulla tela finale), tipo, prompt, rif?, rigidita, ordine, nascosta? }`. Le `nascosta` e quelle senza prompt non partono; l'ordine è `ordine`; `promptScena` (se c'è e ci sono riquadri validi) diventa il `prompt`.
2. `regioni: Regione[]` (`{ id, box, prompt }`) già pronte.

Traduzione per modello: **Klein 3 / Base** → prompt «didascalia che cita `<obj_N>`» + righe JSON con `bbox [y_min,x_min,y_max,x_max]` su 0–1000 (formato nativo, `modifica`: `tgt_bbox`); **Qwen e Klein 4B** → la posizione a parole («at the top left of the frame»). Al massimo 16 riquadri, minimo 2 % per lato. I prompt dei riquadri vengono tradotti in inglese come quello della scena (se `traduci` è acceso).
**Limiti, detti chiari:** i riquadri sono una *guida morbida* (l'elemento può uscire un po'); `rigidita: 'blocca'` per ora vale `'decisa'`; `rif` (foto di riferimento del box) non è ancora usato dal motore.

### 2.5 Modifica con istruzioni
`modalita: 'modifica'` (tutta la foto) e `'zona'` (solo la maschera, il resto identico al pixel): il `prompt` è l'istruzione («make the teapot red»). Famiglie Klein: le foto di riferimento sono `immagini[1..]` (`<image2>`…).

## 3. Catalogo, licenze, uncensored

`modelli.stato(): StatoVoce[]` restituisce **tutte** le voci con: `id`, `nome`, `tipo`, `presente`, `byte`, `licenza`, `licenzaUrl`, `ruolo` (`denoiser|encoder|llm|vae|lora|segmentatore|sfondo`), `uncensored?`, `avviso?`. `modelli.scarica(id)` / `annulla(id)` / evento `su.download`.
**La guardia è nel main**, non nella UI (`motivoDiBlocco`): una voce `uncensored` si scarica solo se **tutte e tre** le condizioni valgono, e se no `modelli.scarica` va in errore con il motivo in italiano:
1. `Impostazioni.uncensored === true` (interruttore «Modelli uncensored», spento di serie);
2. `Impostazioni.uncensoredAccettato === true` (ha letto l'avviso, `AVVISO_UNCENSORED` in `catalogo.ts`);
3. **licenza valida** (`motivoLicenza`): Apache-2.0, MIT, BSD-3-Clause, CC-BY-4.0 oppure «Qwen Research» con l'avviso sul limite d'uso. FLUX Kommunity (§4(d), niente scorciatoie per togliere le protezioni), «non-commercial» non letti, licenza o link mancanti = mai.
Nessuna voce uncensored è `consigliato`: non si scarica mai da sola né in idle. Nel catalogo ci sono: encoder Qwen3-VL 8B uncensored (AtomicChat, mradermacher; Apache), LoRA `lora-uc` (Qwen Research, con avviso), LLM **Qwen3-VL 4B abliterated** (Huihui, Apache) per i testi con Klein (`Impostazioni.testoUncensored`, serve anche l'interruttore). **Non c'è un denoiser FLUX uncensored** e non verrà aggiunto.
`Impostazioni.uncensored` è un **booleano**, non l'oggetto `{abilitato, accettatoIl…}` che la GUI v2 aveva ipotizzato: la GUI deve leggere/scrivere `uncensored`, `uncensoredAccettato`, `testoUncensored` con `impostazioni.salva`.

## 4. Coda, eventi, VRAM
Un lavoro alla volta al motore (`lavori.elenco`, `su.lavori`, `su.lavoro`). Il lavoro ha `fase` (testo in italiano, anche i download di BiRefNet/SAM2), `passo/passiTotali`, `stima`, `anteprima`, `risultati[]` (percorsi in galleria), `errore`. «Una cosa alla volta in VRAM»: cambiando famiglia (Qwen → Klein → Klein 4B) il motore scarica il modello precedente (`/free`) e la fase dice «Scarico FLUX.2 Klein 4B». `sfondo` e `segmenta` non chiedono VRAM (il nodo carica e toglie il segmentatore).

## 5. File e cartelle da conoscere
`modelli.file()` ora include `klein4b` e `klein4bTe`. Un modello Klein 4B è «pronto» con modello + text encoder (Qwen3 4B) + VAE di FLUX.2 (`kleinVae`, lo stesso di Klein 3); voci del catalogo `klein4b-fp8`, `klein4b-te`, `klein-vae`.

## 6. Cosa NON c'è (ancora)
`estrai.ritaglia` come IPC a parte: si usa `lavori.accoda` con `modalita: 'segmenta'`. `box.rif` e `rigidita: 'blocca'` non cambiano il risultato. Nessuna prova di qualità con GPU di `sfondo`/`segmenta` sul motore installato (i nodi `DaProdSfondo`/`DaProdSegmenta` arrivano col motore 9: al primo avvio dopo l'aggiornamento l'app aggiorna il motore da sola).
Loading
Loading