使用 ModelScope 管理本地模型缓存
我原先只把 ModelScope 当成下载命令用,模型多起来后,缓存里同时出现了旧目录、新目录和中断下载留下的临时文件。modelscope cache scan 显示约 128 GiB,磁盘统计却接近 160 GiB;同一个 Qwen3.6-27B 还出现了两份路径。
最后的处理很直接:确认没有需要保留的模型后,清空混杂的缓存,再用当前 CLI 重新下载。新版目录恢复正常,扫描结果也能按仓库列出。本文记录这套管理方式,使用的版本是 ModelScope 1.39.1 和 modelscope-hub 0.2.0。
用 uv tool 安装
ModelScope 是长期使用的命令行工具,我用 uv tool 给它单独建环境:
uv tool install modelscope
uv tool list --show-paths
modelscope --version
modelscope --help如果已经安装,可以升级:
uv tool upgrade modelscopemodelscope --version 在这组安装中会同时涉及完整 SDK 与 Hub CLI。实际排查时不要只说“最新版”,把两边的版本都记下来:
uv tool run --from modelscope python -c \
"import modelscope, modelscope_hub; print('modelscope', modelscope.__version__); print('modelscope-hub', modelscope_hub.__version__)"固定缓存根目录
模型文件较大,我不使用默认缓存,而是通过环境变量固定到模型盘:
echo 'export MODELSCOPE_CACHE="/path/to/modelscope"' >> ~/.bashrc
source ~/.bashrc
printf '%s\n' "$MODELSCOPE_CACHE"
modelscope list --envs设置好 MODELSCOPE_CACHE 后,下载、扫描、校验和清理都会使用同一个根目录。正常命令不需要反复追加 --cache-dir。
--cache-dir 是单次覆盖参数,适合临时测试:
modelscope cache scan --cache-dir /path/to/another-cache如果使用 --local-dir,文件会直接下载到指定目录,绕过受管理的缓存布局。想让 cache scan 和 cache clear 统一管理模型时,不要混用 --local-dir。
查看本地模型
先让 ModelScope 扫描缓存:
modelscope cache scan清理并重新下载后,我的缓存能正确识别两个仓库:
repo_id repo_type revision files size
unsloth/Qwen3.8-27B-GGUF model master 2 16.2 GiB
unsloth/Qwen3.6-27B-GGUF model master 2 16.5 GiB还可以核对文件完整性:
modelscope cache verify unsloth/Qwen3.6-27B-GGUFcache scan 统计的是 ModelScope 能识别的仓库,不等于缓存根目录下所有文件的磁盘占用。两者差距明显时,再看完整目录:
du -sh -- "$MODELSCOPE_CACHE"
du -h --max-depth=3 -- "$MODELSCOPE_CACHE" | sort -h下载未完成的临时文件、旧版缓存和手工放进去的文件可能不会作为正常仓库计入扫描结果。这就是扫描显示 128 GiB、目录实际占用约 160 GiB 的原因之一。
新版缓存路径
modelscope-hub 0.2.0 的受管理模型目录是:
$MODELSCOPE_CACHE/models/{OWNER}--{REPO}/snapshots/{REVISION}/例如:
$MODELSCOPE_CACHE/models/unsloth--Qwen3.6-27B-GGUF/snapshots/master/当前 Hub 实现会把仓库 ID 中的 / 替换为 --,并把具体版本放进 snapshots。旧版 ModelScope 使用过另一套结构:
$MODELSCOPE_CACHE/models/{OWNER}/{REPO_WITH_DOTS_REPLACED_BY_TRIPLE_UNDERSCORES}/例如 Qwen3.6 可能变成 Qwen3___6。为了兼容 1.37 及更早版本,新版下载器仍会探测非空的旧目录并复用它。机器上先有旧缓存、后来又用新布局下载,就可能看到名称相近的两份模型。这不是 Qwen3.6 有两个正式版本,而是缓存布局变过。
旧缓存还会影响扫描粒度。我遇到过这样的结果:扫描 $MODELSCOPE_CACHE 时只显示 unsloth,临时把 $MODELSCOPE_CACHE/models 传给 --cache-dir 后,才看到下面的具体仓库。后一个命令可以用来诊断旧目录,但不能据此把环境变量改成 .../modelscope/models。清空混杂缓存并按新版重新下载后,直接运行 modelscope cache scan 就能从正确的根目录识别仓库。
只下载 llama.cpp 需要的文件
我准备用 llama.cpp 运行 GGUF,不需要把仓库中的所有量化版本下载回来。仓库 ID 使用位置参数,--include 只选需要的文件:
modelscope download unsloth/Qwen3.6-27B-GGUF \
--include "*Q4_K_M*" "*mmproj-F16*"
modelscope download unsloth/Qwen3.8-27B-GGUF \
--include "*Q4_K_M*" "*mmproj-F16*"本次实际下载结果如下:
Qwen3.6-27B-Q4_K_M.gguf 16817244384 bytes
mmproj-F16.gguf 927607360 bytes
Qwen3.8-27B-UD-Q4_K_M.gguf 16464440224 bytes
mmproj-F16.gguf 927607488 bytes文件名里的 UD 是发布者使用的量化命名,不改变它作为主模型权重的用途。启动 Qwen3.8 时要照实际文件名填写,不能把 Qwen3.6 的命名规则硬套过去。
Q4_K_M 为什么适合作为默认选择
Q4_K_M 是 llama.cpp 的 K-quant 混合量化。它不是把每个张量都机械压成同一种四位格式,而是按量化规则给部分重要张量保留更高精度。相同模型下,它通常比 Q5、Q6 和 Q8 更省磁盘与内存,又比更激进的 Q2、Q3 少一些质量损失。
llama.cpp 自己在按量化类型选取 Hugging Face 文件时,也把 Q4_K_M 作为默认值。对 24GB 显存运行 27B 模型来说,它是我更愿意先试的平衡点。这里的“平衡”来自文件大小、内存占用和输出质量之间的取舍,不代表每个模型、后端和任务上都最快或最好。
如果显存充足而且更看重质量,可以试 Q5_K_M 或 Q6_K;内存吃紧时再考虑更小的量化。选择前先看具体文件大小,不要只看名称中的位数。
mmproj-F16.gguf 的作用
Qwen3.6-27B-Q4_K_M.gguf 是语言模型主体。mmproj-F16.gguf 是多模态投影器,负责把图片编码结果映射到语言模型能处理的表示。
需要视觉输入时,两者一起传给 llama-server:
./build/bin/llama-server \
--model "$MODELSCOPE_CACHE/models/unsloth--Qwen3.6-27B-GGUF/snapshots/master/Qwen3.6-27B-Q4_K_M.gguf" \
--mmproj "$MODELSCOPE_CACHE/models/unsloth--Qwen3.6-27B-GGUF/snapshots/master/mmproj-F16.gguf"只做文本推理时可以不下载它,并在启动时使用 --no-mmproj。mmproj 不是第二份语言模型,也不能脱离对应模型单独推理。
用 ModelScope 清理缓存
优先使用 ModelScope 自己的清理命令。删除单个模型:
modelscope cache clear \
--repo-id unsloth/Qwen3.6-27B-GGUF \
--repo-type model \
--yes清理所有受管理的模型缓存:
modelscope cache clear --repo-type model --yes数据集是另一种 repo type,需要单独处理:
modelscope cache clear --repo-type dataset --yes不加 --yes 时会保留确认步骤,第一次操作更适合这样做。清理前先运行 modelscope cache scan,确认 repo ID 和类型。
什么时候需要完整重建缓存
下面几种情况叠在一起时,逐个仓库清理往往比完整重建更麻烦:
- 同时存在旧版
owner/repo___name与新版owner--repo/snapshots。 - 出现
.___temp、中断下载或扫描无法识别的目录。 du与cache scan相差几十 GiB,确认差值不是仍需保留的普通文件。- 受管理清理完成后,磁盘占用仍没有明显下降。
完整删除前先解析并打印目标路径,不要对空变量、/、用户主目录或整个挂载点执行递归删除:
CACHE_ROOT="$(realpath -m -- "${MODELSCOPE_CACHE:?MODELSCOPE_CACHE 未设置}")"
printf '准备重建缓存:%s\n' "$CACHE_ROOT"
du -sh -- "$CACHE_ROOT"
modelscope cache scan确认输出确实是专用的 ModelScope 缓存目录,停止所有正在下载或读取模型的进程,再做一次路径保护和人工确认:
case "$CACHE_ROOT" in
/|/home|/root|/vol1|/mnt|/data|"$HOME")
printf '拒绝删除过宽的路径:%s\n' "$CACHE_ROOT" >&2
exit 1
;;
esac
read -r -p "输入完整路径 $CACHE_ROOT 以确认删除:" CONFIRM_PATH
[ "$CONFIRM_PATH" = "$CACHE_ROOT" ] || exit 1
rm -rf --one-file-system -- "$CACHE_ROOT"
mkdir -p -- "$CACHE_ROOT"缓存中的模型需要重新下载;混在里面的自有文件不会自动恢复,所以不要把其他资料放进这个根目录。
重建后重新执行下载和扫描:
modelscope download unsloth/Qwen3.6-27B-GGUF \
--include "*Q4_K_M*" "*mmproj-F16*"
modelscope cache scan这次完整重建后,Qwen3.6 和 Qwen3.8 都落在新版 owner--repo/snapshots/master 路径,扫描总量与所下载的四个文件相符。