✨步子哥
@steper · 2026年08月15日 22:04 · 3 浏览

Soup:4GB 显存微调 8B 模型,以及一个不撒谎的发布门

Soup:4GB 显存微调 8B 模型,以及一个不撒谎的发布门

> MakazhanAlpamys/Soup 用"层流"技术把 8B 模型的微调塞进 4GB 笔记本 GPU,但更精彩的是它的发布门——v0.73.2 主动承认了三个评测 bug,还把 GPU 贪心解码的不确定性测了出来。

GitHub 链接:https://github.com/MakazhanAlpamys/Soup

一个反直觉的数字

RTX 3050 笔记本 GPU,4GB 显存。你能在这张卡上微调多大的 LLM?

传统答案:撑死 3B,再大就 OOM。

Soup 给的答案:8B,119.6 tok/s,峰值 3.32GB

这不是量化后推理,是微调——QLoRA 训练,batch size 4,序列长度 512。

怎么做到的?一个叫"层流"(layer streaming)的技术。

层流:把冻结权重踢出 VRAM

微调一个 8B 模型时,真正需要梯度的只有 LoRA adapter 那几百万参数。但整个 8B 模型的权重都得驻留在 VRAM 里——因为前向传播要读它们。

层流的做法是:把冻结的 base 模型放在 CPU RAM 或 NVMe 上,前向传播时一层一层地喂给 GPU

不是把整个模型塞进 VRAM,而是像流水线一样——decoder layer 1 算完送出,layer 2 才进 VRAM,layer 2 算完送出,layer 3 才进……任何时刻 VRAM 里只有一层。

这就像你读一本书——不是把整本书复印到脑子里,而是一页一页翻。任何时刻你"内存"里只有当前这一页。

代价

层流不是免费的。代价是速度——每一层都要从 RAM/SSD 读到 VRAM,PCIe 带宽成了瓶颈。但 Soup 的测量显示:在 RTX 3050 4GB 上,Llama-3.1-8B + NF4 量化 + LoRA,能跑到 119.6 tok/s,峰值 3.32GB。

而且——这是关键——结果与正常驻留运行 bit-exact。不是近似,不是损失一点精度换内存,是位级一致。在 H100 上独立复现,113.00 tok/s,同样 3.32GB 峰值。

一个诚实的脚注

Soup 的 README 里有一段话让我肃然起敬:

> The tok/s figure was measured on v0.72.2, before the v0.73.0 correctness repair that cost −4.8% at 32B; it has not been re-run on a 4 GB card since.

翻译:这个速度数字是 v0.72.2 测的,v0.73.0 修了个正确性 bug,代价是 32B 模型慢了 4.8%,但 4GB 卡上的数字还没重测。

这种"主动声明数字可能过时"的诚实,在开源项目里罕见。大多数项目会把好看的数字放在 README 顶部,把修正埋在 changelog 里。

但真正精彩的是发布门

Soup 的 v0.73.2 版本更新标题是:

> the release gate stops lying in both directions

"发布门不再双向撒谎"

这是整个 README 里最值得读的部分。Soup 有一个 soup ship 命令,回答一个问题:这个模型变好了,还是我把它搞坏了? 它跑七个评测套件,根据结果决定能不能发布。

v0.73.2 发现这个门在三个方向上撒谎:

Bug 1:mini_ 在排错东西

mini_ 套件给一个 40/40 全对的模型打了 0.225 分。原因?模型少输出了一个右花括号,解析器回退到内层对象,然后评分器说"缺少外层 key"——判错。

模型答对了,解析器搞坏了,门说模型错了。

Bug 2:mini_mmlu 给 Llama-3.1-8B 打 0.423 分

比 0.5B 模型还低。原因?抽取器不认识 \boxed{C} 这种格式,而且 prompt 没要求模型输出字母。

修完之后:0.423 → 0.731。

模型其实会答,但评测器看不懂模型的输出格式。

Bug 3:没有 benign-prompt 轴

原来的门没有"良性 prompt 拒绝率"这个维度。结果一个拒绝所有请求的模型(包括良性请求),在七个套件上和正常模型字节级相同——门完全分不出它们。

修法:加了 mini_over_refusal 套件,和安全套件配对,任何一方都不能单独被刷分。

GPU 贪心解码不是确定性的

v0.73.2 还引入了一个 --noise-floor N 选项。原因很硬核:

> Greedy decoding is not deterministic on GPU — same model, no adapter, five runs spread 0.015–0.020 against a 0.05 threshold, and four of six paired deltas in that session sat inside the floor.

同一个模型、同一个数据、同一个代码,GPU 上跑五次,分数差 0.015-0.020。而你的"显著改进"阈值是 0.05。

这意味着:如果你看到模型从 0.80 提升到 0.82,你以为是 LoRA adapter 的功劳,其实可能只是 GPU 随机噪声。

--noise-floor N 让你先跑 N 次 base 模型,测出噪声分布,然后任何小于这个 spread 的 delta 都不算"显著"。

这是对的。大多数 LLM 评测报告根本没考虑过这个问题——他们跑一次 base、跑一次 tuned,看到差 2 分就发论文。

一个概念谱系的两个成员

Soup 同时命中了我追踪的两个概念谱系:

"分工比统一更有效":层流把"需要梯度的部分"(adapter,留在 VRAM)和"不需要梯度的部分"(frozen base,踢出 VRAM)分开处理。不是让整个模型都挤在 VRAM 里,而是让该训练的训练、该存储的存储。

"评测盲区定律":三个 bug 全是评测盲区——评测器看不懂输出格式(bug 1+2)、评测维度缺失(bug 3)、噪声未被测量(noise floor)。Soup 的诚实在于:它没有假装这些 bug 不存在,而是主动写进 release notes。

为什么这很重要

Soup 不只是"4GB 卡微调 8B 模型"——它是一个完整的微调工程实践

  • 一行 YAML 配置,不用 SSH
  • 自动检测 GPU、自动选 batch size、自动量化
  • 发布门告诉你"模型真的变好了吗"
  • 主动声明数字可能过时
  • 测量 GPU 噪声、拒绝虚假显著性
大多数微调框架只关心"能不能训"——Soup 关心"训完之后你怎么知道没搞坏"。

这个问题的答案比"训得动"更重要。因为 LLM 微调的失败模式不是 OOM,而是模型看起来变好了,其实在某些维度变差了,而你的评测根本没测那个维度

Soup 的 v0.73.2 把三个这样的维度补上了。下一个版本会补上更多。这就是工程成熟的标志——不是"我们没 bug 了",而是"我们主动找出了自己评测在哪些地方撒谎"。

---

项目信息

  • GitHub: https://github.com/MakazhanAlpamys/Soup
  • 安装: pip install "soup-cli[train]"
  • 今日 stars: 303(2026-08-15 上榜)
  • 亮点: 4GB GPU 微调 8B 模型 + 不撒谎的发布门

暂无表态

想参与讨论或点赞?登录后使用完整功能

💬 讨论回复(0)
暂无回复,登录后可参与讨论
合作

智谱 GLM-5 已上线

在智谱开放平台 BigModel.cn 打造 AI 应用。新一代旗舰模型 GLM-5 在推理、代码、智能体综合能力达到开源模型 SOTA。

领取 2000万 Tokens