DAY 12 / PHASE 1 · ENGINEERING

Fine-tuning vs Prompting

ROI 决策树 · LoRA/QLoRA · 数据集质量 · 解码参数

2026-05-27 · BigCat

2026 年了,「该不该 fine-tune」仍是大多数 AI 工程师过早做的决定。这一期把决策门槛、LoRA 真实工程成本、50 条数据干掉 50K、temperature/top-p 反直觉行为一次说穿。

// WHY THIS MATTERS

2026 年的 fine-tuning 已经不是 2023 年了。LoRA 已成默认(HuggingFace PEFT、Unsloth、Axolotl 一行启动),QLoRA 让 70B 在单卡 4090 上能训,开源模型(Llama 3.3、Qwen 3、DeepSeek V3)多个任务上和 Claude 4.x / GPT-5 差距小到生产可换。但大多数团队仍在错的时机 fine-tune——RAG 没做完就开训、数据集 50K 条噪声不去重、训完发现 prompt + few-shot 就能达到同样效果、推理参数从来没调过。这一期假设你知道 fine-tuning 是什么(ai-ml-daily Day 2 讲过),不重复定义;直接讲 4 个决定 ROI 的工程层:① 何时该 FT 的决策树 → ② LoRA/QLoRA 配置的真实权衡 → ③ 数据集质量为何 10 倍碾压数量 → ④ 解码参数的反直觉行为。重点:fine-tuning 不是「让模型变聪明」,是把分布锁定到你的子空间——理解这点 80% 的误用就避开了。

AI 能力获取的 ROI 阶梯(从便宜到昂贵) 问题:模型在我的场景下表现不够好 │ ▼ ┌─────────────────────────────────────────────────────────┐ │ ① 换更好的 prompt / system prompt 成本:0 │ │ XML 结构、few-shot examples、CoT、role 时间:1 小时 │ └─────────────────────────────────────────────────────────┘ │ 不够好 ▼ ┌─────────────────────────────────────────────────────────┐ │ ② 加 RAG / Tool use 成本:$ │ │ grounding、外部知识、工具调用 时间:1-3 天 │ └─────────────────────────────────────────────────────────┘ │ 仍不够好 ▼ ┌─────────────────────────────────────────────────────────┐ │ ③ 换更大 / 更强的模型 成本:$$ │ │ Haiku → Sonnet → Opus;GPT-mini → GPT-5 时间:5 分钟│ └─────────────────────────────────────────────────────────┘ │ 已用顶级模型仍不够 ▼ ┌─────────────────────────────────────────────────────────┐ │ ④ Few-shot + structured output 成本:$ │ │ 动态 example 选择、JSON schema、CFG 时间:1 天 │ └─────────────────────────────────────────────────────────┘ │ 模式真的稳定不出 prompt 区 ▼ ┌─────────────────────────────────────────────────────────┐ │ ⑤ Fine-tune (LoRA → full) 成本:$$$$ │ │ style/persona/格式/小模型蒸馏 时间:1-4 周│ └─────────────────────────────────────────────────────────┘ 90% 的「需要 fine-tune」其实卡在 ①②③④ 没做满。 ⑤ 真正适用:style transfer / 私有数据 / on-device 蒸馏 / latency 极限
// 01

决策框架:Fine-tuning 是最后一步,不是第一步

论断:80% 的 fine-tune 在工程上是过早优化——团队没把 prompt + RAG + 换模型 + few-shot 这四步做满就跳到训练。Fine-tuning 真正不可替代的场景只有 5 个:style/persona、格式严格化、私有领域知识压缩、小模型蒸馏、超低延迟约束。其余都该回退到上游。

背景与原理

Fine-tuning 的本质是把模型的输出分布锁定到你提供的样本子空间——不是「教会新知识」(事实记忆要 100K+ 样本才稳)、也不是「提升智能」(base capability 由 pretraining 决定)。这一句澄清掉,大部分误用就消失了:你想让模型「更准确地回答专业问题」?这是知识检索问题,FT 不如 RAG;你想让模型「逻辑更强」?这是 base model 选型问题,换 Opus 4.7 / GPT-5 比 FT 一个 Llama 3 8B 强 10 倍;你想让模型「按某种风格说话」「严格输出 JSON」「模仿一个角色」?这才是 FT 的甜点

