""" Flint-1.2B: Convert JAX checkpoint to HuggingFace format Converts trained JAX parameters to a HuggingFace-compatible safetensors model. Usage: python convert_to_hf.py --checkpoint /kaggle/working/checkpoints/flint-1b/step_00005700 python convert_to_hf.py --checkpoint /path/to/checkpoint --push --repo tekkmaven/flint-1.2B """ import argparse import json import os from pathlib import Path import numpy as np import torch from safetensors.torch import save_file from transformers import LlamaConfig, LlamaForCausalLM, AutoTokenizer from huggingface_hub import HfApi def convert_jax_to_hf(checkpoint_path: str, output_dir: str = "./hf_model"): """Convert JAX checkpoint to HuggingFace LlamaForCausalLM format.""" print(f"[Convert] Loading JAX checkpoint from: {checkpoint_path}") # Load JAX checkpoint import orbax.checkpoint as ocp checkpointer = ocp.PyTreeCheckpointer() state = checkpointer.restore(checkpoint_path) params = state['params'] # Create HF config config = LlamaConfig( vocab_size=49216, hidden_size=2048, intermediate_size=5504, num_hidden_layers=22, num_attention_heads=32, num_key_value_heads=4, hidden_act="silu", max_position_embeddings=2048, rms_norm_eps=1e-5, rope_theta=500000.0, tie_word_embeddings=True, attention_bias=False, mlp_bias=False, torch_dtype="bfloat16", ) # Create output directory os.makedirs(output_dir, exist_ok=True) # Convert parameters print("[Convert] Mapping JAX parameters to HuggingFace format...") state_dict = {} # Embedding state_dict['model.embed_tokens.weight'] = torch.from_numpy( np.array(params['embed']) ).to(torch.bfloat16) # Transformer layers for i in range(22): layer = params['layers'][i] prefix = f'model.layers.{i}' # Attention state_dict[f'{prefix}.self_attn.q_proj.weight'] = torch.from_numpy( np.array(layer['wq']).T ).to(torch.bfloat16) state_dict[f'{prefix}.self_attn.k_proj.weight'] = torch.from_numpy( np.array(layer['wk']).T ).to(torch.bfloat16) state_dict[f'{prefix}.self_attn.v_proj.weight'] = torch.from_numpy( np.array(layer['wv']).T ).to(torch.bfloat16) state_dict[f'{prefix}.self_attn.o_proj.weight'] = torch.from_numpy( np.array(layer['wo']).T ).to(torch.bfloat16) # FFN (SwiGLU: gate_proj, up_proj, down_proj) state_dict[f'{prefix}.mlp.gate_proj.weight'] = torch.from_numpy( np.array(layer['w_gate']).T ).to(torch.bfloat16) state_dict[f'{prefix}.mlp.up_proj.weight'] = torch.from_numpy( np.array(layer['w_up']).T ).to(torch.bfloat16) state_dict[f'{prefix}.mlp.down_proj.weight'] = torch.from_numpy( np.array(layer['w_down']).T ).to(torch.bfloat16) # Norms state_dict[f'{prefix}.input_layernorm.weight'] = torch.from_numpy( np.array(layer['attn_norm']) ).to(torch.bfloat16) state_dict[f'{prefix}.post_attention_layernorm.weight'] = torch.from_numpy( np.array(layer['ffn_norm']) ).to(torch.bfloat16) # Final norm state_dict['model.norm.weight'] = torch.from_numpy( np.array(params['final_norm']) ).to(torch.bfloat16) # LM head (tied with embeddings) state_dict['lm_head.weight'] = state_dict['model.embed_tokens.weight'] # Save print(f"[Convert] Saving to {output_dir}") # Save config config.save_pretrained(output_dir) # Save model weights save_file(state_dict, os.path.join(output_dir, "model.safetensors")) # Save tokenizer tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/cosmo2-tokenizer") tokenizer.add_special_tokens({ "additional_special_tokens": [ "", "", "", "", "", "", "", "", "", "", "<|pad|>" ] }) tokenizer.pad_token = "<|pad|>" tokenizer.save_pretrained(output_dir) # Verify print("[Convert] Verifying model loads correctly...") model = LlamaForCausalLM.from_pretrained(output_dir, torch_dtype=torch.bfloat16) print(f"[Convert] ✓ Model loaded: {sum(p.numel() for p in model.parameters()):,} params") return output_dir def push_to_hub(model_dir: str, repo_id: str): """Push converted model to HuggingFace Hub.""" print(f"[Hub] Pushing to {repo_id}...") api = HfApi() api.upload_folder( folder_path=model_dir, repo_id=repo_id, repo_type="model", commit_message="Upload trained Flint-1.2B weights", ) print(f"[Hub] ✓ Pushed to https://huggingface.co/{repo_id}") if __name__ == "__main__": parser = argparse.ArgumentParser(description="Convert Flint JAX checkpoint to HF format") parser.add_argument("--checkpoint", type=str, required=True, help="Path to JAX checkpoint directory") parser.add_argument("--output", type=str, default="./hf_model", help="Output directory for HF model") parser.add_argument("--push", action="store_true", help="Push to HuggingFace Hub") parser.add_argument("--repo", type=str, default="tekkmaven/flint-1.2B", help="HF repo ID for pushing") args = parser.parse_args() output_dir = convert_jax_to_hf(args.checkpoint, args.output) if args.push: push_to_hub(output_dir, args.repo)