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.
107 lines
4.2 KiB
Python
107 lines
4.2 KiB
Python
"""Convergent-evidence analysis of the deepstack layer-gain tables.
|
|
|
|
Reproduces the qualitative chunk->function determination from the repo's own
|
|
tuned tables, with no rendering required. The argument: the five built-in
|
|
layer tables were tuned independently for five different jobs (style,
|
|
palette, material, lighting, and the even baseline). Where the four
|
|
appearance-borrowing tables AGREE about a chunk - all suppress it, or all
|
|
spike it - that agreement is convergent evidence about what the chunk
|
|
carries, because four independent tuning targets converged on the same
|
|
treatment of that chunk.
|
|
|
|
Run: python docs/deepstack-layers/analyze_tables.py
|
|
Reads the live tables from kg_krea_v9/recipes.py via the test stubs, so the
|
|
output tracks the code and can never silently drift from it.
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(REPO_ROOT / "tests"))
|
|
|
|
from _kg_stub_env import load_module # noqa: E402
|
|
|
|
CHUNKS = 12
|
|
# The four tables whose job is to import appearance and reject structure.
|
|
# Their agreement is the evidence; the even baseline is the neutral control.
|
|
APPEARANCE = ("style", "palette", "material", "lighting")
|
|
|
|
|
|
def load_tables():
|
|
v9, _ = load_module("kg_krea_v9", "kg_deepstack_table_analysis")
|
|
r = v9.recipes
|
|
return {
|
|
"even": list(r.EVEN_LAYER_PULL),
|
|
"style": list(r.STYLE_LAYER_PULL),
|
|
"palette": list(r.PALETTE_LAYER_PULL),
|
|
"material": list(r.MATERIAL_LAYER_PULL),
|
|
"lighting": list(r.LIGHTING_LAYER_PULL),
|
|
}
|
|
|
|
|
|
def classify(chunk_vals):
|
|
"""Consensus verdict for one chunk across the appearance tables."""
|
|
lo, hi = min(chunk_vals), max(chunk_vals)
|
|
mean = sum(chunk_vals) / len(chunk_vals)
|
|
if hi < 1.0:
|
|
return mean, "STRUCTURE (all suppress <1.0)"
|
|
if all(abs(v - 1.0) < 1e-9 for v in chunk_vals):
|
|
return mean, "TRANSITION (all neutral)"
|
|
if lo >= 1.0 and mean > 1.5:
|
|
return mean, "APPEARANCE (all spike >1.0)"
|
|
if lo >= 1.0:
|
|
return mean, "mild-positive (all >=1.0, gentle)"
|
|
return mean, "mixed"
|
|
|
|
|
|
def main():
|
|
tables = load_tables()
|
|
|
|
print("=" * 78)
|
|
print("Per-chunk gains across the five tuned tables")
|
|
print("=" * 78)
|
|
print("chunk | " + " ".join(f"{n:>8}" for n in tables))
|
|
for i in range(CHUNKS):
|
|
print(f" {i:>2} | " + " ".join(f"{tables[n][i]:>8.2f}" for n in tables))
|
|
|
|
print("\n" + "=" * 78)
|
|
print("Consensus of the four appearance tables (style/palette/material/lighting)")
|
|
print("=" * 78)
|
|
print("chunk | mean | min | max | consensus verdict")
|
|
verdicts = []
|
|
for i in range(CHUNKS):
|
|
vals = [tables[n][i] for n in APPEARANCE]
|
|
mean, verdict = classify(vals)
|
|
verdicts.append((i, mean, verdict))
|
|
print(f" {i:>2} | {mean:>5.2f} | {min(vals):.2f} | {max(vals):.2f} | {verdict}")
|
|
|
|
print("\n" + "=" * 78)
|
|
print("Findings")
|
|
print("=" * 78)
|
|
structure = [i for i, _, v in verdicts if v.startswith("STRUCTURE")]
|
|
appearance = [i for i, _, v in verdicts if v.startswith("APPEARANCE")]
|
|
ranked = sorted(appearance, key=lambda i: -sum(tables[n][i] for n in APPEARANCE))
|
|
print(f" Structure-carrying chunks (all 4 suppress): {structure}")
|
|
print(f" Appearance-carrying chunks (all 4 spike): {appearance}")
|
|
print(" Appearance response ranking (strongest first):")
|
|
for rank, i in enumerate(ranked, 1):
|
|
m = sum(tables[n][i] for n in APPEARANCE) / len(APPEARANCE)
|
|
print(f" #{rank} chunk {i:>2} mean {m:.2f}x")
|
|
|
|
# Monotonic front ramp = structure fades in smoothly with depth 0->5.
|
|
print(" Front-ramp monotonicity (chunks 0-5, structure fading in with depth):")
|
|
for n in APPEARANCE:
|
|
front = tables[n][:6]
|
|
mono = all(front[j] <= front[j + 1] for j in range(5))
|
|
print(f" {n:>8}: {front} monotonic-rising={mono}")
|
|
|
|
print("\n Interpretation: four tables tuned for FOUR DIFFERENT jobs agree that")
|
|
print(" chunks 0-4 carry structure (all suppress, smooth depth ramp), chunks 5-6")
|
|
print(" are transitional, and chunks 7/8/10 carry appearance (all spike, chunk 8")
|
|
print(" strongest). That agreement is the measurement encoded as data.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|