Buckets:
| #!/usr/bin/env python3 | |
| """ | |
| LMH2 → LMH1 转换器 / LMH1 生成器 | |
| 模式1 (有lm_head.nfv1): 从 C++ LMH2 提取 w_embed/w_proj,新建 bridge | |
| 模式2 (无lm_head.nfv1): 从 model.nfv1 读取维度,全部 xavier 初始化 | |
| LMH1 张量: bridge.weight, bridge.bias, w_proj.weight, w_proj.bias, w_embed | |
| 用法: | |
| # 模式1: 从LMH2转换 | |
| python3 scripts/lmh2_to_lmh1.py \ | |
| --nf-model output/model.nfv1 \ | |
| --lmh2 output/lm_head.nfv1 \ | |
| --output lm_head_lmh1.nfv1 | |
| # 模式2: 从model.nfv1直接生成 (无需lm_head) | |
| python3 scripts/lmh2_to_lmh1.py \ | |
| --nf-model output/model.nfv1 \ | |
| --vocab-size 128000 \ | |
| --d-model 512 \ | |
| --output lm_head_lmh1.nfv1 | |
| """ | |
| import argparse, struct, sys, os | |
| import numpy as np | |
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | |
| from infer_full import load_nfv1, load_lmh1 | |
| def load_lmh2(path): | |
| weights = {} | |
| with open(path, 'rb') as f: | |
| magic = f.read(4) | |
| if magic not in (b'LMH2', b'LMH1'): | |
| raise ValueError(f"Bad magic: {magic} (expected LMH2 or LMH1)") | |
| while True: | |
| nl = struct.unpack('<I', f.read(4))[0] | |
| if nl == 0: | |
| break | |
| name = f.read(nl).decode('utf-8', errors='replace') | |
| ndim = struct.unpack('<I', f.read(4))[0] | |
| shape = tuple(struct.unpack('<I', f.read(4))[0] for _ in range(ndim)) | |
| dsize = struct.unpack('<I', f.read(4))[0] | |
| arr = np.frombuffer(f.read(dsize), dtype=np.float32).reshape(shape).copy() | |
| weights[name] = arr | |
| return weights, magic.decode('utf-8') | |
| def save_lmh1(path, weights): | |
| with open(path, 'wb') as f: | |
| f.write(b'LMH1') | |
| for name, arr in weights.items(): | |
| name_bytes = name.encode('utf-8') | |
| f.write(struct.pack('<I', len(name_bytes))) | |
| f.write(name_bytes) | |
| f.write(struct.pack('<I', len(arr.shape))) | |
| for d in arr.shape: | |
| f.write(struct.pack('<I', d)) | |
| data = arr.astype(np.float32).tobytes() | |
| f.write(struct.pack('<I', len(data))) | |
| f.write(data) | |
| f.write(struct.pack('<I', 0)) | |
| def xavier_uniform(shape, rng): | |
| fan_in = shape[1] if len(shape) == 2 else shape[0] | |
| fan_out = shape[0] if len(shape) == 2 else 1 | |
| limit = np.sqrt(6.0 / (fan_in + fan_out)) | |
| return rng.uniform(-limit, limit, size=shape).astype(np.float32) | |
| def main(): | |
| parser = argparse.ArgumentParser(description='LMH2 → LMH1 converter / LMH1 generator') | |
| parser.add_argument('--nf-model', required=True, help='NF 模型文件 (用于获取 hidden_dim)') | |
| parser.add_argument('--lmh2', default='', help='C++ LMH2 格式 LM head 文件 (可选)') | |
| parser.add_argument('--output', required=True, help='输出 LMH1 文件路径') | |
| parser.add_argument('--vocab-size', type=int, default=128000, help='词表大小 (模式2需要)') | |
| parser.add_argument('--d-model', type=int, default=0, help='LM d_model (0=从NF模型推断)') | |
| parser.add_argument('--seed', type=int, default=42, help='随机种子') | |
| args = parser.parse_args() | |
| nf_w = load_nfv1(args.nf_model) | |
| hidden_dim = nf_w['input_proj.weight'].shape[0] | |
| print(f"NF hidden_dim: {hidden_dim}") | |
| rng = np.random.RandomState(args.seed) | |
| lmh1_w = {} | |
| if args.lmh2 and os.path.exists(args.lmh2): | |
| lmh2_w, fmt = load_lmh2(args.lmh2) | |
| print(f"模式1: 从 {args.lmh2} 转换 (格式: {fmt}, {len(lmh2_w)} 个张量)") | |
| if fmt == 'LMH1': | |
| print("已经是 LMH1 格式,直接复制") | |
| import shutil | |
| shutil.copy2(args.lmh2, args.output) | |
| print(f"输出: {args.output}") | |
| return | |
| vocab_size, d_model = lmh2_w['w_embed'].shape | |
| print(f"vocab_size: {vocab_size}, d_model: {d_model}") | |
| lmh1_w['w_embed'] = lmh2_w['w_embed'] | |
| print(f" w_embed: {lmh1_w['w_embed'].shape} (from LMH2)") | |
| if 'w_proj.weight' in lmh2_w: | |
| lmh1_w['w_proj.weight'] = lmh2_w['w_proj.weight'] | |
| lmh1_w['w_proj.bias'] = lmh2_w['w_proj.bias'] | |
| print(f" w_proj.weight: {lmh1_w['w_proj.weight'].shape} (from LMH2)") | |
| print(f" w_proj.bias: {lmh1_w['w_proj.bias'].shape} (from LMH2)") | |
| else: | |
| lmh1_w['w_proj.weight'] = xavier_uniform((d_model, d_model), rng) | |
| lmh1_w['w_proj.bias'] = np.zeros(d_model, dtype=np.float32) | |
| print(f" w_proj.weight: {lmh1_w['w_proj.weight'].shape} (xavier init)") | |
| print(f" w_proj.bias: {lmh1_w['w_proj.bias'].shape}") | |
| else: | |
| if args.lmh2: | |
| print(f"警告: --lmh2 文件不存在: {args.lmh2}") | |
| print(f"模式2: 从 model.nfv1 生成全新 LMH1") | |
| d_model = args.d_model | |
| if d_model == 0: | |
| d_model = int(nf_w['output_fusion.up.weight'].shape[0]) | |
| print(f" d_model 从NF模型推断: {d_model}") | |
| vocab_size = args.vocab_size | |
| print(f"vocab_size: {vocab_size}, d_model: {d_model}") | |
| lmh1_w['w_embed'] = xavier_uniform((vocab_size, d_model), rng) | |
| print(f" w_embed: {lmh1_w['w_embed'].shape} (xavier init)") | |
| lmh1_w['w_proj.weight'] = xavier_uniform((d_model, d_model), rng) | |
| lmh1_w['w_proj.bias'] = np.zeros(d_model, dtype=np.float32) | |
| print(f" w_proj.weight: {lmh1_w['w_proj.weight'].shape} (xavier init)") | |
| print(f" w_proj.bias: {lmh1_w['w_proj.bias'].shape}") | |
| lmh1_w['bridge.weight'] = xavier_uniform((d_model, hidden_dim), rng) | |
| lmh1_w['bridge.bias'] = np.zeros(d_model, dtype=np.float32) | |
| print(f" bridge.weight: {lmh1_w['bridge.weight'].shape} (xavier init)") | |
| print(f" bridge.bias: {lmh1_w['bridge.bias'].shape}") | |
| out_dir = os.path.dirname(os.path.abspath(args.output)) | |
| if out_dir: | |
| os.makedirs(out_dir, exist_ok=True) | |
| save_lmh1(args.output, lmh1_w) | |
| print(f"\n输出: {args.output} (LMH1, {len(lmh1_w)} 个张量)") | |
| verify_w = load_lmh1(args.output) | |
| print(f"验证: {len(verify_w)} 个张量加载成功") | |
| for name in lmh1_w: | |
| if name in verify_w: | |
| match = np.allclose(lmh1_w[name], verify_w[name]) | |
| print(f" {name}: {'OK' if match else 'MISMATCH'}") | |
| else: | |
| print(f" {name}: MISSING") | |
| if __name__ == '__main__': | |
| main() | |
Xet Storage Details
- Size:
- 6.48 kB
- Xet hash:
- 8327b93379e721355833d6c390cfd38f5d853c3ef6965b5788acc5ef8744975f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.