2026-10-27 · 深度笔记

模型权重下载太慢怎么办:镜像预置、对象存储加速与断点续传

从源站拉几十 GB 权重慢得离谱时,我试过各种办法。这篇讲实测有效的几条路,以及最容易被忽略的一个前提:先确认你下到的确实是权重文件。

云主机模型部署对象存储运维

第一次在新机器上部署模型,我盯着下载进度条看了 40 分钟,进度条走到 12%,然后卡住不动了。

最后发现是超时重试在背后作怪:每传一段就断,断了之后从断点续传,但速度本身已经掉到接近零。折腾了一整个下午,才把权重完整拉下来。

这件事之后我整理了现在这套流程,按顺序走一遍基本不会再卡。

先确认你下的是权重,不是指针文件

这是最容易白忙一场的一步。

模型仓库里的大文件通常用 Git LFS 管理。直接 git clone 下来,你拿到的不是权重,是一个几百字节的文本指针:

version https://git-lfs.github.com/spec/v1
oid sha256:abc123...
size 15281129536

真正的 15GB 文件在 LFS 服务器上,需要额外的 LFS 客户端才会拉。而有些工具(包括一部分一键下载脚本)只做了普通 clone。

症状很典型:目录里有 model-00001-of-00004.safetensors 这个文件名,打开看却只有几百字节,加载时框架报各种看不懂的错——"unexpected size"、"header too large",或者干脆当成损坏文件。

检查方法很简单:

# 看文件真实大小
ls -lh model-00001-of-00004.safetensors

# 期望是十几 GB,看到几百字节就是指针
head -c 100 model-00001-of-00004.safetensors

先验证完整性,再开始下载。 这一步能省掉你后面所有的时间。

方法一:huggingface-cli / hf download

最直接的方式,速度取决于源站和你的出口带宽。

# 装 CLI
pip install -U "huggingface_hub[cli]"

# 下载指定模型的全部文件
hf download Qwen/Qwen2.5-7B-Instruct --local-dir ./models/qwen2.5-7b

# 只下配置文件和分词器,先验证路径通不通
hf download Qwen/Qwen2.5-7B-Instruct config.json tokenizer.json \
  --local-dir ./models/probe

第二条命令是我现在每次都先跑的探针。下几个 KB 的文件只要几秒钟,如果这一步就失败,说明是网络或认证问题,没必要开始几十 GB 的下载。

开加速传输:

export HF_HUB_ENABLE_HF_TRANSFER=1
hf download Qwen/Qwen2.5-7B-Instruct --local-dir ./models/qwen2.5-7b

这个开关会启用多线程分块传输。但它不是万能的——在源站限速的环境里,多线程反而可能触发限流,表现是大量 429 或连接重置。这时候退回到单线程 + 断点续传反而更快。

方法二:断点续传

huggingface_hub 本身就支持断点续传,重复执行同一条命令会接着上次继续。中断之后直接重跑就行。

如果是从任意 URL 下,用 curl 或 wget:

# wget 的 -c 就是断点续传
wget -c -O model.safetensors "https://example.com/model.safetensors"

# curl 的 --continue-at -
curl -L -C - -o model.safetensors "https://example.com/model.safetensors"

有个坑:-C - 要求服务器支持 Range 请求。如果服务器返回的是 200 而不是 206,续传会失败,curl 会报 "Cannot resume"。这种情况下只能删掉重下。

另外,中断的原因比续传本身更重要。我那次卡住是因为单个文件传输到一定量后连接被切断,需要检查是不是:

# 测试长连接稳定性:下 100MB 看会不会中途断
curl -L --limit-rate 10M -o /dev/null -w "%{speed_download} %{size_download}\n" \
  "https://example.com/big-file"

方法三:镜像站

很多模型托管平台在国内访问不稳定,官方也提供了镜像端点。

export HF_ENDPOINT=https://hf-mirror.com
hf download Qwen/Qwen2.5-7B-Instruct --local-dir ./models/qwen2.5-7b

镜像站要留意的点:

用镜像下载之后,校验哈希。这一步不能省——镜像站的完整性问题比源站多。

方法四:对象存储中转

这是我的最终方案,也是一次性的投入换来长期稳定的做法。

流程是:在自己可控的、离云主机近的对象存储里放一份权重,然后云主机从对象存储拉。

