import torch, numpy as np, json
from pathlib import Path
root=Path('artifacts/pretrained-siglip-20260912/fixture'); d=json.loads((root/'manifest.json').read_text())
torch.set_grad_enabled(False); torch.set_num_threads(8)
torch.backends.cuda.matmul.allow_tf32=False; torch.backends.cudnn.allow_tf32=False
F=torch.nn.functional
def load(e): return torch.from_numpy(np.fromfile(root/e['file'],dtype='<f4').reshape(e['shape'])).cuda()
p={k:load(e) for k,e in d['parameters'].items()}
def dense(x,n): return x@p['vit.'+n+'.weight']+p['vit.'+n+'.bias']
def norm(x,n): return F.layer_norm(x,(1152,),p['vit.'+n+'.scale'].flatten(),p['vit.'+n+'.bias'].flatten(),1e-6)
def attn(q,k,v,n):
 def split(x): return x.reshape(1,-1,16,72).transpose(1,2)
 x=F.scaled_dot_product_attention(split(q),split(k),split(v)).transpose(1,2).reshape(1,-1,1152)
 return dense(x,n+'.output')
def mlp(x,n): return dense(F.gelu(dense(x,n+'.up'),approximate='tanh'),n+'.down')
for case in d['cases']:
 x=dense(load(case['inputs']['vit.image.patches']),'embedding')+p['vit.position']
 for i in range(27):
  n=f'encoder.layer{i}'
  q,k,v=dense(norm(x,n+'.attention_norm'),n+'.attention.qkv').chunk(3,dim=-1)
  x=x+attn(q,k,v,n+'.attention'); x=x+mlp(norm(x,n+'.mlp_norm'),n+'.mlp')
 x=norm(x,'encoder.final_norm')
 q=dense(p['vit.map.probe'],'map.attention.query'); k,v=dense(x,'map.attention.kv').chunk(2,dim=-1)
 x=attn(q,k,v,'map.attention'); x=x+mlp(norm(x,'map.norm'),'map.mlp')
 expected=load(case['expected'])
 print(case['name'],'mapped FP32 cosine',F.cosine_similarity(x.flatten(),expected.flatten(),dim=0).item(),'max error',(x-expected).abs().max().item(),flush=True)