OpenAI / Anthropic 工程文档(2024-2025)反复强调同一原则:先 prompt,再 RAG,再换模型,最后 fine-tune。Anthropic 在 Claude 文档里直接写「almost always prefer prompting over fine-tuning」——不是因为 FT 不能用,而是 FT 的边际收益曲线陡降:第一周 RAG 调优能涨 30% accuracy,第一周 FT 通常涨 5-10%,但 FT 还要付 eval 成本、数据成本、维护成本、版本管理成本、模型托管成本。

那 FT 真正应该做的 5 个场景:(1)Style/persona——用 100-500 条对话样本让小模型说话像某个品牌,prompt 几乎做不到;(2)格式严格化——某个 schema 要 100% 不破,FT 比 constrained decoding 通用性更好;(3)蒸馏——把 Claude Opus 在某任务上的输出训进 Llama 8B,推理成本降 50-100 倍;(4)私有领域 token 分布——医学/法律/代码私库等子语言,FT 后 perplexity 显著下降;(5)延迟/隐私硬约束——必须在 7B 本地模型上跑、必须不出公司网络。其他场景几乎都该回退到 prompt + RAG。

哪个手段适合哪个问题(决策矩阵) 问题类型 首选 次选 FT? ────────────────────────────────────────────────────────────── 事实知识不够 RAG 换模型 ✗ 推理能力不够 换模型 CoT ✗ 特定格式 / JSON 输出 prompt+CFG FT 条件 特定风格 / 品牌口吻 few-shot FT ✓ 特定 persona / 角色对话 few-shot FT ✓ 超低延迟 / 本地推理 蒸馏 FT 量化 ✓ 私有领域语言 (医/法/code) RAG + FT RAG ✓ 减少 hallucination RAG + cite prompt ✗ 跨语种 换模型 prompt 条件 Agent 工具调用准确率 prompt + few-shot ✗ Tone 一致 / 减少冗长 prompt FT 条件 超大上下文 (1M+) long-ctx RAG ✗ → FT 真正不可替代只占 ~20% 的工程问题

实战示例

20 行的「该不该 FT」自检脚本——开训前必跑:

# pre_ft_check.py —— 训练前的 ROI sanity check
def should_finetune(task) -> str:
    checks = {
        "prompt_optimized":
            task.has_xml_structure and task.has_few_shot >= 3,
        "tried_bigger_model":
            task.tested_on_top_tier_model,  # Opus 4.7 / GPT-5
        "rag_attempted":
            task.is_knowledge_task <= task.has_rag,
        "have_eval_set":
            len(task.eval_examples) >= 50,
        "data_quality_audited":
            task.dataset_inspected_manually,
        "baseline_metric_known":
            task.prompt_baseline_score is not None,
    }
    failed = [k for k,v in checks.items() if not v]
    if failed:
        return f"❌ DO NOT TRAIN. Fix first: {failed}"

    # 5 个 FT 真正适合的场景
    valid_reasons = {"style_persona", "strict_format",
                     "distillation", "private_domain",
                     "latency_hard_constraint"}
    if task.motivation not in valid_reasons:
        return f"⚠️  Motivation '{task.motivation}' rarely benefits from FT. "\
               f"Re-evaluate via prompt/RAG first."

    # ROI 估算:FT 收益必须 >= 3x prompt 收益才划算
    expected_gain = task.eval_target - task.prompt_baseline_score
    if expected_gain < 0.15:
        return "⚠️  Expected gain < 15pp. FT ops cost likely outweighs benefit."
    return "✅ Proceed. Use LoRA r=16 baseline; full FT only if LoRA insufficient."
失败模式:(1)「我们的 prompt 已经很长很复杂了,所以肯定优化到头了」——长 ≠ 好;多数过长 prompt 删一半 + 加 3 个 few-shot 反而升 accuracy;(2)「RAG 太慢,所以 FT」——RAG 的 retrieval 延迟通常 100ms,FT 模型本身推理延迟可能更高;先看 token 而不是猜;(3)训完没 eval set——FT 后比训前差 5% 你都发现不了,等用户反馈才知道;(4)数据从生产直接抓不审计——把 PII、错误回答、用户骂模型的 reply 全训进去;(5)一上来就 full fine-tune——LoRA 没试就跳 full,工程成本翻 20 倍而很少有相应收益。
进阶资源 · Anthropic When to fine-tune Claude (vs prompt), docs.claude.com/.../prompt-engineering · OpenAI Fine-tuning best practices, platform.openai.com/docs/guides/fine-tuning
// 02

