#!/usr/bin/env python """ Aether Phase-1 CACHED alignment trainer — trains from pre-extracted features with NO ENCODERS LOADED. This is the portable path: base LM (or 4-bit QLoRA of it) + the tiny projectors fit a 16GB card, so alignment/adapters run on 6900XT / Kaggle-T4 / Colab. Consumes /work/slivers_cache/{index.jsonl, /.pt} from preextract.py. Proves loss drops on REAL cached features across ALL THREE modalities at once. """ import os, sys, json, torch, torch.nn as nn sys.path.insert(0,"/work") import forward as F # build_mrope, Projector, build_special, TXT, dev (no encoder load on import) from transformers import AutoModelForImageTextToText, AutoTokenizer dev=F.dev; TXT=F.TXT; CACHE="/work/slivers_cache" class CachedAether(nn.Module): """Base LM + projectors + expanded vocab. NO encoders (features come pre-extracted).""" def __init__(self): super().__init__() self.base=AutoModelForImageTextToText.from_pretrained("/work/base",torch_dtype=torch.bfloat16,trust_remote_code=True) self.tok=AutoTokenizer.from_pretrained("/work/base",trust_remote_code=True) old=len(self.tok); self.tok.add_special_tokens({"additional_special_tokens":F.build_special()}) self.new_vocab=len(self.tok); self.base.resize_token_embeddings(self.new_vocab); self.new_row_lo=old self.visual_proj=F.Projector(3200,TXT); self.audio_proj=F.Projector(1280,TXT) self.mv_proj=F.Projector(3200,TXT); self.geom_proj=F.Projector(8,TXT) self.cam_pose=nn.Parameter(torch.zeros(1,1,TXT)) self.id={k:self.tok.convert_tokens_to_ids(k) for k in ["","