| import os |
| import tempfile |
| from typing import Callable, Optional |
|
|
| from transformers import ( |
| AutoConfig, |
| CLIPVisionConfig, |
| GPT2Config, |
| GPT2LMHeadModel, |
| GraniteConfig, |
| GraniteForCausalLM, |
| LlamaConfig, |
| LlamaForCausalLM, |
| LlavaConfig, |
| LlavaForConditionalGeneration, |
| ) |
|
|
| from mergekit.architecture import ( |
| arch_info_for_config, |
| get_architecture_info, |
| ) |
| from mergekit.config import MergeConfiguration |
| from mergekit.io.lazy_tensor_loader import LazyTensorLoader, ShardedTensorIndex |
| from mergekit.merge import MergeOptions, run_merge |
|
|
|
|
| def run_and_check_merge( |
| config: MergeConfiguration, |
| check_nan: bool = True, |
| check_tensors: bool = True, |
| validate: Optional[Callable[[str], None]] = None, |
| index_json_name: Optional[str] = None, |
| auto_arch: bool = False, |
| ): |
| if index_json_name is None: |
| index_json_name = "model.safetensors.index.json" |
|
|
| with tempfile.TemporaryDirectory() as tmpdir: |
| run_merge(config, out_path=tmpdir, options=MergeOptions()) |
| index_path = os.path.join(tmpdir, index_json_name) |
| index_exists = os.path.exists(index_path) |
| single_shard_exists = os.path.exists(index_path.replace(".index.json", "")) |
| assert index_exists or single_shard_exists, "No model produced by merge" |
| assert os.path.exists( |
| os.path.join(tmpdir, "config.json") |
| ), "No config json produced by merge" |
|
|
| if check_nan: |
| |
| loader = LazyTensorLoader.from_disk(tmpdir, lazy_unpickle=False) |
| tp = loader.index.tensor_paths |
| sorted_tensors = sorted(tp.keys(), key=lambda k: tp[k]) |
| for tensor_name in sorted_tensors: |
| tensor = loader.get_tensor(tensor_name) |
| has_nan = tensor.view(-1).isnan().any() |
| assert not has_nan, "Output contains NaN" |
|
|
| if check_tensors: |
| model_config = AutoConfig.from_pretrained(tmpdir) |
| if auto_arch: |
| arch_info = get_architecture_info(config, MergeOptions()) |
| else: |
| arch_info = arch_info_for_config(model_config) |
|
|
| index = ShardedTensorIndex.from_disk(tmpdir) |
| for weight_info in arch_info.all_weights(model_config): |
| if weight_info.optional: |
| continue |
| if weight_info.name not in index.tensor_paths and not any( |
| a in index.tensor_paths for a in weight_info.aliases |
| ): |
| raise RuntimeError(f"Output missing tensor {weight_info.name}") |
|
|
| if validate: |
| validate(tmpdir) |
|
|
|
|
| def make_picollama(path: str, vocab_size: int = 64): |
| cfg = LlamaConfig( |
| vocab_size=vocab_size, |
| hidden_size=32, |
| intermediate_size=48, |
| num_attention_heads=16, |
| num_hidden_layers=2, |
| ) |
| model = LlamaForCausalLM(cfg) |
| model.save_pretrained(path, safe_serialization=True) |
| return str(path) |
|
|
|
|
| def make_picogranite(path: str, vocab_size: int = 64): |
| cfg = GraniteConfig( |
| vocab_size=vocab_size, |
| hidden_size=32, |
| intermediate_size=48, |
| num_attention_heads=2, |
| num_key_value_heads=2, |
| num_hidden_layers=2, |
| ) |
| model = GraniteForCausalLM(cfg) |
| model.save_pretrained(path, safe_serialization=True) |
| return str(path) |
|
|
|
|
| def make_gpt2size(path: str): |
| cfg = GPT2Config( |
| n_ctx=1024, |
| n_embd=768, |
| n_head=12, |
| n_layer=12, |
| n_positions=1024, |
| vocab_size=50257, |
| ) |
| model = GPT2LMHeadModel(cfg) |
| model.save_pretrained(path, safe_serialization=True) |
| return str(path) |
|
|
|
|
| def make_picoLlaVa(path: str): |
| |
| vision_config = CLIPVisionConfig( |
| image_size=32, |
| patch_size=4, |
| num_hidden_layers=2, |
| num_attention_heads=2, |
| hidden_size=64, |
| intermediate_size=128, |
| ) |
|
|
| |
| text_config = LlamaConfig( |
| vocab_size=64, |
| hidden_size=32, |
| intermediate_size=48, |
| num_attention_heads=16, |
| num_hidden_layers=2, |
| ) |
|
|
| |
| llava_config = LlavaConfig( |
| vision_config=vision_config, |
| text_config=text_config, |
| image_seq_length=16, |
| ) |
|
|
| |
| model = LlavaForConditionalGeneration(config=llava_config) |
| model.save_pretrained(path, safe_serialization=True) |
| return str(path) |
|
|