LoRA / QLoRA:rank、target_modules、alpha 的真实权衡

论断:LoRA 的「神秘旋钮」rank/alpha/target_modules 不是玄学。rank 是容量、alpha 是学习率乘子、target_modules 是覆盖面——三者各有反直觉的 sweet spot,多数 tutorial 给的默认(r=8, alpha=16, q_proj+v_proj only)对大多数任务都偏保守。

背景与原理

LoRA(Hu et al. 2021)的核心:冻结基础权重 W,加一对低秩矩阵 ΔW = B·A(A 是 r×d,B 是 d×r,r ≪ d),只训 A、B。参数量从 100% 降到 0.1-2%,显存从 80GB 降到 6-12GB。QLoRA(Dettmers et al. 2023)再加一招:base 模型用 4-bit NF4 量化常驻显存,前向反向时按需 dequantize——70B 模型在单张 4090(24GB)能训,是 2023 年最重要的工程突破之一。

三个核心旋钮的真实行为:

QLoRA 一个易忽视的细节:4-bit 量化只在前向推理时存在,反向梯度计算回到 bf16——所以「量化损失」不会进梯度,loss 曲线和 LoRA 几乎一致。但推理时如果直接用 4-bit base + LoRA adapter 部署,会比训练时多一层量化噪声——生产推理建议 merge 后用 bf16 或 8-bit GPTQ/AWQ,不要直接拿训练时的 4-bit 状态发布。

LoRA 参数 sweet spot(按任务类型) 任务类型 rank alpha target_modules data size ────────────────────────────────────────────────────────────────── Style / persona 8-16 r q,v 或 all_linear 100-1000 Format 严格化 16 r all_linear 500-5000 小模型蒸馏 (Opus→8B) 32-64 r all_linear 10K-100K 领域适配 (医/法/code) 64-128 r all_linear 10K-1M Instruction tune 32 r all_linear 5K-50K 反例(常见错误默认): r=8, alpha=16, target=[q_proj,v_proj], data=未审计 → 多数任务上欠拟合 + 训练时间 60% 浪费在错的层

实战示例

Unsloth(2026 年 LoRA/QLoRA 性能最高的开源训练栈,比 HF PEFT 快 2-5x、显存省 60%)的最小可工作配置:

from unsloth import FastLanguageModel
from trl import SFTTrainer
from transformers import TrainingArguments

# —— 加载 4-bit 量化 base(70B 在单卡 4090 可训)——
model, tok = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Meta-Llama-3.3-70B-Instruct-bnb-4bit",
    max_seq_length = 4096,
    load_in_4bit = True,           # QLoRA: 4-bit NF4 量化
)

# —— LoRA adapter 配置:稳态默认 ——
model = FastLanguageModel.get_peft_model(
    model,
    r = 32,                          # 蒸馏/能力任务推荐 32-64
    lora_alpha = 32,                 # alpha = r,不要 2r
    target_modules = [               # all_linear,不要只 q,v
        "q_proj", "k_proj", "v_proj", "o_proj",
        "gate_proj", "up_proj", "down_proj",
    ],
    lora_dropout = 0.05,              # 小数据集开 0.05-0.1,大集开 0
    use_gradient_checkpointing = "unsloth",
    random_state = 42,
)

trainer = SFTTrainer(
    model = model,
    train_dataset = dataset,         # 见 #03,质量>数量
    tokenizer = tok,
    max_seq_length = 4096,
    args = TrainingArguments(
        per_device_train_batch_size = 2,
        gradient_accumulation_steps = 8,   # effective batch=16
        warmup_steps = 10,
        num_train_epochs = 2,              # LoRA 多数任务 1-3 epoch
        learning_rate = 2e-4,              # LoRA 标准 2e-4,比 full FT 高 10x
        bf16 = True,
        logging_steps = 5,
        optim = "adamw_8bit",            # 显存再省 40%
        weight_decay = 0.01,
        lr_scheduler_type = "cosine",
    ),
)
trainer.train()

