Download convert_decoder.py from maxffarrell/amos-1-small-CoreAI: direct link, hf CLI and curl.
- Browser
- Download file 3.61 kB
-
https://huggingface.co/maxffarrell/amos-1-small-CoreAI/resolve/main/convert_decoder.py
- Command line
-
hf download hf://maxffarrell/amos-1-small-CoreAI/convert_decoder.py
-
curl -L -o convert_decoder.py https://huggingface.co/maxffarrell/amos-1-small-CoreAI/resolve/main/convert_decoder.py
3.61 kB
| """Export AMOS Qwen3.5 bidirectional decisions and trained quote/box heads.""" | |
| import argparse,json,math,sys | |
| from pathlib import Path | |
| import torch | |
| from coreai_torch import TorchConverter,get_decomp_table | |
| from qwen_export_helpers import DecisionVision | |
| class Text(torch.nn.Module): | |
| def __init__(self,model,letters): | |
| super().__init__();self.language_model=model.model.language_model;self.noncausal=bool(getattr(model.config,'amos_noncausal',False)) | |
| self.register_buffer('readout',model.get_output_embeddings().weight[letters].detach().float().clone()) | |
| def forward(self,input_ids,attention_mask,position_ids,visual_embeddings,visual_mask): | |
| emb=self.language_model.embed_tokens(input_ids) | |
| emb=torch.where(visual_mask,visual_embeddings.to(emb.dtype),emb) | |
| mask=attention_mask[:,None,None,:].bool() | |
| if not self.noncausal: | |
| width=input_ids.shape[1];idx=torch.arange(width,device=input_ids.device);mask=mask&(idx[:,None]>=idx[None,:])[None,None] | |
| h=self.language_model(inputs_embeds=emb,attention_mask={'full_attention':mask,'linear_attention':None},position_ids=position_ids,use_cache=False).last_hidden_state | |
| return h.float(),h.float()@self.readout.T | |
| class Heads(torch.nn.Module): | |
| def __init__(self,heads):super().__init__();self.heads=heads | |
| def forward(self,question_hidden,state_hidden,image_hidden): | |
| h=self.heads;d=question_hidden.shape[0];dtype=h.span_q.weight.dtype | |
| q=question_hidden.to(dtype);s=state_hidden.to(dtype);im=image_hidden.to(dtype) | |
| span=torch.einsum('cd,lcd->cl',h.span_q(q).view(2,d),h.span_k(s).view(-1,2,d))/math.sqrt(d) | |
| region=h.region_k(im)@h.region_q(q)/math.sqrt(d) | |
| box=h.box(q,im,region,7,7) if h.box is not None else torch.zeros(4) | |
| return span.float(),region.float(),box.float() | |
| def save(m,args,path): | |
| with torch.no_grad():ep=torch.export.export(m,args,strict=False).run_decompositions(get_decomp_table()) | |
| program=TorchConverter().add_exported_program(ep).to_coreai();program.save_asset(path) | |
| return list(ep.graph_signature.user_outputs) | |
| def main(): | |
| p=argparse.ArgumentParser();p.add_argument('name');p.add_argument('--length',type=int,default=512);p.add_argument('--precision',default='bfloat16');a=p.parse_args() | |
| source=Path('upstream')/a.name;out=Path('bundles')/(a.name+'-CoreAI');out.mkdir(parents=True,exist_ok=True) | |
| sys.path.insert(0,str((source/'serve').resolve())) | |
| from amos.decoder import load_model,load_heads | |
| torch.set_num_threads(4);model,codec=load_model(str(source/'model'),'cpu',dtype=getattr(torch,a.precision));model.eval();heads=load_heads(source/'model',model,codec) | |
| d=model.config.text_config.hidden_size;L=a.length | |
| inputs=(torch.full((1,L),codec.pad,dtype=torch.int32),torch.ones(1,L,dtype=torch.int32),torch.arange(L,dtype=torch.int32).view(1,1,-1).expand(4,1,-1),torch.zeros(1,L,d),torch.zeros(1,L,1,dtype=torch.bool)) | |
| print('Exporting text',flush=True);outputs=save(Text(model,codec.letters).eval(),inputs,out/'text.aimodel') | |
| print('Exporting vision',flush=True);visual=model.model.visual;vo=save(DecisionVision(visual).eval(),(torch.zeros(196,1536),),out/'vision.aimodel') | |
| print('Exporting heads',flush=True);ho=save(Heads(heads).eval(),(torch.zeros(d),torch.zeros(L,d),torch.zeros(49,d)),out/'heads.aimodel') | |
| (out/'manifest.json').write_text(json.dumps({'sequence_length':L,'hidden_size':d,'outputs':outputs,'vision_output':vo[0],'head_outputs':ho,'precision':a.precision,'echo':codec.echo,'kinds':heads.kinds,'keep':heads.keep,'has_box':heads.box is not None,'image_side':224,'noncausal':bool(getattr(model.config,'amos_noncausal',False))},indent=2)) | |
| print('Saved',flush=True) | |
| if __name__=='__main__':main() | |