Prhub

#33671 [Bugfix] Treat unsharded model.safetensors as HF weights in Mistral-native format detection

原始 PR 作者 alexnails 合并时间 2026-08-05 16:54 文件变更 1 提交数 1 评论 0 代码增减 +6 / -3

执行摘要

修复未分片 HF 权重未被识别导致的 Mistral 加载崩溃

PR body 明确指出:Shieldstral-1.0-3B 和 Ministral-3-3B-Instruct-2512 仓库同时携带未分片 HF model.safetensors 与 Mistral-native consolidated.safetensors/params.json/tekken.json,而 _is_mistral_native_format() 仅按分片模式 model-*.safetensors 判定 'HF weights present',未分片单文件 checkpoint 不被识别,于是自动设置 load_format=mistral,加载器读取 Mistral-native 权重名,最终在 Mistral3ForConditionalGeneration.load_weights 中因找不到 layers.0.attention.wk.weight 或 layers.0.attention.k_fake_quantizer.qscale_act 而崩溃。

值得精读。改动虽小(1 文件 9 行),但位于权重加载格式自动检测的核心决策点,修复了 Mistral 双子模型开箱即崩的问题。值得关注的设计点:一是 AUTO 加载路径与 filter_duplicate_safetensors_files 去重配合,实现检测翻转后自动选择正确权重文件;二是 HF-API 分支用根目录限定避免子目录误判,保持与本地 glob 语义一致。若团队后续维护 Mistral 系新模型,建议为该检测逻辑补充单元测试,避免回归。

讨论亮点

该 PR 没有任何 inline 评论或线程讨论,reviewer JustinTong0323 直接给出 APPROVED 并附言 'LGTM'。关键设计权衡记录在 PR body 中:检测翻转只作用于「consolidated + 未分片根目录 model.safetensors」这一原先必崩的仓库类;native-only、分片双格式、mistral-large-3/mistral-small-4/leanstral 名称覆盖以及显式 --load-format mistral 的路径均不受影响。

实现拆解

  1. 定位检测入口:server_args.py 的 _is_mistral_native_format()(约 7328 行)通过 _check_format(has_params, has_consolidated, has_hf_weights) 决定是否强制 load_format=mistral;其设计意图是当同一 checkpoint 同时存在两种权重格式时优先 HF 路径。
  2. 本地目录分支:将 has_hf_weights 的 glob 匹配从 model-.safetensors 改为 model.safetensors,使未分片 model.safetensors 也能命中,从而让 _check_format 返回 False。
  3. HF-API 分支:将文件匹配从 startswith('model-') 放宽为 startswith('model'),并新增 '/' not in f 条件限定仓库根目录,与本地 glob 语义保持一致,避免子目录内同名 safetensors 误判为 HF 权重。
  4. 配套与验证:同步更新函数 docstring 中的模式描述;未新增自动化测试(checklist 未勾选测试项),改为在 4x H200 上对 Mistral 家族 8 个仓库做检测翻转矩阵验证;检测翻转后 AUTO 加载路径会同时 glob 两类文件,由既有的 filter_duplicate_safetensors_files 两文件去重逻辑优先选择 model.safetensors,保证权重名与 HF 架构匹配。
文件 模块 状态 重要度
python/sglang/srt/server_args.py 加载格式 modified 5.14

关键符号

_is_mistral_native_format _check_format

关键源码片段

python/sglang/srt/server_args.py core-logic

修改 _is_mistral_native_format() 的 HF 权重识别逻辑,是本次修复的核心;本地 glob 与 HF-API 两处匹配同时放宽并保持语义一致。

def _is_mistral_native_format(self) -> bool:
    """判断 checkpoint 是否必须使用 load_format=mistral。    只要检测到 HF 权重(model*.safetensors),就优先走 HF 加载路径,
    避免把 Mistral-native 命名的权重加载进 HF 命名架构。
    """
    _MISTRAL_NATIVE_PATTERNS = (
        'mistral-large-3',
        'mistral-small-4',
        'leanstral',
    )
    # 名称覆盖:这几类模型家族无论本地文件如何,只要存在 params.json 就按 native 处理
    name_matches = any(
        p in str(self.model_path).lower() for p in _MISTRAL_NATIVE_PATTERNS
    )
​
    def _check_format(has_params, has_consolidated, has_hf_weights) -> bool:
        # 家族名命中且存在 params.json 时,强制走 Mistral-native 加载
        if has_params and name_matches:
            return True
        # 其他情况:只有存在 consolidated 权重且没有 HF 权重时才返回 True,
        # 即“双格式仓库优先选 HF 路径”
        return has_consolidated and not has_hf_weights
​
    if os.path.isdir(self.model_path):
        # 本地目录分支用 glob 匹配 model*.safetensors,同时覆盖分片与未分片
        return _check_format(
            has_params=os.path.exists(os.path.join(self.model_path, 'params.json')),
            has_consolidated=bool(
                glob.glob(os.path.join(self.model_path, 'consolidated*.safetensors'))
            ),
            has_hf_weights=bool(
                glob.glob(os.path.join(self.model_path, 'model*.safetensors'))
            ),
        )
​
    try:
        from huggingface_hub import HfApi
​
        files = {s.rfilename for s in HfApi().model_info(self.model_path).siblings}
        return _check_format(
            has_params='params.json' in files,
            has_consolidated=any(
                f.startswith('consolidated') and f.endswith('.safetensors')
                for f in files
            ),
            has_hf_weights=any(
                f.startswith('model')
                and f.endswith('.safetensors')
                and '/' not in f # 只统计 repo 根目录的权重文件,子目录同名文件不参与判定
                for f in files
            ),
        )
    except Exception:
        # HfApi 查询失败(无网络或仓库不存在)时按非 native 处理,交由 AUTO 路径兜底
        return False

评论区精华

整体审阅 other

JustinTong0323 未提出任何代码评论,直接批准并附言 LGTM;PR 中的检测边界与根目录限定等设计决择在 PR body 与 docstring 中说明。

结论:无未解决疑虑,批准合并。 · 已解决

风险与影响

回归面:变更局限于 _is_mistral_native_format() 的匹配宽度,native-only 仓库 has_hf_weights 仍为 False,分片双格式仓库仍为 True,名称覆盖分支提前返回,因此只有原本崩溃的「未分片 HF + consolidated」组合发生行为翻转,回归风险低。
误判风险:startswith('model') + 根目录限定理论上可能将仓库根目录下其他以 model 开头、以 .safetensors 结尾的非权重文件误判为 HF 权重,实际概率很低;本地 glob 同样放宽,存在同类理论风险。
测试缺口:PR 未新增自动化测试,仅靠 4x H200 手动矩阵验证,后续 Mistral 新模型缺少针对该检测逻辑的回归保护,这是主要风险点。
已知无关问题:Mistral-Small-3.2-24B-Instruct-2506 缺少 HF preprocessor_config.json/tokenizer_config.json,在处理器初始化阶段即失败,与本次权重检测无关(PR body 已说明)。

对用户:Shieldstral-1.0-3B、Ministral-3-3B-Instruct-2512 等双格式未分片仓库可开箱加载,无需手动 --load-format 纠偏。对系统:仅影响 ServerArgs 加载格式自动判定,不触及推理、调度、KV 管理等运行时路径。对团队:为 Mistral3ForConditionalGeneration 类新模型铺平加载基础,配合 AUTO 加载与 filter_duplicate_safetensors_files 去重形成闭环;整体影响面中等偏小。

核心路径变更 缺少测试覆盖 匹配规则放宽

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论