# —— 生产部署:merge 后用 bf16 / 8-bit,别直接发布 4-bit + adapter ——
model.save_pretrained_merged("./merged", tok, save_method = "merged_16bit")
失败模式:(1)alpha = 2r 是 PEFT 默认但已被多次复现为次优——尤其在 r ≥ 32 时,alpha > r 让 LoRA 矩阵幅度过大,常见症状是训练 1 epoch 后 loss 跳水但 eval 反而崩;改 alpha = r 解决;(2)只训 q_proj, v_proj 然后觉得 LoRA「没效果」——MLP 层(gate/up/down)占模型参数 60%+,不训等于放弃大半容量;(3)learning rate 复用 full FT 的 2e-5——LoRA 应当用 1e-4 到 5e-4,低了根本学不动;(4)4-bit 训练直接 4-bit 部署——多了一层量化误差,eval 掉 2-5%;正确做法是 merge 后 bf16 或 8-bit 部署;(5)QLoRA 训练时 batch_size 拉太大爆显存——QLoRA 的显存瓶颈在 activation 而不是权重,要靠 gradient checkpointing + 小 micro batch + 大 accumulation。
进阶资源 · Hu et al. LoRA: Low-Rank Adaptation of LLMs (ICLR 2022), arxiv.org/abs/2106.09685 · Dettmers et al. QLoRA: Efficient Finetuning of Quantized LLMs (NeurIPS 2023), arxiv.org/abs/2305.14314 · Raschka Practical Tips for Finetuning LLMs Using LoRA, magazine.sebastianraschka.com/.../lora-tips · Unsloth docs, docs.unsloth.ai
// 03

数据集:50 条高质量 > 50,000 条噪声

论断:fine-tuning 的最大杠杆不在算法、不在 rank、不在模型——在数据集。LIMA / Zephyr / Tülu 系列论文反复证明:1000 条人精挑的样本,超越 100,000 条网上抓来的;distillation 数据比人工标注 cheaper + better。数据集是 fine-tuning 的 90%,剩下 10% 是配置。

背景与原理

LIMA(Meta 2023)是这个原则的标杆:用 1000 条人工精挑的对话样本 fine-tune Llama 65B,效果在人评测上 43% 优于 DaVinci-003、46% 优于 Bard(早期版本)。对比当时主流做法(FLAN-T5 那种百万条指令数据),数据量小 1000 倍、效果反而更好。原因:fine-tuning 在 instruction-tune 阶段不是教知识,是解锁已有能力 + 锁定回答格式——你给的样本数 quality 决定锁定到什么质量的子空间。喂噪声 = 锁到噪声子空间。

2024 年延续这条线:Zephyr-7B 用 distillation(GPT-4 输出当老师)+ DPO 偏好对齐打败了同等大小的人工标注模型;Tülu 3(Allen AI 2024)系统消融证明数据筛选 > 数据规模——去重、去 hallucination 标注、按难度采样,比单纯堆量提升大得多。

三个数据工程铁律:

有一个反常识结论:数据集越小,质量门槛越高。LIMA 1000 条里每条都被作者人工挑过;Tülu 3 把噪声率压到 <1%。你的 500 条数据如果有 5% 是错的,等于 25 条强反例直接污染——比 50000 条 5% 噪声里 25 条反例的相对权重大 100 倍。所以小数据 + 严挑 是更难而不是更简单的工程。

数据集质量 vs 数量(典型曲线) Eval accuracy │ 85% ┤ ╭──────━━━━━━━ 1000 条精挑 (LIMA 风格) │ ╭─╯ 80% ┤ ╭──╯ │ │ 75% ┤ │ ╭━━━━━━━━━━ 50K 条混杂 (生产抓取) │ │ ╭──╯ 70% ┤ │ ╭───╯ │ │ ╭───╯ 65% ┤ ╰───╯ │ └─────────────────────────────────────────────► 100 1K 10K 100K data size → 同样 80% accuracy:1K 精挑 ≈ 50K 混杂(成本差 50 倍) → 100K 混杂经常打不过 1K 精挑(过拟合到噪声分布)

实战示例

distillation + 去重 + 质量审计的最小可运行 pipeline(Anthropic + sklearn):

import anthropic, json, hashlib, random
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

client = anthropic.Anthropic()

# —— Step 1: 用 Claude Opus 4.7 蒸馏出高质量训练目标 ——
def distill(user_query: str) -> str:
    msg = client.messages.create(
        model="claude-opus-4-7",
        max_tokens=800,
        system="You are answering as the production assistant. Be precise, "
               "non-redundant. Refuse politely if uncertain. Output only the reply.",
        messages=[{"role":"user","content":user_query}],
    )
    return msg.content[0].text

