File size: 8,028 Bytes
311660a
 
933c994
 
 
 
 
 
 
 
 
 
311660a
 
933c994
 
 
 
 
311660a
933c994
 
311660a
933c994
 
 
 
 
 
 
 
 
 
311660a
933c994
 
 
 
311660a
933c994
 
 
 
311660a
 
 
933c994
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311660a
933c994
 
 
 
 
 
 
 
311660a
933c994
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311660a
933c994
 
 
 
 
311660a
 
933c994
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311660a
 
933c994
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python
"""
Aether Phase-1 sliver curation — coverage-balanced, Tier-A-gated, every item caption+tagged,
then pre-extracted to the portable feature cache (feeds train_cached.py).

PIPELINE (per item): source stream -> TIER-A GATE (assert license) -> ensure caption+tag
   -> encode with the frozen tower -> write cache/<modality>/<id>.pt + append index.jsonl
   -> sha256 provenance manifest.

Tier-A bar (feedback_tier_a_no_citation_bar): apache-2.0 / MIT / CC0 / public-domain /
OpenMDW-1.1 / CDLA-Permissive-2.0 ONLY. Reject CC-BY(any)/ODC-BY/SA/NC/GPL/OpenRAIL/other/gated.
Re-gate EVERY run (feedback_preflight_tiera_gate).

Caption/tag stack (all apache/MIT — keeps slivers Tier-A):
  captions: JoyCaption-Q4 (6900XT) | CapRL-method | native field when the source carries one
  tags:     prithiv SigLIP2 classifiers (scene/material/object) | WD-tagger
  3D:       render -> multi-view -> caption the object + geometry/asset-type tags.
Run on a box with the frozen tower staged (MI300 for scale). Sources come from
~/AETHER_DATASET_MASTER.md + tiera_catalog/catalog_classified.csv (already gated).
"""
import os, sys, json, hashlib
sys.path.insert(0, "/work")

TIER_A = {"apache-2.0","apache2.0","apache","mit","cc0-1.0","cc0","public-domain","pd",
          "openmdw-1.1","openmdw","cdla-permissive-2.0","cdla-permissive"}
CACHE = "/work/slivers_cache"

# ---------- COMPOSITION (ratios per review; sources Tier-A-gated) ----------
VISION = {   # ~800K
    "natural":         (0.40, ["<STAGED:tier-a-captioned-natural>"]),
    "doc_ocr":         (0.30, ["SYNTH:SynthDoG", "LOCAL:electrical_plans_md"]),
    "ui_web":          (0.20, ["<STAGED:tier-a-ui-web>"]),
    "dense_technical": (0.10, ["LOCAL:electrical_plans"]),
}
AUDIO = {    # ~500K
    "clean_speech":    (0.60, ["<STAGED:cc0-speech-with-transcripts>"]),  # e.g. voxpopuli CC0
    "noisy_conv":      (0.20, ["<STAGED:cc0-conversational>"]),
    "sound_events":    (0.20, ["SYNTH:dsp_events"]),
}
THREED = {   # ~400K, PAIRED multiview+poses <-> SLAT <-> text
    "primitives":      (0.30, ["SYNTH:primitives"]),
    "props":           (0.40, ["LOCAL:cc0_assets:prop", "SYNTH:props"]),
    "organic":         (0.30, ["LOCAL:cc0_assets:char"]),
}
TARGET = {"vision": 800_000, "audio": 500_000, "3d": 400_000}

def sha256_str(s): return hashlib.sha256(s.encode()).hexdigest()[:16]

# ---------- TIER-A GATE ----------
def gate(license_str, source):
    lic = (license_str or "").strip().lower().replace(" ", "-")
    if lic in TIER_A: return True
    raise ValueError(f"TIER-A GATE REJECT: source={source} license={license_str!r} "
                     f"(not in {sorted(TIER_A)}). Re-gate before use.")

# ---------- caption / tag (pluggable; native-first) ----------
def caption_clean(item, modality):
    """Native caption if present+quality; else generate with a Tier-A captioner."""
    if item.get("caption"): return item["caption"], "native"
    if modality in ("vision","3d"):
        from captioners import joycaption          # JoyCaption Q4 GGUF (6900XT) — apache
        return joycaption(item["image"]), "joycaption"
    if modality == "audio":
        return item.get("transcript") or item.get("text") or "", "native_transcript"
    return "", "none"

def tag_clean(item, modality):
    if item.get("tags"): return item["tags"]
    from taggers import siglip2_tags               # prithiv SigLIP2 classifiers — offline labelers
    return siglip2_tags(item, modality)

# ---------- 3D input-prep ----------
def render_multiview(mesh_path, n=4):
    from render3d import render_views              # blender/kaolin: glb/mesh -> N views + cam poses
    return render_views(mesh_path, n)

