指南 14:一小时微调你的第一个 LLM

作者: Jakub Rusinowski · 最后更新: 2026年7月12日

在这一小时结束时,你将拥有一个以你的格式作答的小型语言模型,在本地的 Ollama 中运行——总成本:0 美元。无需博士学位。你只需要以下之一:一块显存 6GB 以上的 NVIDIA GPU,或一台内存 16GB 以上的 Apple Silicon Mac。我们将挑选一个入门数据集,用不会翻车的保守设置训练一个 QLoRA 适配器,导出为 GGUF,然后与你自己的模型对话。这是"食谱卡";[指南

本指南内容

在这一小时结束时,你将拥有一个以你的格式作答的小型语言模型,在本地的 Ollama 中运行——总成本:0 美元。无需博士学位。你只需要以下之一:一块显存 6GB 以上的 NVIDIA GPU,或一台内存 16GB 以上的 Apple Silicon Mac。我们将挑选一个入门数据集,用不会翻车的保守设置训练一个 QLoRA 适配器,导出为 GGUF,然后与你自己的模型对话。这是"食谱卡";指南 13:在本地微调 LLM 是完整的"菜谱大全"——当你想了解某一步背后的原理时就去看它。


第 0 步 —— 你到底该不该微调?(5 分钟)

在你花掉一小时之前,先诚实地把把关:微调是你该拿起的*第三*件工具,而不是第一件。

先用提示。 一个好的系统提示加上两三个示例输出,能在五分钟内解决大多数"让它像 X 那样作答"的问题。其次用 RAG。 如果问题在于*知识*——你的文档、你的产品、当前事实——那么检索胜出,因为微调无法可靠地添加事实。当以下情况时才微调: 你需要每次回复都保持一致的风格或格式、领域特定的措辞、必须始终能解析的结构化输出,或出于延迟考虑而使用简短提示。这是一段话的版本——带示例的完整决策清单在指南 13 的"何时应该微调?"一节。

还在看?很好——风格、格式和语气正是一小时微调所擅长的。

第 1 步 —— 选择你的路径(2 分钟)

路径 A:NVIDIA路径 B:Apple Silicon
硬件显存 6GB 以上的 GeForce GPU(RTX 3060/4060 或更好)拥有16GB 以上统一内存的 M1–M4 Mac
工具Unsloth(在 4-bit 基座上做 QLoRA)MLX-LM(在 4-bit 模型上做 LoRA)
基座模型unsloth/Llama-3.2-3B-Instructmlx-community/Mistral-7B-Instruct-v0.3-4bit
约 1k 样本用时~20–60 分钟~20–40 分钟

QLoRA 是让这一切在消费级硬件上成为可能的诀窍:基座模型以 4-bit 加载,你只训练小的适配器矩阵,因此一个 7B 微调只需约 6GB 显存——而 Mac 上 4-bit 的 7B 微调约占用 8GB 工作内存,在 16GB 机器上仍有余量。在路径 B 上请注意,在一个已经是 4-bit 的模型上训练 LoRA 适配器*就是* QLoRA——MLX 会处理好,无需额外设置。

不确定你的显卡是否合格?在硬件分析器中检查你的 GPU。完全没有兼容硬件?以约 0.35 美元/小时租一块 RTX 4090——见云 GPU 租用指南;下面的一切在租用的机器上运行方式完全相同。

如果你在为第一块微调显卡选购,16GB 的 RTX 4060 Ti 是甜蜜点——足够的显存可支撑 13B 的 QLoRA 训练:

{{affiliate-box:rtx-4060-ti-16}}

第 2 步 —— 挑选一个入门数据集(5 分钟)

三个不错的选择,按优先顺序:

1. No Robots —— 1 万条完全由人工标注者撰写的示例。小巧、干净、多样。是*学习*工作流的最佳首选数据集,也是下面脚本所使用的。 2. Databricks Dolly 15k —— 1.5 万条人工撰写的问答对,采用 CC BY-SA 3.0 许可。如果你的微调有可能用于产品,就选这个。 3. 你自己的 200–500 条示例 —— 当你想让模型听起来像*你*的那一刻,没有什么比得上你自己的数据。使用 Alpaca JSONL 格式(与指南 13 相同):

{"instruction": "Summarize this support ticket in two sentences.", "input": "Customer reports login fails after password reset...", "output": "Customer cannot log in following a password reset. Issue traced to a stale session cookie; cleared and resolved."}

> ⚠️ 训练前请检查许可证。 Alpaca 和 ShareGPT 是 CC BY-NC(非商用)——No Robots 也是,因此把它当作学习数据集。任何商用用途请使用 Dolly 15k(CC BY-SA)或其他宽松许可的数据集——在数据集中心按"宽松许可(Permissive)"筛选即可看到全部。

第 3A 步 —— 在 NVIDIA 上用 Unsloth 训练(25 分钟)

一个脚本,从头到尾。先安装(干净的虚拟环境能省去 CUDA 依赖的麻烦):

pip install unsloth
from unsloth import FastLanguageModel
from datasets import load_dataset
from trl import SFTTrainer
from transformers import TrainingArguments

# 1. Load a small 4-bit base — 3B keeps this comfortable even on 6GB cards
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="unsloth/Llama-3.2-3B-Instruct",
    max_seq_length=2048,
    load_in_4bit=True,
)