# —— Step 2: 语义去重(SemDeDup 简化版)——
def dedupe(samples, threshold=0.92):
    texts = [s["prompt"] + " " + s["completion"] for s in samples]
    vec = TfidfVectorizer(max_features=20000).fit_transform(texts)
    sim = cosine_similarity(vec)
    keep, seen = [], set()
    for i in range(len(samples)):
        if i in seen: continue
        keep.append(samples[i])
        for j in range(i+1, len(samples)):
            if sim[i,j] > threshold: seen.add(j)
    return keep

# —— Step 3: Claude-as-judge 质量审计(自动拒绝低质样本)——
def audit(sample) -> bool:
    msg = client.messages.create(
        model="claude-haiku-4-5-20251001", max_tokens=10,
        messages=[{"role":"user", "content":
          f"Rate this Q&A pair on factual correctness, format integrity, "
          f"and helpfulness. Output ONLY one of: GOOD / BAD.\n\n"
          f"Q: {sample['prompt']}\nA: {sample['completion']}"}]
    )
    return "GOOD" in msg.content[0].text.upper()

# —— Step 4: 人工抽样确认(无法自动化的最后一道闸)——
def human_sample_review(dataset, n=50):
    """随机 50 条打到本地 JSON,人眼过一遍。<95% 通过整批弃用"""
    sample = random.sample(dataset, min(n, len(dataset)))
    json.dump(sample, open("audit_sample.json","w"), indent=2, ensure_ascii=False)
    print("Open audit_sample.json. Pass rate < 95% → abort training.")

