资讯动态

Phi-3.5-mini-instruct_rai_1.8.0_hybrid源码逐行精讲:RMSNorm、LongRoPE与注意力机制实现原理

发布时间:2026/10/17 2:29:09 来源:尧图企业网站定制
【免费下载链接】Phi-3.5-mini-instruct_rai_1.8.0_hybrid项目地址https://ai.gitcode.com/hf_mirrors/amd/Phi-3.5-mini-instruct_rai_1.8.0_hybrid点击查看免费下载本文对Phi-3.5-mini-instruct_rai_1.8.0_hybridAMD Ryzen AI 混合部署的 Phi-3.5 大语言模型进行源码逐行精讲用通俗的语言拆解RMSNorm 层归一化、LongRoPE 长上下文位置编码、多头注意力机制三大核心模块的实现原理并给出 config.json 关键参数速查表帮助新手快速读懂这个 ONNX 量化模型包是怎么跑起来的。 项目概览这是一个什么样的模型包Phi-3.5-mini-instruct_rai_1.8.0_hybrid 是 AMD 基于微软 Phi-3.5-mini-instruct 模型使用Quark 量化工具AWQ / 分组 128 / 非对称 / UINT4 权重 / BFP16 激活处理后得到的Ryzen AI 1.8.0 专用部署包。所谓hybrid混合体现在 genai_config.json 中ONNX Runtime GenAI 会话配置了RyzenAI执行器并设置了hybrid_opt_max_seq_length: 4096——即以4096 token 为分界点短序列走混合引擎优化路径长序列仍可支持到131072128K上下文。这与源码中 LongRoPE 的切换阈值见下文正好一致。核心文件一览表文件作用modeling_phi3.py模型结构源码RMSNorm、RoPE/LongRoPE、注意力、解码器层configuration_phi3.pyPhi3Config配置类含 LongRoPE 参数校验config.json架构超参数与 AWQ 量化配置genai_config.jsonONNX Runtime GenAI 推理与搜索参数rai_config.json各版本 Ryzen AI 允许的最大 prompt 长度model.onnx / model.onnx.dataONNX 计算图与外部权重数据model.pb.binRyzenAI 引擎引用的外部权重文件tokenizer.json / chat_template.jinja分词器与对话模板sample_finetune.py基于 SFTTrainer 的微调示例脚本 快速上手获取模型包在本地克隆仓库即可得到完整模型包git clone https://gitcode.com/hf_mirrors/amd/Phi-3.5-mini-instruct_rai_1.8.0_hybrid配合支持 Ryzen AI 的 ONNX Runtime 环境加载 model.onnx 即可推理量化配置见 config.json 的quantization_config。下面进入源码本体。 源码地图三大核心机制都在哪modeling_phi3.py 共 1500 多行按数据流可以这样看input_ids → embed_tokens → 32 × [RMSNorm → 注意力(RoPE) → 残差 → RMSNorm → MLP(SwiGLU) → 残差] → final RMSNorm → lm_head → logits机制类 / 函数位置RMSNormPhi3RMSNormmodeling_phi3.py#L81-L95标准 RoPEPhi3RotaryEmbeddingmodeling_phi3.py#L112-L139LongRoPEPhi3LongRoPEScaledRotaryEmbeddingmodeling_phi3.py#L142-L180多头注意力Phi3Attention等三个实现modeling_phi3.py#L251-L381解码器层组装Phi3DecoderLayermodeling_phi3.py#L791-L866 逐行精讲一RMSNorm 层归一化实现原理Phi-3.5 没有使用传统 LayerNorm不减均值、不用 Layer 里的 gamma/beta 双参数而是RMSNorm——只用均方根来缩放激活值计算量更小、推理更快。核心就 3 行modeling_phi3.py#L90-L95hidden_states hidden_states.to(torch.float32) # ① 提升到 fp32 防精度损失 variance hidden_states.pow(2).mean(-1, keepdimTrue) # ② 平方后取均值平方均值 hidden_states hidden_states * torch.rsqrt(variance self.variance_epsilon) # ③ 除以均方根 return self.weight * hidden_states.to(input_dtype) # ④ 乘可学习缩放系数 weight逐行理解① 先转 fp32归一化在低精度下容易累积误差先升精度、算完再转回去是 LLM 里的通用手法。②pow(2).mean(-1)对最后一个维度隐层维度求平方均值这就是 RMS均方根的平方不需要像 LayerNorm 那样先减均值。③rsqrt(variance eps)乘以均方根的倒数等价于除以 RMS。eps即variance_epsilon防止除零本项目取rms_norm_eps 1e-05见 config.json。④self.weight每个维度一个可学习的缩放系数初始化为全 1相当于 LayerNorm 的 gamma但没有 beta不减均值所以不需要偏置。它被用了几次每个解码器层里有两次注意力前 MLP 前全部 32 层结束后还有最后一次final normmodeling_phi3.py#L1138见 Phi3DecoderLayer。 逐行精讲二LongRoPE 长上下文位置编码实现原理RoPE 基础先搞懂 inv_freq 与旋转RoPE旋转位置编码通过给 Q、K 向量旋转一个与位置相关的角度来编码位置信息。基础版Phi3RotaryEmbedding的关键步骤modeling_phi3.py#L122-L139self.inv_freq 1.0 / (self.base ** (arange(0, dim, 2) / dim)) # 不同维度的旋转频率 freqs inv_freq_expanded position_ids_expanded # 频率 × 位置 角度 cos emb.cos(); sin emb.sin()拿到 cos/sin 后用rotate_halfmodeling_phi3.py#L184-L188把向量切成前后两半再旋转x1 x[..., : x.shape[-1] // 2] x2 x[..., x.shape[-1] // 2 :] return torch.cat((-x2, x1), dim-1)最后apply_rotary_pos_emb一句q * cos rotate_half(q) * sin就完成了对 Q 和 K 的旋转modeling_phi3.py#L192-L216。注意V 不旋转只有 Q、K 需要位置信息。LongRoPE4096 是分水岭长短序列用两套系数Phi-3.5 支持 128K 上下文但原始训练长度只有4096original_max_position_embeddings。直接外推会幻觉LongRoPE 的解法是给每个频率维度单独乘一个扩展系数且短/长序列各一套if seq_len self.original_max_position_embeddings: # 超过 4096 → 长序列模式 ext_factors torch.tensor(self.long_factor, ...) else: # 4096 以内 → 短序列模式 ext_factors torch.tensor(self.short_factor, ...) self.inv_freq 1.0 / (ext_factors * self.base ** inv_freq_shape)modeling_phi3.py#L151-L159这两个系数表就在 config.json 的rope_scaling里各48 个数值——因为hidden_size 3072 ÷ 32 头 96个头维度再除以 2 就是 48。规律很直观短序列系数从 1.0 缓慢涨到约 2.8长序列系数则一路涨到64把低频维度压慢旋转从而容纳更长序列。另外源码还做了一个注意力 logits 校准modeling_phi3.py#L172-L179外推时给 cos/sin 乘一个scaling_factor基于 131072/4096 的对数比值开根号缓解长序列下注意力分布变平的问题。还有一个容易被忽略的巧思Phi3ForCausalLM.prepare_inputs_for_generationmodeling_phi3.py#L1285-L1293会在刚越过 4096 那个 token 时主动丢弃 KV Cache 重算一次——因为跨越分界点意味着全部换用 long_factor旧缓存的 K 值旋转角度已不匹配。宁可慢一个 token也要保证长上下文正确这是逐行读源码才能看到的工程细节。⚡ 逐行精讲三Phi3Attention 多头注意力实现融合 QKV 投影与多头切分Phi-3 把 Q、K、V 三个线性层合并成一个qkv_proj一次矩阵乘法后按列切片modeling_phi3.py#L313-L323qkv self.qkv_proj(hidden_states) query_states qkv[..., :query_pos] # 前段 → Q key_states qkv[..., query_pos : query_pos kv_dim] # 中段 → K value_states qkv[..., query_pos kv_dim :] # 尾段 → V融合后对 GPU/NPU 更友好减少 kernel 启动次数。切完再view transpose成多头形状(batch, heads, seq_len, head_dim)。缩放点积注意力 KV Cache注意力核心modeling_phi3.py#L346-L365attn_weights torch.matmul(query_states, key_states.transpose(2, 3)) / math.sqrt(self.head_dim) attn_weights softmax(attn_weights, dim-1, dtypetorch.float32) # 升精度 softmax attn_output torch.matmul(attn_weights, value_states)除以 √head_dim防止点积值过大导致 softmax 梯度消失经典缩放。softmax 升 fp32与 RMSNorm 同理精度敏感操作先升精度。KV Cache自回归生成时上一步的 K、V 通过past_key_value.update(...)缓存复用modeling_phi3.py#L338-L340避免重复计算历史 token——这也是 genai_config.json 里past_key_values输入输出的来源。GQA 支持repeat_kvmodeling_phi3.py#L239-L248用于 KV 头少于 Q 头时的复制扩展本项目num_key_value_heads 32 num_attention_heads实际走的是标准 MHA但代码保留了 GQA 能力。三种注意力实现一套权重源码用字典注册了三种前向实现modeling_phi3.py#L784-L788实现类特点eagerPhi3Attention手工 matmul可输出注意力权重便于调试flash_attention_2Phi3FlashAttention2IO 感知的快速实现支持滑窗注意力sdpaPhi3SdpaAttentionPyTorch 原生scaled_dot_product_attention三者权重结构完全相同继承自Phi3Attention只是前向算法不同加载模型时按attn_implementation参数选择。 组装Phi3DecoderLayer 的完整数据流一层解码器 两次 RMSNorm 注意力 MLP 两条残差modeling_phi3.py#L837-L856residual hidden_states hidden_states self.input_layernorm(hidden_states) # RMSNorm ① attn_outputs self.self_attn(hidden_states, ...) hidden_states residual self.resid_attn_dropout(attn_outputs) # 残差连接 residual hidden_states hidden_states self.post_attention_layernorm(hidden_states) # RMSNorm ② hidden_states self.mlp(hidden_states) # SwiGLU 前馈 hidden_states residual self.resid_mlp_dropout(hidden_states) # 残差连接这是标准的Pre-Norm 残差结构归一化放在子层之前残差主干保持原始信号不被稀释训练稳定。MLP 部分Phi3MLPmodeling_phi3.py#L219-L235用的是SwiGLU激活gate_up_proj一次算出 gate 和 up 两路up * silu(gate)相乘后经down_proj降回 3072 维。32 层堆叠nn.ModuleListmodeling_phi3.py#L1003-L1005→ final RMSNorm →lm_head线性层把 3072 维映射到 32064 词表 logitsmodeling_phi3.py#L1256-L1257。 config.json 关键参数速查表参数值含义hidden_size3072隐层维度RMSNorm 的 weight 长度num_hidden_layers32解码器层数num_attention_heads/num_key_value_heads32 / 32头数每头 96 维intermediate_size8192MLP 中间维度SwiGLUmax_position_embeddings131072最大支持上下文128Koriginal_max_position_embeddings4096LongRoPE 长短系数切换点rope_scaling.typelongrope位置编码扩展策略系数校验见 configuration_phi3.py#L189-L227rms_norm_eps1e-05RMSNorm 的数值稳定项sliding_window262144滑窗注意力窗口大于 128K实际不裁剪quantization_configquark / awq / uint4 / group 128AWQ 4-bit 量化配置config.json#L27-L106❓ 常见问题解答Q1为什么同时有 model.onnx、model.onnx.data 和 model.pb.binmodel.onnx是计算图不含大权重model.onnx.data是 ONNX 外部权重model.pb.bin是 RyzenAI 执行引擎的外部权重文件由 genai_config.json 的external_data_file指定。这种图与数据分离是 ONNX 部署的常规做法方便按引擎各自加载。Q2上下文 128K为什么 rai_config 里 prompt 只给 4096rai_config.json 按 Ryzen AI 版本区分最大 prompt 长度1.5.x 为 20481.6.0 及以上为 4096。结合hybrid_opt_max_seq_length: 4096与 LongRoPE 的 4096 切换点可以看出设计思路prompt 控制在 4096 内走最优混合路径超长输出由 LongRoPE 的 long_factor 平滑外推到 128K。Q3能直接微调这个包吗本包是 UINT4 量化的部署产物不建议直接微调。仓库提供了 sample_finetune.pySFTTrainer LoRA DeepSpeed ZeRO-3 的完整示例微调应基于原始模型权重完成后再走量化导出流程。写在最后读懂 modeling_phi3.py 这条主线——RMSNorm 负责稳定数值、LongRoPE 负责记住位置、注意力负责融合信息、残差连接负责保送信号——基本就掌握了绝大多数现代 LLM 的骨架。Phi-3.5 的特别之处在于把 128K 长上下文、融合 QKV、三种注意力实现和 AWQ 量化都压缩进了同一个代码库里是非常好的学习样本。赞分享【免费下载链接】Phi-3.5-mini-instruct_rai_1.8.0_hybrid项目地址https://ai.gitcode.com/hf_mirrors/amd/Phi-3.5-mini-instruct_rai_1.8.0_hybrid点击查看免费下载相关推荐从开发机到生产环境Phi-3.5-mini-instruct_rai_1.8.0_hybrid部署分步实战指南从开发机到生产环境Phi 3.5 mini instruct_rai_1.8.0_hybrid部署分步实战指南 Phi 3.5 mini instruct_rNYU-DLSP20 第12讲三注意力机制与 Transformer 从原理到 PyTorch 实现NYU DLSP20 第12讲三注意力机制与 Transformer 从原理到 PyTorch 实现 本文是 NYU DLSP20NYU Deep Le示例工程DeepSeek-VL注意力机制跨模态注意力实现原理DeepSeek VL注意力机制跨模态注意力实现原理 引言多模态融合的技术挑战 在人工智能领域视觉 语言模型Vision Language Models人工智能大模型多模态计算机视觉NLPDeepSeek上一篇OmniRoute MCP Server 实战指南把 AI 网关的路由、配额与成本能力暴露给 Agent下一篇Sim 前端工程规范让列表与菜单自己排序——Sim 的 List Menu Ordering 设计规则与源码实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