什么是微调

什么时候用rag,什么时候用微调?
rag: 是为了解决大模型对非公开知识的幻觉问题,是结合外部数据在对话中加入对问题的相关知识,让大模型结合知识做解答,但是本质上大模型对rag知识库是没有学习的,rag的优势是无需训练大模型,仅在应用的时候查询,因此可以实时更新知识库。

  • 实时性
  • 可溯源
  • 无需训练
  • 缺点:增加检索时候的token开销

微调: 可以让大模型学会特定的知识、特性或者风格等,让大模型直接写入到参数,对于相关知识直接结合学习的结果回答,缺点是需要训练成本、无法实时更新等

  • 一次性训练成本
  • 无需检索相关知识,模型直接回答
  • 缺点:训练成本、高质量数据集、重新训练

在企业应用开发中,我们应该优先选择rag来解决幻觉问题,对于垂直细分领域,有特定的风格要求等,再通过微调优化,微调可以使用Lora这样的参数高效方法,几百到上千条数据就能有明显效果,成本和风险都可控。

适合微调的场景:

  • 输出格式要求严格 如json
  • 风格、语气固定
  • 工具调用不准确(如agent场景下,针对性微调可以显著提升工具识别率)
  • 私有术语体系 rag检索到了但是大模型不会,微调可以让大模型学会这些术语和用法

案例: 1、如何做一个客服机器人,知识库每天都会更新,那就适合rag 2、客服机器人必须非常懂礼貌、带特定表情可以考虑使用微调

“RAG 和微调解决的是不同维度的问题。” RAG 解决的是“知识”问题:当模型需要访问私有数据、实时信息或非公开知识时,用 RAG 从外部知识库检索相关内容,让模型基于检索结果回答。优点是知识可更新、可溯源,缺点是检索和生成的链路更长。

微调解决的是“行为”问题:当模型需要稳定输出某种格式、风格、或执行特定任务(比如 function calling)时,用微调来改变模型的输出分布。优点是效果稳定、延迟低,缺点是成本高、知识固化。 在实际项目中,两者通常是互补的。比如一个客服 Agent,我用 RAG 获取产品知识,用微调让模型学会统一的应答格式和工具调用方式。两者结合,既保证了知识的准确性,又保证了交互的稳定性。”

一个常见的误区是‘RAG 和微调二选一’,但实际工程中往往是两者结合。微调让模型学会‘怎么用’RAG 检索到的内容,RAG 为微调后的模型提供实时知识。

微调的原理

微调是在原模型旁边添加一个增量(低秩矩阵),训练时只增加增量部分,原模型不变。
LoRA的优点:

  • 显存小 原模型冻结 秩存adapter的梯度
  • 可插拔 多个adapter可切换使用
  • 训练快 参数少 收敛快
  • 不破坏原模型 保留基座模型的通用能力

使用LoRA做参数高效微调,核心是冻结原模型的所有参数,在原模型旁加入两个低秩矩阵A和B,训练时只更新这两个小矩阵。这样显存的占用大幅降度,训练速度快,而且可以训练多个adapter针对不同场景 切换使用,QLoRA进一步结合4-bit量化,能在一阵24G的显卡上微调70B模型

低秩是什么? 为什么能减少参数?

举个例子,原模型的权重矩阵是 W(比如 4096×4096),LoRA 引入 B×A,其中 A 是 4096×8,B 是 8×4096。这样训练参数从 1600 万降到了 6.5 万,减少了 99% 以上。

最终的计算是 W·x + B·A·x,相当于在原模型的基础上做了一个‘轻量级调整’。因为参数少、显存小,而且可以训练多个 adapter 随时切换,所以在工业界很常用。”

数据与流程

数据格式:

  • Alpaca数据集是一个指令微调数据集,格式如下:
    {
    "instruction": "将以下句子翻译成英文",
    "input": "今天天气很好",
    "output": "The weather is nice today"
    }
    
  • ShareGPT 格式(多轮对话):
    {
    "conversations": [
      {"from": "human", "value": "你好"},
      {"from": "gpt", "value": "你好!有什么可以帮助你的?"},
      {"from": "human", "value": "今天天气怎么样?"},
      {"from": "gpt", "value": "抱歉,我无法获取实时天气信息"}
    ]
    }
    

训练流程: 1、准备数据: 按格式整理成json 2、选择基座模型:如Qwen2.5、LLama3等 3、配置LoRA参数:rank=8/16/32,alpha=16,设置target_modules(q_proj,k_proj,v_proj,o_proj) 4、训练启动:使用LLaMA-Factory 、unsloth等 5、评估结果:用验证集看loss 或人工评估生成质量 6、部署:合并adapter或用vLLM动态加载

参数 rank(r) 低秩矩阵纬度 越大表达能力越强 一般设置8 16 32 alpha 缩放因子 一般设置为rank的两倍 target_modules 要加LoRA模块 一般设置为q_proj,k_proj,v_proj,o_proj learning_rate 学习率 一般设置为1e-4 5e-5