# —— 全流程 ——
queries = load_real_user_queries(n=2000)              # 真实生产 query
raw = [{"prompt":q, "completion":distill(q)} for q in queries]
deduped = dedupe(raw)                                  # ~1200 条
clean = [s for s in deduped if audit(s)]          # ~900 条
human_sample_review(clean)                             # 你亲眼看 50 条
# 最终 ~900 条 = 比 50K 抓取数据集 train 得更好
失败模式:(1)不去重——FAQ 前 10 个问题占 60% 训练样本,模型只学会回答这 10 个;(2)混入模型本身的失败回答——很多团队从「客服日志」抓数据,里面用户说「这个回答不对」的部分被全部训了进去;必须按 user feedback / thumbs-up 过滤;(3)distillation 时老师模型不固定——上周用 Claude Sonnet、本周用 GPT-5 出 distill,style drift 进训练集,模型学不出稳定 voice;(4)合成数据没有 ground truth 校验——LLM 蒸馏的回答 5-10% 是错的,直接当 label 训等于教模型编;至少用一个独立 LLM 做 judge;(5)忽视负样本——只训正确回答,模型不知道什么时候该拒答;要混入 5-15% 「不知道 / 拒答」的样本(也叫 I-don't-know data)。
进阶资源 · Zhou et al. LIMA: Less Is More for Alignment (NeurIPS 2023), arxiv.org/abs/2305.11206 · Lambert et al. Tülu 3: Pushing Frontiers in Open Language Model Post-Training (2024), arxiv.org/abs/2411.15124 · Abbas et al. SemDeDup: Data-efficient learning via semantic dedup (2023), arxiv.org/abs/2303.09540 · Tunstall et al. Zephyr: Direct Distillation (2023), arxiv.org/abs/2310.16944
// 04

解码参数:temperature、top-p、min-p 的反直觉行为

论断:FT 训完发现模型「不稳」「偶发胡说」「输出冗长」——80% 是解码参数没调,不是模型问题。temperature/top-p/min-p/repetition_penalty 的相互作用反直觉,多数 API 默认值(temp=1, top_p=1)是面向 chat 体感而不是面向工程稳定性的,生产环境必须调。

背景与原理

解码 = 把模型输出的 logits(vocab 上的分布)转成具体 token 的过程。LLM 内部本来知道「下一个 token 90% 是 A、5% 是 B、5% 是其它」——是解码策略决定你拿到什么。三个核心参数的精确行为:

FT 后的解码参数比 base 模型更关键,因为 FT 把分布锁紧——T=1 时 base 模型的 top-10 token 概率可能是 [20%, 15%, 10%, ...],FT 后变成 [85%, 5%, 3%, ...]。这种情况下 top_p=0.9 几乎只让 top-1 通过,等价 greedy;T=0.7 反而把 5% 的 token 概率放大到 15%,引入本来不应该有的随机性。FT 后降 temperature、用 min-p、低 repetition_penalty 是稳态。

解码参数生产建议(FT 后模型) 场景 temp top_p / min_p rep_penalty ────────────────────────────────────────────────────────────── Code / JSON tool 0.0 top_p=1 (no-op) 1.0 Structured extract 0.0 top_p=1 1.0 RAG 严肃问答 0.2 min_p=0.1 1.05 Chat / Persona 0.7 min_p=0.05 1.05-1.1 Creative / 写作 0.9 min_p=0.05 1.1 Brainstorm 多样 1.0 min_p=0.02 1.0 反例(常见 prod 默认): temp=1.0, top_p=1.0, rep_penalty=1.0 → 等价于全无控制;FT 后小模型很容易飘 / 重复 / 偶发胡说

实战示例

FT 后小模型的稳态解码配置(vLLM / OpenAI 兼容 API):

from openai import OpenAI

# vLLM serve 起来的本地 endpoint
client = OpenAI(base_url="http://localhost:8000/v1", api_key="x")

# —— 生产配置:JSON 严格输出场景 ——
resp = client.chat.completions.create(
    model = "merged-llama-3.3-8b-ft",
    messages = msgs,
    temperature = 0.0,            # 完全确定性,不要随机
    top_p = 1.0,                  # T=0 时 top_p 无意义,给 1.0 表明态度
    max_tokens = 512,
    response_format = {"type": "json_schema",
                       "json_schema": my_schema},  # 结构强约束
    extra_body = {                   # vLLM 扩展
        "repetition_penalty": 1.0,
        "min_p": 0.0,
    },
)

# —— 生产配置:Persona / chat 场景 ——
resp = client.chat.completions.create(
    model = "merged-llama-3.3-8b-ft",
    messages = msgs,
    temperature = 0.7,
    top_p = 1.0,                  # 关掉 top_p,让 min_p 接管
    max_tokens = 1024,
    extra_body = {
        "min_p": 0.05,              # 比 top_p 更鲁棒
        "repetition_penalty": 1.05, # 防卡词,但不要 > 1.1
    },
)

# —— 监控:把 logprob 也抓回来,用来定位「为什么模型在这里飘了」 ——
resp = client.chat.completions.create(
    model = "merged-llama-3.3-8b-ft",
    messages = msgs,
    temperature = 0.2,
    logprobs = True,
    top_logprobs = 5,             # 每步看 top-5 候选 + 概率
    max_tokens = 200,
)
for token in resp.choices[0].logprobs.content:
    # top-1 概率 < 0.5 = 模型在「犹豫」,是 hallucination 高风险点
    if token.logprob < -0.7:   # exp(-0.7) ≈ 0.5
        print(f"⚠️  uncertain at: {token.token}",
              [(t.token, f"{2.718**t.logprob:.2f}")
               for t in token.top_logprobs])
失败模式:(1)temperature=1 配 top_p=1——这是 OpenAI/Anthropic SDK 的默认,但对 FT 后模型几乎是「不稳定」的代名词;生产场景至少改一个;(2)用 temperature 控制「创意」——T 不是 creativity dial,它是「分布锐度」dial;要更有创意正确做法是改 prompt(提供风格、添加随机种子词),不是无脑拉 T;(3)repetition_penalty > 1.2——强制不用刚出现过的 token,对长输出会破坏自然语法,看似「不重复」其实是退化;1.05-1.1 是甜点;(4)code / JSON 场景用非 0 temperature——结构化输出靠 0 温度 + grammar/JSON schema,开温度等于自找 bug;(5)seed 没固定——FT 完做 A/B eval,没固定 seed → 同样输入两次结果不同,eval 数字没意义;vLLM/OpenAI 都支持 seed,必固定。
进阶资源 · Holtzman et al. The Curious Case of Neural Text Degeneration (Nucleus / top-p), arxiv.org/abs/1904.09751 · Nguyen et al. Min-p Sampling: Balancing Creativity and Coherence, arxiv.org/abs/2407.01082 · vLLM Sampling parameters, docs.vllm.ai/.../openai_compatible_server

// 综合实战 · 从 prompt 到 FT 的两周决策路径

假设你手上一个真实生产问题,模型表现不够好。按 ROI 顺序两周决定要不要 FT:

  1. Day 1 · 建 eval set(半天,最关键的一步):写 50-100 条带标准答案的 eval 案例。没有 eval 就停下来;后面所有改动都靠 eval 数字判优劣。
  2. Day 1-2 · Prompt 拉满:XML 结构化 system prompt + 3-5 个 few-shot + CoT(如果是推理任务)。跑 eval,记基准。
  3. Day 3 · 换更强模型:Sonnet → Opus;GPT-5-mini → GPT-5。多数情况下 +10-20pp accuracy,比 FT 一周快得多。如果换模型已够,到此为止。
  4. Day 4-5 · 加 RAG(若是知识任务):按 Day 10 的 hybrid + reranker 配置上一套。再跑 eval。
  5. Day 6 · 调解码参数:温度从 1 降到 0.2-0.7,加 min_p=0.05,rep_penalty=1.05。这一步 0 成本,但常被忽略。
  6. Day 7 · 决策点:现在的 eval 数字 vs 目标差多少?差 < 10pp → 继续 prompt/RAG 微调;差 > 15pp 且属于 style/persona/格式/蒸馏 5 种合适场景 → 进入 FT 阶段。
  7. Day 8-10 · 数据集:用 Claude Opus 4.7 蒸馏 800-2000 条 → 去重 → judge 审计 → 人工抽 50 条审。这一步比训练本身耗时。
  8. Day 11-12 · 训练:Unsloth + QLoRA + r=32, alpha=32, all_linear,2 epoch。Llama 3.3 8B 在 4090 上 4-8 小时一轮。
  9. Day 13 · Merge + 部署:Merge LoRA 回 bf16,vLLM serve。一定要重新跑完整 eval,对比 baseline。
  10. Day 14 · 长尾观察:生产 shadow traffic 跑 1 天,看真实分布下是否有 regression。没问题再切流量。

两周走完这条路径——FT 不是「我先训了再说」,是「我已经把上游 4 层做满、确认收益曲线仍陡、然后用最便宜的 LoRA 走最少的训练周期」。这才是 2026 年 fine-tuning 的工程姿势。多数团队走到 Day 6 就发现根本不需要 FT。

// ENGLISH GLOSSARY

Fine-tuning
在 pretrained model 上用特定数据集继续训练;用来锁定输出分布或蒸馏到小模型。
LoRA (Low-Rank Adaptation)
冻结主权重、只训低秩 adapter 矩阵的 PEFT 方法;显存降 90%。
QLoRA
把 base model 4-bit 量化后再做 LoRA;70B 单卡可训。
PEFT (Parameter-Efficient Fine-Tuning)
只更新少量参数的微调家族;LoRA/IA³/Prefix tuning 等。
Rank (r)
LoRA 的低秩矩阵维度;容量旋钮,但非越大越好。
Alpha
LoRA 的 scaling 因子;实际作用是学习率乘子(alpha/r)。
target_modules
LoRA 要插入的层;建议训 all_linear 而非只 q,v。
Distillation
用大模型的输出当训练目标训小模型;2024 后开源模型主流策略。
LIMA
Meta 2023 论文;1000 条精挑数据 > 100K 抓取数据的最佳示例。
SemDeDup
基于 embedding 相似度的语义去重方法。
DPO (Direct Preference Optimization)
用偏好对比数据直接优化策略,无需 reward model;RLHF 的轻量替代。
Temperature
解码采样参数;softmax 前除 T,控制分布锐度。
Top-p / Nucleus sampling
累计概率截断的 token 池采样;高 T 时容易引入噪声。
Min-p
按相对最高概率比例剪枝的采样;比 top-p 鲁棒。
Repetition penalty
对已出现 token 的 logit 惩罚;防卡词,但 > 1.2 会破坏语法。
Merge (LoRA merge)
把 LoRA adapter 矩阵融回 base 权重,得到独立 checkpoint。

// 深入思考

如果 prompt + RAG + 换模型几乎能搞定 80% 工程问题,为什么开源社区还在拼命发布 fine-tune 模型?背后的真实驱动是什么?
三个力学。(1)所有权 / 可控性:FT 出的模型权重在自己手里,不受 API 厂商限速、不涨价、不下线;这是企业级用户的真需求,prompt+RAG 解决不了。(2)蒸馏经济学:把 Claude Opus 在自己业务上的智能压进 Llama 8B,推理成本从 $15/M tokens 降到 $0.2/M——这是 5-100 倍的单位成本下降,规模一上来 FT 是必须的。(3)研究价值:FT 是开源社区证明「我们能跟上」的核心活动,模型卡片本身就是品牌;DeepSeek、Qwen、Mistral 的影响力一大半来自持续放出新 FT。这三个驱动在 2026 年都没有变弱,所以「prompt 优先」并不矛盾于「FT 仍是关键能力」——只是谁来 FT变了:以前是每个团队,现在是少数有规模的团队 + 开源社区,剩下的人用别人 FT 出的模型 + prompt。
LIMA 用 1000 条数据打败 100K 条这个事实,到 GPT-5 / Claude 4.7 时代还成立吗?还是只在 base model 较弱的时代才有效?
更成立而不是更不成立。LIMA 的本质洞察是「instruction tuning 是 unlock 而不是 teach」——base model 越强,能 unlock 的能力越多,少量高质量样本的杠杆就越大。Tülu 3(2024)在 Llama 3 上复现 LIMA 风格的小数据高质量 SFT,accuracy 比 2023 年的 LIMA 高一档;Zephyr / Phi-3 / Qwen-Distill 都在用类似策略。反方向论据是 Llama 3.1 / 3.3 / Qwen 3 等大厂 instruct 模型仍用百万级数据——但他们的目标不一样(覆盖全 long tail 任务),不能直接对比单业务 FT。结论:你的业务 FT 用 500-5000 条精挑数据 + distillation 是 2026 年的最优实践,base model 越强这个策略越占优。
QLoRA 让 70B 在单卡能训,但推理仍要多卡——这个「训得起、用不起」的不对称,对独立开发者意味着什么?
这个不对称是 2024-2026 年最被低估的开发者经济学转折。训:QLoRA 让你能在 24GB 卡(4090, A10)上 fine-tune 70B 模型,6-12 小时一轮训练,全自己掌控。用:70B 推理需要 80GB+ 显存(4-bit 也要 40GB),单卡 H100 才能跑起来,按 hour billing。所以独立开发者的可行路径其实是:训大模型 + 蒸馏到小模型 + 部署小模型。具体说:用 QLoRA 把 70B 在你的领域上训好,然后用这个 70B 当老师,distill 出 7B/8B 学生模型——8B 可以在 16GB 卡或 Mac M-series 上跑推理,推理成本骤降。这条「训大用小」的路线把训练算力和推理算力解耦,让一个独立开发者也能拥有定制模型 + 可部署的完整 stack。未来 3 年这会是个人 AI 工程师最重要的护城河之一。
解码参数(temperature、top-p、min-p)为什么没有像 LoRA 那样「卷出最优默认」?为什么生产团队还需要手调?
因为最优解码取决于任务而非模型。LoRA 的最优 rank/alpha 大体上是模型架构的函数,可以「卷出公认默认」;解码不是——同一个 FT 后的 Llama 8B,做 code 时要 T=0、做 chat 时要 T=0.7、做 brainstorm 时要 T=1。任务空间无限大、参数交互非凸(T 和 top_p 的组合效应是非线性的),没有单一默认能覆盖。所以模型厂商的 API 默认(T=1, top_p=1)是偏向 chat 体感的「最不出错」选项,但对生产工程几乎一定不是最优。中期看会出现 auto-tune decoding:根据 prompt 类型自动选解码参数(类似 GPT-5 的「reasoning effort」按问题难度自动调),但 2026 年仍是手动工程。学会调解码参数是 LLM 工程师的基本功,跟「会写 SQL index」一个量级。
如果 2027 年开源 7B 模型在大多数业务任务上和 Claude 4.x 几乎打平,「该不该 FT」的决策树会怎么变?
决策树会反过来。今天的顺序是 prompt → RAG → 换更强模型 → FT,因为换模型的 ROI 最高。当 7B 开源模型已经接近顶级 API 时,「换更强模型」这一步收益骤降——剩下能动的就只有 prompt 和 FT。这时FT 的相对 ROI 大幅提升,因为:(1)模型本身够强,FT 不需要补 base capability,只需要 alignment/style/格式锁定,少量数据就够;(2)私有部署的边际成本几乎为零(开源 + 量化 + 边缘 GPU),推理 cost 不再是约束;(3)数据所有权变成核心竞争力——你的 FT 数据集是别人复制不了的护城河。预测:2027 年「该不该 FT」会从「99% 不该」反转到「业务护城河必须 FT」——但仍是少量高质量数据 + LoRA,不是回到 2023 年的 full FT 时代。FT 永远是工程,永远要走 ROI 决策——只是 ROI 函数本身在变

// 延伸阅读