| import struct |
| import torch |
| import os |
| import glob |
| from mamba3_prime_native import build_prime_lut |
|
|
| def main(): |
| |
| ckpts = sorted(glob.glob('prime_mamba3_*.pt'), |
| key=lambda f: int(f.split('_')[-1].replace('.pt', ''))) |
| ckpt_path = ckpts[-1] |
| print(f"Loading {ckpt_path}...") |
|
|
| ckpt = torch.load(ckpt_path, map_location='cpu', weights_only=False) |
| sd = ckpt['state_dict'] |
|
|
| d_model = 1024 |
| n_layers = 28 |
| vocab_size = sd['embedding.weight'].shape[0] |
| lut_size = 65536 |
| |
| lut = build_prime_lut() |
|
|
| out_path = ckpt_path.replace('.pt', '.bin') |
| print(f"Exporting to {out_path}...") |
|
|
| with open(out_path, 'wb') as f: |
| |
| |
| magic = 0x5052494D |
| header = struct.pack('iiiii', magic, d_model, n_layers, vocab_size, lut_size) |
| header += b'\x00' * (256 - len(header)) |
| f.write(header) |
|
|
| |
| f.write(lut.numpy().astype('float32').tobytes()) |
|
|
| |
| f.write(sd['embedding.weight'].numpy().astype('float32').tobytes()) |
|
|
| |
| for i in range(n_layers): |
| prefix = f'layers.{i}.' |
| |
| |
| f.write(sd[f'{prefix}norm.weight'].numpy().astype('float32').tobytes()) |
| f.write(sd[f'{prefix}norm.bias'].numpy().astype('float32').tobytes()) |
| |
| |
| f.write(sd[f'{prefix}ssm.A_log'].numpy().astype('float32').tobytes()) |
| f.write(sd[f'{prefix}ssm.D'].numpy().astype('float32').tobytes()) |
| |
| |
| base = sd[f'{prefix}ssm.in_proj.base_idx'].to(torch.int32) |
| fine = sd[f'{prefix}ssm.in_proj.fine_idx'].to(torch.int32) |
| combined = (base * 256 + fine).to(torch.int16) |
| f.write(combined.numpy().tobytes()) |
| |
| |
| f.write(sd[f'{prefix}ssm.conv1d.weight'].numpy().astype('float32').tobytes()) |
| f.write(sd[f'{prefix}ssm.conv1d.bias'].numpy().astype('float32').tobytes()) |
| |
| |
| f.write(sd[f'{prefix}ssm.x_proj.weight'].numpy().astype('float32').tobytes()) |
| |
| |
| f.write(sd[f'{prefix}ssm.dt_proj.weight'].numpy().astype('float32').tobytes()) |
| f.write(sd[f'{prefix}ssm.dt_proj.bias'].numpy().astype('float32').tobytes()) |
| |
| |
| base_out = sd[f'{prefix}ssm.out_proj.base_idx'].to(torch.int32) |
| fine_out = sd[f'{prefix}ssm.out_proj.fine_idx'].to(torch.int32) |
| combined_out = (base_out * 256 + fine_out).to(torch.int16) |
| f.write(combined_out.numpy().tobytes()) |
|
|
| |
| f.write(sd['norm_f.weight'].numpy().astype('float32').tobytes()) |
| f.write(sd['norm_f.bias'].numpy().astype('float32').tobytes()) |
| f.write(sd['lm_head.weight'].numpy().astype('float32').tobytes()) |
|
|
| size_mb = os.path.getsize(out_path) / (1024 * 1024) |
| print(f"Export complete. Size: {size_mb:.2f} MB") |
|
|
| if __name__ == '__main__': |
| main() |
|
|