微调实践

“微调的主要流程分为 6 步:

  1. 数据准备 先整理数据,通常用 Alpaca 或 ShareGPT 格式。关键是要保证 instruction 足够明确,output 格式完全一致。数据量一般在几百到几千条,按 9:1 划分训练集和验证集,验证集用来监控过拟合。

  2. 基座模型选择 根据任务选择基座模型,中文场景我常用 Qwen2.5-7B 或 Llama 3-8B,因为开源生态好,中文支持强。

  3. 工具选择 我用 LLaMA-Factory,它有 Web UI,配置起来方便。也可以用 unsloth,训练速度更快。

  4. LoRA 参数配置 关键参数:rank 通常设 16,alpha 设 16 或 32,target_modules 选 q_proj 和 v_proj。学习率 2e-4 左右,训练 2-3 个 epoch。

  5. 训练与监控 开始训练后,盯着 loss 曲线,如果验证集 loss 上升而训练集 loss 还在降,说明过拟合了,会提前停止或增加 dropout。

  6. 评估与部署 评估时看格式正确率、关键字段提取准确率,再用 GPT-4 对比微调前后的效果。部署时可以用 vLLM 加载合并后的模型,或者动态加载 adapter 做 A/B 测试。”

微调实战

  • 下载llamafactory
    git clone https://github.com/hiyouga/LLaMA-Factory.git
    cd LLaMA-Factory
    
  • 使用虚拟环境来管理python包依赖 这里使用conda创建一个虚拟环境(或者venv)
conda create -n lamaf python=3.11
conda activate lamaf
# ⚠️如果要 退出虚拟环境 执行
conda deactivate
# ⚠️如果要 删除虚拟环境 执行
conda env remove -n lf 

# 安装训练所需依赖
pip install -e ".[torch,metrics]"
  • llamafactory目录 data/
    存放训练数据集,每一个数据集是一个json文件,在dataset_info.json中配置数据集的路径和格式。 dataset_info.json中可以设置数据集的配置: file_name是文件路径,默认当前目录,dataset_format可以设置数据集的格式,默认是alpaca格式,如果提供的数据集格式不是常规的格式需要映射 key是固定的,value是数据集中的输入。
    {
    "my_dataset_name": {
        "file_name": "alpaca.json",
        "formatting": "alpaca",
        "columns": {
          "prompt": "instruction",
          "query": "input",
          "response": "output"
        }
      },
    }
    

数据集格式有:

  • Alpaca 格式
  • ShareGPT 格式

examples/
存放不同的训练方式的配置文件,我们使用的是lora微调,可查看文件examples/train_lora/qwen3_lora_sft.yaml

微调参数都在此处配置

saves/
微调完成之后的大模型默认存放位置

src/
llamafactory源码

**启动微调: ** 我们使用 llamafactory-cli train命令来制定参数开始微调,参数配置文件是examples/train_lora/qwen3_lora_sft.yaml,其他参数后续补充。

llamafactory-cli train examples/train_lora/qwen3_lora_sft.yaml
# 如果需要下载模型到本地可以在前面加上以下命令 会在训练前从魔搭社区下载模型
# USE_MODELSCOPE_HUB=1 

⚠️或者也可以用webui页面来查看和执行训练过程

llamafactory-cli webui

启动聊天测试

USE_MODELSCOPE_HUB=1 llamafactory-cli chat examples/inference/qwen3_lora_sft.yaml

qwen3_lora_sft.yaml是配置文件,如下配置了:

model_name_or_path: qwen/Qwen3.5-2B-Base
adapter_name_or_path: saves/Qwen3.5-2B-Base/lora/train_2026-03-24-11-41-33
template: qwen3_5
infer_backend: huggingface
trust_remote_code: true

max_new_tokens: 512
temperature: 0.7
top_p: 0.9
repetition_penalty: 1.1
do_sample: true

参数说明

以下是一些用到的参数说明

  • model_name_or_path:指定要微调的模型路径或名称,如 Qwen/Qwen2.5-7B
  • dataset:指定要使用的数据集名称,需在 dataset_info.json 中配置使用名称。
  • template:指定要使用的模板名称。
  • stage:指定训练阶段,sft 表示指令微调。
  • do_train:是否执行训练,默认 true,如果只是想构建数据集,则设置为false
  • do_eval:是否执行评估,默认 true
  • per_device_train_batch_size:每个设备的训练批量大小,默认 4
  • gradient_accumulation_steps:梯度累加步数,默认 1
  • learning_rate:学习率,默认 2e-4, 为了避免过拟合,建议设置为1e-4 5e-5
  • num_train_epochs:训练轮数,默认 3
  • max_seq_length:最大序列长度,默认 512
  • logging_steps:日志记录步数,默认 10
  • save_steps:模型保存步数,默认 1000
  • output_dir:指定模型输出目录,如 ` saves/qwen3-4b/lora/sft`。

参考