Commit Graph
7 Commits
Author SHA1 Message Date
Kevin Gilper e8a97d0dcf Stage 3 render-derivation: shipped style table measures best; layers are second-order
Ran a render-based derivation for the style role on the model: held the real
style settings fixed, varied only the 12 layers across seven candidates,
rendered and scored look-transfer minus subject-leak.

- The shipped STYLE table scored best (objective 0.106); the shallow-tap table
  was worst - render evidence supports spiking the effective deep taps.
- But differences were small and every output was nearly the same bowl: at
  realistic style settings the layer table is a second-order knob. The primary
  look-vs-subject control is strength and the shape/global split.

Bottom line committed to the README: the reliable way to set the layers is
render-based measurement (conditioning analysis alone misleads); applying it
shows the shipped tables are directionally right and, for the style role,
near-optimal. The durable deliverable is the render harness, which can
re-derive or verify the layers for any future checkpoint. Full result + images
in local_records.
2026-07-03 07:50:48 -04:00
Kevin Gilper 5291940073 Render-validate the tap measurement: deep taps dominate, must derive from renders
Ran the decisive test on the model: isolate specific taps (shape=1, global=0),
render, measure. Result flipped the conditioning-level read:

- Mechanism confirmed live (feature width 30720 = 12x2560, split engages).
- Clean-stimuli Stage 1 does show proportional selectivity (shallow taps lean
  palette, middle lean texture) - but render validation shows it is
  practically irrelevant: the deep taps' large magnitude dominates the pixel
  effect. Spiking taps 7/8/10 reproduced the reference entirely; spiking the
  shallow taps did nothing.
- So the shipped tables spiking 7/8/10 target the effective (high-leverage)
  taps, which the model's projector also emphasizes; the effective taps move
  palette+texture+subject together and do not cleanly separate.

The load-bearing lesson for reliable derivation: conditioning-level analysis
misleads because magnitude and the nonlinear diffusion path dominate - the
layers can only be derived reliably from renders. README Stage 1/2 updated;
full arc + validation images in local_records.
2026-07-03 07:44:16 -04:00
Kevin Gilper 7ce90da3a9 Run Stage 1 live: mechanism confirmed, taps show no attribute specialization
Installed V10 + the probe node on the render box, generated a controlled
reference set, and ran the encode-only selectivity harness on the real Krea 2
model. First actual measurement of the 12 text-layer taps:

- Mechanism confirmed live: probe reports feature width 30720 (= 12 x 2560),
  divisible by 12, so the tap split engages on the model (no fallback). Tap
  magnitude rises with depth.
- No strong per-tap specialization: after removing the depth-magnitude
  confound, every tap carries essentially the same attribute mix (palette
  0.20 / structure 0.33 / texture 0.35 / lighting 0.12; cross-tap std-dev
  ~0.01). Taps differ by overall magnitude (depth), not by which attribute
  they encode - only a faint depth gradient in the design direction, far too
  weak to justify the tables' 5x spikes. The "tap 8 = palette" premise is not
  supported.

Caveats recorded honestly (seq-mean signature, weak palette axis from a
near-neutral base, single scene). README Stage 1 updated with the result;
raw signatures + full write-up in local_records. Also fixes the probe graph
generator to supply the V10 card's full widget set (API validation).
2026-07-03 07:24:09 -04:00
Kevin Gilper 839fa6e246 Add the layer-derivation harness (reliable, targeted methodology)
Replaces "borrow a template + eyeball renders" with a staged pipeline for
setting the 12 layer-gain values, cheapest/most-targeted first:

- Stage 0 (done, local): extract_model_prior.py reads Krea 2's own learned
  per-tap weighting (txtfusion.projector [1,12]) from the checkpoint;
  compare_to_model_prior.py scores each shipped table against it. Finding:
  the model leans hardest on taps 7>9>4>10>8 but the tables spike 8>10>7
  (rank-corr only +0.58..+0.64) - the borrowed template does not track how
  the model uses the taps. model_prior.json records the values.
- Stage 1 (harness ready, no render): probe_node/ is a tiny ComfyUI node
  that saves per-tap conditioning signatures; probe_selectivity.py does a
  variance decomposition (eta^2) of each tap against palette/structure/
  texture/lighting over a controlled reference set; generate_probe_graphs.py
  builds the encode-only graphs. The selectivity math passes a synthetic
  self-test (recovers an injected tap->attribute map exactly). Running it for
  real needs V10 + the probe node installed on a box, plus controlled image
  sets - it renders nothing (text-encoder passes only).
