DeAIafdeling's picture
Add files using upload-large-folder tool
2bedc3e verified
Raw History Blame Contribute Delete
2.04 kB
# SPDX-FileCopyrightText: © 2025 Tenstorrent USA, Inc.
# SPDX-License-Identifier: Apache-2.0
import os
import torch
from transformers import AutoConfig
def load_hf_mixtral_config():
hf_model = os.getenv("HF_MODEL")
assert hf_model is not None, "Please set HF_MODEL to a HuggingFace name e.g. meta-llama/Llama-3.1-8B-Instruct"
config = AutoConfig.from_pretrained(hf_model, local_files_only=os.getenv("CI") == "true")
return config
def fuse_mixtral_experts(state_dict, num_experts, src_prefix, dst_prefix):
"""Convert per-expert w1/w2/w3 weights to the transformers 5.x fused MixtralExperts format.
transformers 5.x replaced the per-expert MixtralBlockSparseTop2MLP modules with a single fused
``MixtralExperts`` module whose weights are applied via ``F.linear`` (same orientation as the old
per-expert ``nn.Linear`` weights):
* ``{dst_prefix}.gate_up_proj``: (num_experts, 2*intermediate, hidden) = cat([w1, w3], dim=0)
per expert (gate first, up second; split via ``chunk(2, dim=-1)`` in the forward).
* ``{dst_prefix}.down_proj``: (num_experts, hidden, intermediate) = w2 per expert.
``src_prefix`` is where the per-expert weights live (e.g. ``experts`` for a standalone
MixtralSparseMoeBlock, ``block_sparse_moe.experts`` inside a decoder layer). The matching
per-expert source keys are consumed; all other keys pass through unchanged.
"""
consumed = set()
gate_up, down = [], []
for e in range(num_experts):
w1 = state_dict[f"{src_prefix}.{e}.w1.weight"]
w2 = state_dict[f"{src_prefix}.{e}.w2.weight"]
w3 = state_dict[f"{src_prefix}.{e}.w3.weight"]
gate_up.append(torch.cat([w1, w3], dim=0))
down.append(w2)
consumed.update(f"{src_prefix}.{e}.w{i}.weight" for i in (1, 2, 3))
out = {k: v for k, v in state_dict.items() if k not in consumed}
out[f"{dst_prefix}.gate_up_proj"] = torch.stack(gate_up, dim=0)
out[f"{dst_prefix}.down_proj"] = torch.stack(down, dim=0)
return out