| # Hy-MT2-7B 在 cccc 上的可行性分析 | |
| ## 模型概述 | |
| | 属性 | 值 | | |
| |------|-----| | |
| | 来源 | https://huggingface.co/tencent/Hy-MT2-7B | | |
| | 架构 | `hunyuan_v1_dense` (HunYuanDenseV1ForCausalLM) | | |
| | 用途 | 多语言翻译模型(36种语言,支持指令翻译) | | |
| | 大小 | 7B 参数,BF16 约 16 GB,FP16 同等 | | |
| | 权重文件 | 4 × safetensors(共 ~16 GB),另有 FP8/GGUF 版本 | | |
| --- | |
| ## 架构参数对比 | |
| | 参数 | Qwen3-8B(已支持) | Hy-MT2-7B(待支持) | | |
| |------|-------------------|---------------------| | |
| | `num_hidden_layers` | 36 | **32** | | |
| | `hidden_size` (D) | 4096 | 4096 | | |
| | `intermediate_size` (I) | 12288 | **14336** | | |
| | `num_attention_heads` (H) | 32 | 32 | | |
| | `num_key_value_heads` (Hkv) | 8 | 8 | | |
| | `head_dim` (hd) | 128 | 128 | | |
| | `vocab_size` (V) | 151936 | **128167** | | |
| | `rope_theta` | 1,000,000 | **10,000** | | |
| | `rope_scaling` | 无 | dynamic YaRN (factor=1.0) | | |
| | `hidden_act` | silu | silu | | |
| | `norm_type` | rms | rms | | |
| | QK 归一化 (query/key_layernorm) | ✅ | ✅ | | |
| | `tie_word_embeddings` | ❌ | **✅ (lm_head = embed)** | | |
| --- | |
| ## cccc 算子支持情况 | |
| | 功能 | cccc 算子 | 支持状态 | | |
| |------|-----------|---------| | |
| | Token Embedding | `embed` | ✅ | | |
| | RMSNorm | `rmsNorm` | ✅ | | |
| | QK Norm | `rmsNorm`(作用于 Q/K) | ✅ | | |
| | Q/K/V/O 线性投影 | `batchedMul` | ✅ | | |
| | GQA(K/V 头复制) | `tile` + `reshapeBatch` | ✅ | | |
| | RoPE 位置编码 | `rope`, `ropeCosTbl`, `ropeSinTbl` | ✅ | | |
| | KV 缓存 | `kvcache` | ✅ | | |
| | Scaled Dot-Product Attention | `attention` | ✅ | | |
| | SwiGLU FFN | `silu` + `elementMul` + `batchedMul` | ✅ | | |
| | Tied Embeddings (lm_head=embed) | 同一 `MatrixWithName` 复用 | ✅(见 ini) | | |
| **结论:架构层面 cccc 完全兼容 Hy-MT2-7B,无需新增算子。** | |
| --- | |
| ## 需要适配的部分 | |
| ### 1. 新建 ini 配置(简单,已提供模板) | |
| - 修改层数 32、FFN 维度 14336、词表 128167、rope_theta 10000.0 | |
| - W_lm_head 复用 W_emb(tied embeddings) | |
| ### 2. 权重转换(Python 脚本,已提供 `convert_weights.py`) | |
| - 从 HuggingFace safetensors 下载权重 | |
| - 转置并重命名矩阵 → cccc 的 `named_weights` 格式 | |
| - 保存为 `INIReaderBin` 格式的 `.bin` 文件 | |
| **权重名称映射(HF → cccc):** | |
| | HuggingFace 名称 | cccc 名称 | | |
| |-----------------|----------| | |
| | `model.embed_tokens.weight` [V,D] → 转置 | `W_emb` [D,V] | | |
| | `lm_head.weight` [V,D] → 转置(与 embed 相同) | `W_lm_head` [D,V] | | |
| | `model.norm.weight` | `W_rms_final` | | |
| | `model.layers.{i}.input_layernorm.weight` | `W_rms_attn_{i}` | | |
| | `model.layers.{i}.self_attn.q_proj.weight` [Dq,D] → 转置 | `W_q_{i}` [D,Dq] | | |
| | `model.layers.{i}.self_attn.k_proj.weight` [Dkv,D] → 转置 | `W_k_{i}` [D,Dkv] | | |
| | `model.layers.{i}.self_attn.v_proj.weight` [Dkv,D] → 转置 | `W_v_{i}` [D,Dkv] | | |
| | `model.layers.{i}.self_attn.o_proj.weight` [D,D] → 转置 | `W_o_{i}` [D,D] | | |
| | `model.layers.{i}.self_attn.query_layernorm.weight` | `W_qnorm_{i}` | | |
| | `model.layers.{i}.self_attn.key_layernorm.weight` | `W_knorm_{i}` | | |
| | `model.layers.{i}.post_attention_layernorm.weight` | `W_rms_ffn_{i}` | | |
| | `model.layers.{i}.mlp.gate_proj.weight` [I,D] → 转置 | `W_gate_{i}` [D,I] | | |
| | `model.layers.{i}.mlp.up_proj.weight` [I,D] → 转置 | `W_up_{i}` [D,I] | | |
| | `model.layers.{i}.mlp.down_proj.weight` [D,I] → 转置 | `W_down_{i}` [I,D] | | |
| ### 3. cccc-llm.cpp 适配(需修改 C++ 代码) | |
| 这是**唯一需要改 C++ 的地方**,涉及两处硬编码: | |
| #### 3a. EOS token 硬编码(`run_generate` 函数) | |
| ```cpp | |
| // 当前(Qwen3 硬编码): | |
| const int EOS_IM_END = 151645; | |
| const int EOS_EOT = 151643; | |
| // Hy-MT2 需要: | |
| const int EOS = 127960; // <|eos|> | |
| ``` | |
| #### 3b. 对话格式(`make_turn` + `llm_init`) | |
| **Hy-MT2 Chat Template(来自 chat_template.jinja):** | |
| ``` | |
| System: <|startoftext|>{content}<|extra_4|> | |
| User(1st): {content}<|extra_0|> ← 首条 user(system 后) | |
| User(nth): <|startoftext|>{content}<|extra_0|> | |
| Assistant: {content}<|eos|> ← 无 start marker,直接输出 | |
| ``` | |
| **当前 cccc 格式(ChatML):** | |
| ``` | |
| <|im_start|>system\n{content}<|im_end|>\n | |
| <|im_start|>user\n{content}<|im_end|>\n | |
| <|im_start|>assistant\n | |
| ``` | |
| 需修改 `make_turn`、`asst_header`、`im_end_nl` 的构造逻辑。 | |
| > 建议:在 `[llm]` section 里增加 `chat_format=` 参数支持不同格式,避免每次改 C++ 代码。 | |
| --- | |
| ## RoPE Scaling 说明 | |
| Hy-MT2-7B 的 `rope_scaling.type = "dynamic"`, `factor = 1.0`。 | |
| - **factor=1.0 时**:YaRN/dynamic NTK 缩放因子为 1,与普通 RoPE 等效 | |
| - **对于 ≤1024 token 的上下文**:用标准 RoPE(theta=10000)完全没有精度损失 | |
| - **如需超长上下文(>32k)**:才需实现 dynamic/YaRN 频率插值 | |
| 当前 cccc 的 `ropeCosTbl/ropeSinTbl` 使用标准 RoPE,对翻译任务(通常几百 token)完全够用。 | |
| --- | |
| ## 实施路线图 | |
| ``` | |
| 步骤 1:下载权重 | |
| huggingface-cli download tencent/Hy-MT2-7B --local-dir ./Hy-MT2-weights | |
| (或直接下载 GGUF 版 Hy-MT2-7B.gguf 用 llama.cpp 验证先) | |
| 步骤 2:运行转换脚本 | |
| python convert_weights.py \ | |
| --hf_dir ./Hy-MT2-weights \ | |
| --output hy_mt2_7b_fp16_cccc.bin | |
| 步骤 3:复制 tokenizer.json | |
| cp ./Hy-MT2-weights/tokenizer.json . | |
| 步骤 4:修改 cccc-llm.cpp(EOS tokens + chat format) | |
| → 详见 analysis.md §3 | |
| 步骤 5:重编 cccc-llm.dll,加载 hy_mt2_7b_fp16.ini 测试 | |
| ``` | |
| --- | |
| ## 预估难度 | |
| | 工作项 | 难度 | 工时估算 | | |
| |--------|------|----------| | |
| | 写 ini 配置 | 低(复制 qwen3 改参数)| 已完成 | | |
| | 权重转换脚本 | 低(已提供) | 已完成 | | |
| | cccc-llm.cpp EOS 修改 | 低(改 2 个常量)| 0.5h | | |
| | cccc-llm.cpp 格式修改 | 中(改对话拼接逻辑)| 1-2h | | |
| | 下载权重 + 验证运行 | 低 | 依网速 | | |