- Stages 2-3 (documented, need a V10 box): metric-scored render validation,
  then black-box optimization of the 12-gain vector against a stated
  objective, held-out validated.

README section 4 rewritten as the methodology. All scripts run/validate
locally; tooling stays under docs/ (excluded from registry packs).
2026-07-03 07:04:42 -04:00
Kevin Gilper f7061c7057 Correct the layer-values determination from the model + dev history
Traced the real provenance (Kevin's Codex dev sessions) and verified the
mechanism against the Krea 2 model on the render box. Two earlier claims
(07d2f0b) were wrong and are now fixed across the docs:

1. Mechanism: the 12 "deepstack chunks" are the 12 TEXT-encoder layer taps
   Krea 2 conditions on (comfy/text_encoders/krea2.py: hidden_states
   [2,5,8,...,35], (B,12,seq,2560) flattened to 30720), NOT the 3 vision
   deepstack taps (qwen3vl.py deepstack_visual_indexes=[5,11,17]) the name
   implies. 30720 % 12 == 0, so the node's split lands on the taps and the
   per-layer gains do apply (no fallback) - confirmed from the model weights
   (txtfusion.projector [1,12], layerwise blocks at 2560).

2. Provenance: the 12 values were NOT derived by a per-chunk sweep. They
   were adopted from the third-party ComfyUI-ConditioningKrea2Rebalance node
   (DEFAULT_WEIGHTS spike 8>10>7, matching STYLE_LAYER_PULL) plus the
   shallow=structure/deep=appearance principle; only the scalar shape (0.45
   ->0.35) and cap (->0.9) were empirically tuned. The four role tables are
   scalings of one template, so their agreement is design self-consistency,
   not independent measurement - the "convergent evidence" framing is
   withdrawn.

docs/deepstack-layers/ rewritten to separate verified mechanism, traced
provenance, and the still-unrun single-tap sweep. Corrections propagated to
the V9 technical paper (5.2 + architecture note + glossary), the V10 guide
and companion, custom_recipes/README, the V10 node doc, and CHANGELOG. Full
evidence chain preserved in local_records (gitignored).
2026-07-03 01:53:39 -04:00
Kevin Gilper 8f7fac5e3d Write deepstack sweep renders to the dedicated Claude output folder
SaveImage prefix now targets output/claude-generations/krea-deepstack-sweep/
on the render box, per Kevin's instruction that generated images go to a
dedicated folder and nothing else is opened. The tool only downloads back
the images it just generated.
2026-07-03 01:23:11 -04:00
Kevin Gilper 07d2f0b763 Determine and document what each deepstack layer carries
New docs/deepstack-layers/ is the authoritative, reproducible account of
the 12 layers values, at three separated confidence levels:

1. Structure (verified from code): the values are gains on 12 equal
   deepstack chunks - features from 12 successive Qwen3-VL encoder-depth
   bands. Shown in kg_krea_v9/clip_hooks.py (the deepstack feature list)
   and conditioning.py (the 12-way width split).

2. Semantics (convergent evidence): analyze_tables.py reads the live
   tables and shows the four independently-tuned appearance tables
   (style/palette/material/lighting) agree chunk-for-chunk - 0-4 carry
   structure (monotonic depth ramp, all suppress), 5-6 transition, 7/8/10
   carry appearance (all spike, chunk 8 strongest, then 10, then 7). Four
   tables tuned for four different jobs converging is the measurement
   encoded as data, not an assertion.

3. Precise response curve (fresh measurement): generate_sweep.py is a
   turnkey single-chunk-spike sweep (the paper's section 16.4 method),
   emitting each spike as a V10 custom recipe validated against the real
   node code. Dry-run works anywhere; rendering needs the V10 nodes on a
   ComfyUI box (single-chunk tables are not V9-expressible), so the
   measured-verdict table is staged pending a V10-equipped render box.
   SCORING.md defines the rubric.

Cross-linked from technical paper 5.2, the recipe guide, and
custom_recipes/README. Tooling lives under docs/ (excluded from registry
packs by .comfyignore). sweep_out/ is gitignored.
2026-07-03 00:59:35 -04:00