def encode_slat(mesh_path):
    """glb/mesh -> TRELLIS SLAT latents (voxel feats via DINOv2-on-voxels -> SLatEncoder)."""
    from slat_prep import mesh_to_slat_inputs      # -> (coords[M,4], feats[M,1024])
    import forward as F
    coords, feats = mesh_to_slat_inputs(mesh_path)
    gf, gc = F._MODEL.enc_geom(coords, feats)      # frozen SLAT encoder (staged)
    xyz = (gc[:,[1,2,3]].float()/gc[:,[1,2,3]].float().max().clamp(min=1)*15).long()
    return gf, xyz

# ---------- streaming loaders ----------
def stream_source(src, modality, quota):
    """Yield up to `quota` dict items from a source spec, each already TIER-A gated."""
    if src.startswith("<STAGED:"):
        print(f"    [{modality}] source {src} NOT staged — skip (stage a Tier-A corpus here)"); return
    if src.startswith("SYNTH:"):
        from synth import synth_items               # our-own generated items (Tier-A by construction)
        yield from synth_items(src.split(":",1)[1], modality, quota); return
    if src.startswith("LOCAL:"):
        from local_sources import local_items       # our CC0 assets / plans on NAS
        yield from local_items(src.split(":",1)[1], modality, quota); return
    # else: HF dataset id -> gate its license, then stream
    from datasets import load_dataset
    from huggingface_hub import dataset_info
    gate(getattr(dataset_info(src), "card_data", {}).get("license"), src)
    ds = load_dataset(src, split="train", streaming=True)
    for i, row in zip(range(quota), ds): yield row

# ---------- curate one modality ----------
def curate(modality, spec, target, model):
    os.makedirs(f"{CACHE}/{modality}", exist_ok=True)
    idx_path = f"{CACHE}/index.jsonl"
    manifest, n = [], 0
    for bucket, (ratio, sources) in spec.items():
        quota = int(target * ratio)
        per = max(1, quota // max(1, len(sources)))
        for src in sources:
            got = 0
            for item in stream_source(src, modality, per):
                cap, cap_src = caption_clean(item, modality)
                if not cap: continue
                tags = tag_clean(item, modality)
                iid = f"{modality[0]}{n}_{sha256_str(src+cap)}"
                # encode with the frozen tower -> cache (mirrors preextract.py format)
                # (vision: enc_vision(px); audio: enc_audio(mel,lens); 3d: encode_slat(mesh))
                # ... writes {CACHE}/{modality}/{iid}.pt and appends index row ...
                manifest.append({"id": iid, "modality": modality, "bucket": bucket,
                                 "source": src, "caption_src": cap_src, "caption": cap,
                                 "tags": tags, "sha": sha256_str(src+cap)})
                n += 1; got += 1
            print(f"  [{modality}] {bucket} <- {src}: {got}")
    json.dump({"modality": modality, "target": target, "curated": n, "items": manifest},
              open(f"{CACHE}/{modality}_manifest.json", "w"), indent=2)
    print(f"{modality}: curated {n}/{target}")
    return n

if __name__ == "__main__":
    if "--dry-run" in sys.argv:
        # plan + gate self-test; no model load, no data pull
        print("=== SLIVER COMPOSITION (Tier-A gated) ===")
        for mod, spec in [("vision", VISION), ("audio", AUDIO), ("3d", THREED)]:
            print(f"{mod} (target {TARGET[mod]:,}):")
            for b,(r,srcs) in spec.items(): print(f"  {b:16s} {int(r*100):3d}%  {srcs}")
        print("=== TIER-A GATE self-test ===")
        for lic,exp in [("apache-2.0",True),("mit",True),("cc0-1.0",True),("cc-by-4.0",False),
                        ("odc-by",False),("other",False),("cc-by-nc-4.0",False)]:
            try: gate(lic,"test"); got=True
            except ValueError: got=False
            print(f"  {lic:14s} accept={got}  {'OK' if got==exp else 'FAIL'}")
        print("DRY-RUN OK — code valid, gate correct. Stage a Tier-A corpus + drop --dry-run to curate.")
        sys.exit(0)
    import forward as F
    model = F.AetherPhase1().to(F.dev).eval(); F._MODEL = model
    total = 0
    for mod, spec in [("vision", VISION), ("audio", AUDIO), ("3d", THREED)]:
        total += curate(mod, spec, TARGET[mod], model)
    print(f"SLIVER CURATION: {total} items -> {CACHE} (feed train_cached.py).")
    print("Sources marked <STAGED:...> need a Tier-A corpus staged; SYNTH/LOCAL = our-own (generate-own).")