GitHub Actions 中缓存 HuggingFace 模型缓存目录避免每次拉取的 key 配置

文章导读
在 GitHub Actions 里缓存 HuggingFace 模型缓存目录,核心不是路径本身,而是 key 的稳定性。固定 key 每次都能命中,但模型更新后缓存仍是旧版本;时间戳做 key 每次都会 miss。这里要处理的是两种情况的分界:模型集合未变时命中长期缓存,模型集合变化时让 key 失效。
📋 目录
  1. A 先确认缓存目录指向哪里
  2. B 配置缓存 key:主 key 加 restore-keys
  3. C 缓存命中后仍需校验模型完整
  4. D 验证方式和边界
  5. E 常见问题
A A

在 GitHub Actions 里缓存 HuggingFace 模型缓存目录,核心不是路径本身,而是 key 的稳定性。固定 key 每次都能命中,但模型更新后缓存仍是旧版本;时间戳做 key 每次都会 miss。这里要处理的是两种情况的分界:模型集合未变时命中长期缓存,模型集合变化时让 key 失效。

缓存 HuggingFace 目录的关键是用“模型清单或依赖快照”作为 key,而不是拉取时刻;固定 key 能保证命中,但不容易感知模型更新;建议用主 key 加 restore-keys 的方式,给模型组合变化留出失效通道。实施前先确认缓存目录和配额。

先确认缓存目录指向哪里

HuggingFace 的模型缓存默认在 ~/.cache/huggingface,但通过 HF_HOME 环境变量可以整体迁移。在 GitHub Actions 里,建议在 job 层统一设置:

env:
  HF_HOME: ${{ runner.temp }}/hf-cache

这样不会把模型写到容器默认 HOME 之外的杂散位置,也让后续步骤引用更明确。要确认实际路径,可以加一步:

- name: Check HF cache path
  run: |
    python -c 'from huggingface_hub import scan_cache_dir; print(scan_cache_dir())'

这一步会在日志中列出实际缓存目录和已缓存的模型条目,也方便在本地和 Actions 里对比。

GitHub Actions 中缓存 HuggingFace 模型缓存目录避免每次拉取的 key 配置

配置缓存 key:主 key 加 restore-keys

用一个固定前缀,加上一个能反映模型集合的 hash。推荐把需要用的模型 ID 写进一个文件,例如 models.txt,每行一个:

sentence-transformers/all-MiniLM-L6-v2
BAAI/bge-small-zh-v1.5

缓存步骤这样写:

- name: Cache HuggingFace models
  id: cache-models
  uses: actions/cache@v4
  with:
    path: ${{ runner.temp }}/hf-cache
    key: hf-models-${{ runner.os }}-${{ hashFiles('models.txt') }}
    restore-keys: |
      hf-models-${{ runner.os }}-

key 负责精确匹配,restore-keys 负责在 miss 时退回最近的通用缓存。模型组合没有变化时,hashFiles 输出相同,缓存能稳定命中;需要新增或替换模型时,models.txt 变化,key 自然失效。

GitHub Actions 中缓存 HuggingFace 模型缓存目录避免每次拉取的 key 配置

如果模型集合长期不变,也可以直接写固定 key,例如 hf-models-${{ runner.os }},识别和排查都简单。但模型如果没有更新,缓存会一直锁住旧版本,需要手动改 key 才会失效。

缓存命中后仍需校验模型完整

actions/cache 会恢复上次保存的整个目录,但无法确认里面每个模型文件是否完整。上一次写入时如果模型只下了一半,这次命中后会拿到残缺目录。建议在加载模型前做一次轻量校验:

GitHub Actions 中缓存 HuggingFace 模型缓存目录避免每次拉取的 key 配置
- name: Verify models
  run: |
    test -d $HF_HOME/hub/models`--sentence-transformers--all-MiniLM-L6-v2` && echo model ok

这一步可以放在加载模型之前,失败就删除缓存目录重新下载。缓存损坏是低频事件,但校验成本很低,值得保留。

验证方式和边界

第二次运行时观察缓存步骤输出。actions/cache 会显示 Cache hit 或 Cache miss。hit 说明缓存生效,后续加载步骤应直接使用本地文件;miss 则说明 key 变化或缓存被回收,会重新下载并保存新缓存。

边界方面需要确认两点。第一,GitHub Actions 缓存有总量配额,过大或长期不活跃的缓存可能被清理,不要把它当成唯一副本,重新下载是最差情况的兜底。第二,私有仓库与公共仓库的缓存保留策略不同,应用层看不到保留时长,需要通过运行日志观察实际 miss 频率。

常见问题

  1. key 需要写死模型 ID 吗? 不需要。hashFiles('models.txt') 已经把模型集合编码进 key。如果模型固定,直接用固定 key 也可以,但模型版本更新时不会自动失效,需要手动改 key。建议在 models.txt 中保留模型 ID 和更新日期,方便人工识别。
  2. 缓存目录太大怎么办? 先观察一次跑完后的缓存大小,再决定缩小范围。可以为单个模型建立独立缓存,或者用 snapshot_download 配合 local_dir 把模型放到指定目录,而不是缓存整个 ~/.cache 目录。大缓存恢复慢,也可能触发配额问题,需要实测确认。