Prhub

#39155 [BugFix] HFValidationError with cloud storage URIs when HF_HUB_OFFLINE=1

原始 PR 作者 sts07142 合并时间 2026-05-27 23:53 文件变更 4 提交数 6 评论 3 代码增减 +63 / -10

执行摘要

修复云存储 URI 在 HF_HUB_OFFLINE=1 时导致的 HFValidationError

关联Issue #39112 报告:用户无法在HF_HUB_OFFLINE=1时加载S3模型。原因是EngineArgs.__post_init__无条件调用get_model_path(),而get_model_path()将路径传递给snapshot_download,snapshot_download验证repo ID,导致崩溃。用户设置HF_HUB_OFFLINE=1正是为了避免联系HF Hub,因此不应该干扰云URI解析。

值得阅读。该PR展示了如何优雅地隔离外部存储URI与HF Hub的交互,代码改动简洁,注释清晰,可作为处理类似hybrid路径解析的参考。

讨论亮点

审核者 gshtras 评论 "Looks good. Could you please update the branch to test against the up to date codebase",作者随后多次合并main分支以确保代码与最新库兼容,最终获得批准。无其他实质性讨论。

实现拆解

  1. 在EngineArgs.__post_init__中跳过云存储URI(vllm/engine/arg_utils.py):当检测到HF_HUB_OFFLINE时,先调用is_cloud_storage()检查model和tokenizer是否为云存储URI,如果是则跳过get_model_path()调用,保留原始URI供后续流程处理。
  2. 修复maybe_pull_model_tokenizer_for_runai错误参数(vllm/config/model.py):当模型和tokenizer是不同云URI时,pull_files()应该传递tokenizer URI而非model URI。将第891行的model改为tokenizer
  3. 添加测试覆盖:在tests/engine/test_arg_utils.py中新增两个测试函数,验证云URI在HF_HUB_OFFLINE下不会被传递给get_model_path();在tests/test_config.py中新增一个测试函数,验证不同模型和tokenizer URI时pull_files被正确调用两次且参数正确。
文件 模块 状态 重要度
vllm/engine/arg_utils.py 引擎参数 modified 6.68
vllm/config/model.py 模型配置 modified 4.93
tests/engine/test_arg_utils.py 参数测试 modified 6.24
tests/test_config.py 配置测试 modified 5.29

关键符号

__post_init__ maybe_pull_model_tokenizer_for_runai test_cloud_storage_uri_skips_get_model_path test_cloud_storage_tokenizer_skips_get_model_path test_s3_url_different_model_and_tokenizer

关键源码片段

vllm/engine/arg_utils.py core-logic

核心修复所在:在 EngineArgs.__post_init__ 中为云存储 URI 跳过 get_model_path 调用,防止 HFValidationError

# when use hf offline, replace model and tokenizer id to local model path
if huggingface_hub.constants.HF_HUB_OFFLINE:
    # Skip cloud storage URIs (s3://, gs://, az://) — they are not
    # HF repo IDs and will be resolved later by
    # ModelConfig.maybe_pull_model_tokenizer_for_runai().
    if not is_cloud_storage(self.model):
        model_id = self.model
        self.model = get_model_path(self.model, self.revision)
        if model_id is not self.model:
            logger.info(
                "HF_HUB_OFFLINE is True, replace model_id "
                "[%s] to model_path [%s]",
                model_id,
                self.model,
            )
    if self.tokenizer is not None and not is_cloud_storage(self.tokenizer):
        tokenizer_id = self.tokenizer
        self.tokenizer = get_model_path(self.tokenizer, self.tokenizer_revision)
        if tokenizer_id is not self.tokenizer:
            logger.info(
                "HF_HUB_OFFLINE is True, replace tokenizer_id [%s] "
                "to tokenizer_path [%s]",
                tokenizer_id,
                self.tokenizer,
            )
vllm/config/model.py data-contract

修复第二个 bug:maybe_pull_model_tokenizer_for_runai 中错误传递 model URI 给 tokenizer 的 pull_files

# Only download tokenizer if needed and not already handled
if is_runai_obj_uri(tokenizer):
    object_storage_tokenizer = ObjectStorageModel(url=tokenizer)
    object_storage_tokenizer.pull_files(
        tokenizer, # 修复:传递 tokenizer URI,而非 model URI
        ignore_pattern=["*.pt", "*.safetensors", "*.bin", "*.tensors", "*.pth"],
    )
    self.tokenizer = object_storage_tokenizer.dir

评论区精华

分支更新要求 other

审核者 gshtras 评论 'Looks good. Could you please update the branch to test against the up to date codebase',作者随后多次合并 main 分支以确保兼容性。

结论:作者更新了分支并重新测试,最终获得批准。 · 已解决

风险与影响

风险较低。主要变更在启动时控制流,添加了is_cloud_storage检查条件,仅对云存储URI才跳过get_model_path,不影响普通HF仓库路径。但需确保is_cloud_storage函数的覆盖范围与后续runai_utils的处理一致,避免新增URI协议(如r2://)遗漏。测试通过,但缺少端到端集成测试(mock实际云存储下载)。

直接影响:使用云存储(S3/GCS/Azure)且设置HF_HUB_OFFLINE=1的用户不再遇到启动崩溃,vLLM可以正常启动并进入模型加载流程。间接影响:无,因为改动仅在HF_HUB_OFFLINE为True的路径下生效,且通过is_cloud_storage隔离。对普通用户无影响。

启动路径变更 云路径跳过逻辑 分支条件覆盖

关联 Issue

#39112 [Bug]: HFValidationError when loading model from cloud storage (s3://) with `HF_HUB_OFFLINE=1`

完整报告

参与讨论