# 2. Add LoRA adapters (r=16 is the standard starting point)
model = FastLanguageModel.get_peft_model(
    model,
    r=16,
    lora_alpha=16,
    lora_dropout=0,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                    "gate_proj", "up_proj", "down_proj"],
)

# 3. Load No Robots and render each conversation with the chat template.
#    Columns on the HF card: prompt, prompt_id, messages, category —
#    "messages" is the list of {role, content} turns we train on.
dataset = load_dataset("HuggingFaceH4/no_robots", split="train[:1000]")

def to_text(row):
    return {"text": tokenizer.apply_chat_template(row["messages"], tokenize=False)}

dataset = dataset.map(to_text)

# 4. Train — conservative defaults, same as Guide 13
trainer = SFTTrainer(
    model=model,
    tokenizer=tokenizer,
    train_dataset=dataset,
    dataset_text_field="text",
    max_seq_length=2048,
    args=TrainingArguments(
        per_device_train_batch_size=2,
        gradient_accumulation_steps=4,
        num_train_epochs=2,
        learning_rate=2e-4,
        logging_steps=10,
        optim="adamw_8bit",
        output_dir="./outputs",
        save_strategy="epoch",
    ),
)
trainer.train()

# 5. Save the adapter
model.save_pretrained("my-first-lora")
tokenizer.save_pretrained("my-first-lora")

在 RTX 3060/4060 级别的 GPU 上,1000 条示例的子集(2 个 epoch)大约需要 20–60 分钟——区间取决于示例长度;较老的 6GB 显卡会落在上限。损失(loss)应从约 2 开始并稳步下降;如果没有,请跳到第 5 步。

第 3B 步 —— 在 Mac 上用 MLX 训练(25 分钟)

pip install mlx-lm

MLX 需要一个 data/ 文件夹,内含其聊天格式的 train.jsonlvalid.jsonl——每一行是 {"messages": [...]},最后一条消息就是模型要学着生成的内容。几行代码即可转换 No Robots:

import json
from datasets import load_dataset

ds = load_dataset("HuggingFaceH4/no_robots")
def dump(rows, path):
    with open(path, "w") as f:
        for row in rows:
            f.write(json.dumps({"messages": row["messages"]}) + "\n")

dump(ds["train"].select(range(1000)), "data/train.jsonl")
dump(ds["test"].select(range(100)), "data/valid.jsonl")

然后训练——一条命令:

mlx_lm.lora \
  --model mlx-community/Mistral-7B-Instruct-v0.3-4bit \
  --data ./data \
  --train \
  --batch-size 2 \
  --iters 600

由于基座模型已经是 4-bit,这个 LoRA 训练就是 QLoRA——无需任何标志。在 16GB 的 M2/M3/M4 上预计需要 20–40 分钟;验证损失会一路打印出来。立即测试适配器:

mlx_lm.generate \
  --model mlx-community/Mistral-7B-Instruct-v0.3-4bit \
  --adapter-path adapters \
  --prompt "Summarize what QLoRA does in one sentence."

