在 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 里对比。
配置缓存 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 自然失效。
如果模型集合长期不变,也可以直接写固定 key,例如 hf-models-${{ runner.os }},识别和排查都简单。但模型如果没有更新,缓存会一直锁住旧版本,需要手动改 key 才会失效。
缓存命中后仍需校验模型完整
actions/cache 会恢复上次保存的整个目录,但无法确认里面每个模型文件是否完整。上一次写入时如果模型只下了一半,这次命中后会拿到残缺目录。建议在加载模型前做一次轻量校验:
- 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 频率。
常见问题
- key 需要写死模型 ID 吗? 不需要。hashFiles('models.txt') 已经把模型集合编码进 key。如果模型固定,直接用固定 key 也可以,但模型版本更新时不会自动失效,需要手动改 key。建议在 models.txt 中保留模型 ID 和更新日期,方便人工识别。
- 缓存目录太大怎么办? 先观察一次跑完后的缓存大小,再决定缩小范围。可以为单个模型建立独立缓存,或者用 snapshot_download 配合 local_dir 把模型放到指定目录,而不是缓存整个 ~/.cache 目录。大缓存恢复慢,也可能触发配额问题,需要实测确认。