Google Cloud Run中使用Hugging Face Snapshot Download离线加载模型失败
我太懂你这个糟心的处境了——明明把模型快照好好存在GCS桶里,也成功挂载到Cloud Run,离线环境变量也设了,结果Hugging Face的库就是认不出本地模型,非要去连官网触发报错。咱们一步步拆解问题,找出根源:
先排查最关键的:HF缓存目录结构对不对
Hugging Face的缓存系统有严格的目录格式要求,不是随便把模型文件夹扔到HF_HOME下面就行的。你用snapshot下载的模型,应该是这样的结构:
/mnt/gcs/huggingface/ ├── models--bert-base-uncased/ # 把模型名里的/换成-- │ └── snapshots/ │ └── [具体的commit哈希值]/ # 快照对应的哈希目录 │ ├── config.json │ ├── vocab.txt │ └── 其他模型必备文件 └── models--nomic-ai--nomic-embed-text-v1.5/ └── snapshots/ └── [具体的commit哈希值]/ ├── config.json ├── pytorch_model.bin └── 其他模型文件
你可以在初始化代码里加一段检查,确认结构是否正确:
# 在initialize_offline_env函数里,设置完HF_HOME后添加 bert_model_dir = hf_cache_path / "models--bert-base-uncased" if bert_model_dir.exists(): for snap_dir in bert_model_dir.glob("snapshots/*"): logging.info(f"找到bert模型快照目录:{snap_dir},包含文件:{list(snap_dir.iterdir())}") else: logging.error("❌ HF缓存里找不到bert-base-uncased的模型目录!")
如果日志里显示找不到对应的models--xxx目录,那就是你下载快照时的路径没放对,得调整GCS桶里的文件结构。
检查GCS FUSE的挂载选项
GCS是对象存储,不是传统文件系统,Cloud Run用FUSE挂载的时候,默认可能没开启嵌套目录识别。你需要在挂载配置里加上--implicit-dirs参数,这个参数能让FUSE正确识别GCS里的嵌套目录结构。
从你的挂载日志里看不到这个选项,很大概率是这个原因导致HF库遍历不到快照子目录。去Cloud Run的服务配置里,找到GCS挂载的部分,添加这个参数再试试。
确认环境变量真的生效了
虽然你设置了HF_HUB_OFFLINE和HF_HOME,但有时候可能被其他配置覆盖,或者代码执行顺序有问题(不过你是先设环境变量再导入库,这点是对的)。可以在prewarm_models开头加个日志验证:
logging.info(f"当前HF_HUB_OFFLINE值:{os.getenv('HF_HUB_OFFLINE')}") logging.info(f"当前HF_HOME路径:{os.getenv('HF_HOME')}")
确保输出的是1和/mnt/gcs/huggingface,没有偏差。
试试直接指定本地快照路径
如果上面的排查都没问题,那可以绕开HF的缓存查找逻辑,直接给模型指定本地的快照路径:
# 替换成你实际的快照哈希目录 tokenizer = AutoTokenizer.from_pretrained( pretrained_model_name_or_path="/mnt/gcs/huggingface/models--bert-base-uncased/snapshots/abc123xxx", local_files_only=True ) model = SentenceTransformer( model_name_or_path="/mnt/gcs/huggingface/models--nomic-ai--nomic-embed-text-v1.5/snapshots/def456yyy", trust_remote_code=True, local_files_only=True )
如果这样能成功加载,说明是HF的缓存路径识别逻辑出了问题,直接指定路径就能解决。
最后检查模型文件完整性
有时候下载快照时可能漏掉了某些小文件(比如tokenizer的配置文件、模型的权重分片),HF库会认为缓存不完整,自动触发下载。你可以对比Hugging Face官网上对应模型的文件列表,确认GCS桶里的文件一个不少。
按照这个顺序排查,应该能找到问题所在,祝你顺利解决!
内容来源于stack exchange