第 4 步 —— 测试并导出到 Ollama(10 分钟)

路径 A(Unsloth): 直接导出为 GGUF——在你的脚本中加一行:

model.save_pretrained_gguf("my-first-model", tokenizer, quantization_method="q4_k_m")

路径 B(MLX): 把适配器融合进权重并导出。GGUF 导出需要 fp16 权重,因此在融合时反量化:

mlx_lm.fuse \
  --model mlx-community/Mistral-7B-Instruct-v0.3-4bit \
  --adapter-path adapters \
  --de-quantize \
  --export-gguf

现在用一个两行的 Modelfile 把它接入 Ollama(把 FROM 指向你刚生成的 .gguf 文件):

FROM ./my-first-model/unsloth.Q4_K_M.gguf
SYSTEM You are a concise assistant that answers in two sentences maximum.
ollama create my-first-model -f Modelfile
ollama run my-first-model

前后对比就是回报所在。同一个提示——"解释一下 VPN 的作用":

之前(基座模型): *"好问题!VPN,即虚拟专用网络,是一种在不太安全的网络上建立安全加密连接的技术……[还有三段]"*

之后(你的微调版): *"VPN 会加密你的流量并通过远程服务器转发,从而对本地网络隐藏你的活动并掩盖你的 IP 地址。它能在公共 Wi-Fi 上保护隐私,但并不能让你完全匿名。"*

这就是每一次成功的风格微调的样子:知识相同,格式是你的。

第 5 步 —— 哪里出错了?(5 分钟)

每个人都会遇到的四种失败,按出现频率排序:

1. CUDA 显存不足(out of memory) —— 把 per_device_train_batch_size 降到 1,把 max_seq_length 减到 1024,或(MLX)加上 --grad-checkpoint。3B 基座上的 QLoRA 只需约 4GB;如果在那里就 OOM,说明有别的东西在占用显存——把它关掉。 2. 模型逐字复述训练示例 —— 你过拟合了。降到 1 个 epoch,或增加更多样化的数据。 3. 模型在其他所有方面都变笨了 —— 学习率过高或 epoch 过多抹掉了通用能力。回到 2e-4 和 2 个 epoch;这正是它们作为默认值的原因。 4. 损失从不下降 —— 几乎总是数据格式问题:文本字段没有经过聊天模板,或你的 JSONL 键不匹配。打印一条格式化后的样本并读一读。

遇到的是奇怪的驱动或安装错误?故障排查一节逐条讲解了 CUDA OOM 及其同类问题。

接下来做什么

常见问答

微调一个 LLM 的最低 GPU 要求是什么?

一块 6GB 的 NVIDIA 显卡(RTX 3060/4060 级别)可从容地用 QLoRA 微调 7B 模型,而 3B 模型只需约 4GB。不使用 QLoRA 的完整微调需要多 10–20 倍的内存——这正是本指南每一步都使用 4-bit 基座配 LoRA 适配器的原因。

我能在 Mac 上微调 LLM 吗?

可以。苹果的 MLX 框架利用统一内存在 4-bit 模型上训练 LoRA 适配器——一台 16GB 的 M 系列 Mac 约用 8GB 工作内存就能处理一个 7B 的 QLoRA 微调。它比桌面 NVIDIA 显卡慢,但完全本地且静音。

我需要多少条示例来微调?

对于风格、语气和格式:200–1000 条好示例。LIMA 证明了 1000 条精挑细选的样本就能对齐一个 65B 模型。对于新的领域技能,目标是 1 万条以上。质量永远胜过数量——一条糟糕的示例就会教出一个坏习惯。

微调需要多长时间?

按本指南的设置,在 RTX 3060/4060 级别的 GPU 上,1000 条示例大约 20–60 分钟;在 16GB 的 Apple Silicon Mac 上为 20–40 分钟。更大的数据集呈线性增长:1 万条示例是一夜的训练,而不是一个周末。

微调会给模型添加新知识吗?

不可靠——微调改变的是模型*如何*作答,而不是它*知道什么*。要让模型基于你的文档或当前事实作答,请改用 RAG(检索增强生成),或两者结合:用 RAG 提供事实,用微调提供口吻。

相关指南

← 所有指南 | 检查 GPU 兼容性