# 第一步:把权重传到对象存储(可以用 CLI 或 SDK)
# 第二步:生成一个有时效的签名 URL
# 第三步:在云主机上拉

wget -c -O model.safetensors "https://bucket.oss-cn-hangzhou.aliyuncs.com/model.safetensors?签名参数"

好处有三条:

  1. 同云厂商内网拉取可以走内网 endpoint,不走公网,速度和稳定性都上一个台阶。
  2. 不限速、不限源站策略,还能自己控速避免影响其他服务。
  3. 可以预热。运维流程里提前把新版本的权重传上去,机器开出来直接拉本地的。

需要注意的一点:内网 endpoint 通常要求同地域,跨地域还是走公网。而且对象存储和云主机要在同一个账号下、走 VPC 内网,这两点要一起满足。

拉完之后算个校验值存下来:

sha256sum model.safetensors > model.safetensors.sha256

# 下次用这个校验
sha256sum -c model.safetensors.sha256

方法五:直接打进镜像

适合部署固定的场景。把量化后的模型烤进镜像:

FROM vllm/vllm-openai:latest
COPY ./models/qwen2.5-7b-int4/ /models/qwen2.5-7b-int4/
ENV VLLM_MODEL_PATH=/models/qwen2.5-7b-int4

好处是彻底消灭"下载"这个环节——机器开出来镜像就带权重。但代价也明显:

我只在模型固定且节点池稳定的场景这么做。如果模型要频繁更新,这条路维护起来很痛苦。

缓存目录一定要挂持久盘

这个坑我踩过两次,每次都因为机器重启。

很多框架默认把权重缓存在容器内的某个目录,比如 ~/.cache/huggingface。容器重建、机器重启、编排滚动更新——缓存就没了,下次启动又是几十 GB 的下载。

# 显式指定缓存目录
export HF_HOME=/data/models/hf
export HF_HUB_CACHE=/data/models/hf/hub
export TRANSFORMERS_CACHE=/data/models/hf/transformers

# 或者用 huggingface_hub 的 API
python -c "
from huggingface_hub import snapshot_download
snapshot_download(
    'Qwen/Qwen2.5-7B-Instruct',
    local_dir='/data/models/qwen2.5-7b',
    cache_dir='/data/models/hf/hub',
)
"

/data 要挂在持久卷上,不是容器可写层。这件事值得专门检查一遍:

docker inspect <容器> | grep -A 5 Mounts

落到一起的下载流程

我现在实际执行的顺序:

#!/usr/bin/env bash
set -euo pipefail

MODEL_ID="Qwen/Qwen2.5-7B-Instruct"
DEST="/data/models/qwen2.5-7b"

# 1. 探针:先确认网络和路径通
echo "== 探针 =="
HF_ENDPOINT="${HF_ENDPOINT:-}" hf download "$MODEL_ID" config.json --local-dir "$DEST.probe"
rm -rf "$DEST.probe"

# 2. 主下载(可断点续传,重复执行安全)
echo "== 下载 =="
HF_HUB_ENABLE_HF_TRANSFER=1 hf download "$MODEL_ID" --local-dir "$DEST"

# 3. 校验文件大小,看有没有下成指针
echo "== 校验 =="
find "$DEST" -name "*.safetensors" -exec ls -lh {} \;
find "$DEST" -name "*.safetensors" -size -10M -print | \
  { grep . && echo "有文件小于 10MB,很可能是指针文件" && exit 1; } || true

# 4. 清理临时目录
rm -rf "$DEST/.cache"

第 3 步那个 -size -10M 的检查是我加的自动化,原理就是前面说的"先确认下的是权重"。

收尾

权重下载这件事本身没什么技术含量,但它是整条部署链路里最不可控的一环——因为它依赖一个你控制不了的源站。

所以我现在的原则是:把下载从部署流程里移出去。下载是一次性的、可缓存的、可预热的事,不该出现在"机器开出来 → 服务就绪"这条关键路径上。放进镜像、放进对象存储、放进持久卷缓存,都是同一个思路。

至于各家的对象存储费用、镜像仓库配额、限速策略这些,各家差异很大而且经常调整,文章里说的都是做法不是报价,实际以官方页面和文档为准。

接着读