3.1 生成模型选择与微调
📌 本节目标
学完本节后,你将能够区分主流生成模型(如 GPT 系列和 LLaMA 系列)的核心特点,理解为什么在 RAG 系统中“选对模型”比“堆参数”更重要;同时,你会掌握两种最常用的微调策略——全量微调和 LoRA,并知道在什么场景下该选用哪种方法。
1. 核心概念讲解
1.1 什么是生成模型
生成模型是 RAG 系统的“最后一公里”。当检索器从知识库中找回一堆相关文档后,生成模型负责把这些信息组织成自然、流畅的答案。简单说,检索器负责找素材,生成器负责写文章。
比如:你问 AI “什么是量子纠缠?” 检索器去数据库里翻出三篇物理论文,生成模型则把这些论文中的关键句子揉在一起,写成一段你能看懂的解释。
1.2 主流生成模型:GPT vs. LLaMA
目前 RAG 系统中最常用的两类生成模型是 GPT(Closed-source) 和 LLaMA(Open-source)。它们的核心区别在于:
| 特性 | GPT(如 GPT-4, GPT-3.5) | LLaMA(如 LLaMA 2, LLaMA 3) | |------|--------------------------|-------------------------------| | 开源程度 | 闭源,通过 API 调用 | 开源,可本地部署 | | 可控性 | 低,不能修改模型权重 | 高,可自由微调 | | 成本 | 按 token 付费,长期成本高 | 一次性硬件投入,长期成本低 | | 数据隐私 | 数据需传给第三方 | 数据完全本地化 | | 开箱即用 | 极好,无需额外训练 | 较好,但领域知识需微调 |
选择建议:
- 如果你的业务涉及敏感数据(如医疗、金融),或者需要高频调用(每天百万级请求),优先考虑 LLaMA 等开源模型。
- 如果你希望快速验证产品原型,且数据不敏感,直接调用 GPT API 是最省力的方式。
1.3 微调策略:全量微调 vs. LoRA
微调(Fine-tuning)是指在预训练模型的基础上,用你的业务数据再做一次小规模训练,让模型更懂你的领域。
全量微调(Full Fine-tuning):
- 更新模型所有参数
- 效果最好,但计算成本极高(例如微调 70B 参数的 LLaMA 需要多张 A100 GPU)
- 适合有充足算力的大团队
LoRA(Low-Rank Adaptation):
- 冻结原始模型参数,只训练一小部分“适配器”参数
- 参数量仅为全量微调的 0.1%~1%
- 效果接近全量微调,但显存需求降低 8~10 倍
- 当前最主流的微调方式
比如:你想让模型学会回答公司内部的产品问题。全量微调就像给整栋楼重新装修,而 LoRA 就像在每个房间里放一本说明书——效果差不多,但成本天差地别。
下面是一个使用 LoRA 微调 LLaMA 2 的简单代码片段(使用 Hugging Face 的 PEFT 库):
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model, TaskType
# 1. 加载基础模型(以 LLaMA 2 7B 为例)
model_name = "meta-llama/Llama-2-7b-chat-hf"
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 2. 配置 LoRA
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM, # 因果语言模型任务
r=8, # LoRA 秩(rank),通常 8~16
lora_alpha=32, # 缩放系数
lora_dropout=0.1, # 防止过拟合
target_modules=["q_proj", "v_proj"] # 只微调注意力层的 Q 和 V 矩阵
)
# 3. 应用 LoRA
peft_model = get_peft_model(model, lora_config)
# 4. 查看可训练参数数量
trainable_params = sum(p.numel() for p in peft_model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in peft_model.parameters())
print(f"可训练参数占比: {trainable_params / total_params * 100:.2f}%")
# 输出示例: 可训练参数占比: 0.08% —— 几乎可以忽略不计!
2. 深入理解
2.1 为什么生成模型的选择如此关键?
很多初学者以为 RAG 系统中“检索”才是核心,生成模型随便选一个就行。这是一个常见的误区。
实际上,生成模型的质量直接决定了 RAG 系统的最终表现。具体来说:
- 指令遵循能力:好的生成模型能严格遵循“只根据检索到的内容回答,不要编造”的指令。差的模型会“自由发挥”,产生幻觉。
- 上下文窗口:LLaMA 2 的上下文窗口是 4096 tokens,而 GPT-4 是 128K tokens。如果你的检索结果很长,模型窗口不够就会截断关键信息。
- 多轮对话能力:在聊天型 RAG 中,模型需要记住之前的问题和回答。GPT 系列在这方面明显优于早期的 LLaMA。
2.2 微调的本质:不是“教新知识”,而是“教新格式”
初学者常有一个误解:微调是为了让模型记住更多知识。
真相是:微调主要改变的是模型的输出风格和行为模式,而不是增加知识库。知识应该放在检索器的数据库中,而不是塞进模型参数里。
比如:你微调一个法律问答模型,不是为了让模型背下《民法典》全文(那是检索器的活),而是让模型学会“先引用法条,再给出解释”的回答格式,以及使用更严谨的法律术语。
2.3 初学者最常踩的三个坑
-
过度微调导致灾难性遗忘:用 100 条数据微调 10 个 epoch,模型可能把原本的通用能力(如写诗、翻译)忘得一干二净。建议:混合 10%~20% 的通用数据一起训练。
-
忽视数据质量:微调数据如果包含错误答案,模型会“学坏”。建议:宁可只用 500 条高质量数据,也不要用 5000 条粗制滥造的数据。
-
盲目追求大模型:70B 的 LLaMA 效果当然比 7B 好,但部署成本也高了 10 倍。对于大部分 RAG 场景,7B~13B 的模型经过良好微调,已经能胜过未微调的 70B 模型。
3. 实战演示
场景:你正在为一家电商公司构建客服 RAG 系统。你需要比较 GPT-3.5(API)和微调后的 LLaMA 2 7B(本地)在处理退货问题时的表现。
步骤 1:准备测试问题
# 测试问题集
test_questions = [
"我昨天买的手机屏幕有划痕,能退货吗?",
"退货的运费谁出?",
"超过7天无理由退货时间了,还能退吗?"
]
# 期望的回答风格:先引用政策,再给出具体建议
expected_style = "引用政策 → 给出方案 → 提供下一步操作"
步骤 2:调用 GPT-3.5 API
import openai
def query_gpt(prompt):
"""调用 GPT-3.5 API"""
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "你是一个电商客服助手。请根据公司政策回答,不要编造信息。如果不知道,请说'我无法确认'。"},
{"role": "user", "content": prompt}
],
temperature=0.3 # 低温度让回答更稳定
)
return response.choices[0].message.content
# 测试第一个问题
answer_gpt = query_gpt(test_questions[0])
print("GPT-3.5 回答:", answer_gpt)
步骤 3:加载并查询微调后的 LLaMA
from transformers import pipeline
# 加载已微调的 LLaMA 模型(假设你已经用 LoRA 微调过)
model_path = "./llama2-7b-returns-finetuned" # 你的微调模型路径
generator = pipeline(
"text-generation",
model=model_path,
tokenizer=model_path,
device=0 # 使用 GPU
)
def query_llama(prompt):
"""调用微调后的 LLaMA"""
# 构造完整的提示词,包含检索到的政策片段(模拟 RAG 检索结果)
full_prompt = f"""【公司退货政策】
1. 商品不影响二次销售,7天内可无理由退货
2. 质量问题由商家承担运费,非质量问题由买家承担
3. 超过7天但不超过15天,仅限质量问题可退
【用户问题】
{prompt}
【请根据上述政策回答】"""
result = generator(
full_prompt,
max_new_tokens=200,
temperature=0.3,
do_sample=True
)
return result[0]['generated_text'].split("【请根据上述政策回答】")[-1].strip()
# 测试第一个问题
answer_llama = query_llama(test_questions[0])
print("微调 LLaMA 回答:", answer_llama)
步骤 4:对比结果
| 评价维度 | GPT-3.5 | 微调 LLaMA 2 7B | |---------|---------|-----------------| | 回答速度 | 0.8 秒(网络延迟) | 1.2 秒(本地推理) | | 每次调用成本 | $0.002 | $0(仅电费) | | 回答准确性 | 较好,但偶尔泛化 | 严格遵循政策 | | 数据隐私 | 数据出域 | 完全本地 |
结论:对于高频、敏感的业务场景,微调后的 LLaMA 2 7B 虽然推理稍慢,但在成本控制和数据安全上完胜 GPT API。
4. 关键要点
- 选模型先看场景:数据敏感或高频调用选开源(LLaMA),快速验证选闭源(GPT)。
- 微调首选 LoRA:效果接近全量微调,但成本降低 90% 以上,是当前业界标准做法。
- 微调改的是“说话方式”,不是“知识”:把知识放在检索器里,把格式和风格教给生成器。
- 数据质量决定微调上限:500 条高质量数据 > 5000 条噪声数据。
- 不要盲目追求大参数:7B 微调模型在垂直领域往往吊打 70B 通用模型。
✏️ 练习任务
练习方向:比较不同生成模型在 RAG 中的表现
基础任务: 选择一个你感兴趣的垂直领域(如医疗问答、法律咨询、代码助手),完成以下操作:
- 准备 3 个该领域的测试问题(如“高血压患者能喝咖啡吗?”)
- 分别使用 GPT-3.5 API 和 Hugging Face 上的一个开源模型(如
Qwen/Qwen-7B-Chat或mistralai/Mistral-7B-Instruct)生成回答 - 从“准确性”、“回答格式”、“是否引用来源”三个维度对比两者表现
- 用表格记录对比结果,并写一段 100 字左右的总结
进阶挑战(选做):
- 使用
datasets库加载一个开源数据集(如wiki_qa),构建一个简单的 RAG 流程 - 用同样的检索结果,分别喂给不同的生成模型(至少 3 个),计算它们在 ROUGE-L 或 BLEU 指标上的分数
- 分析为什么某些模型在特定类型的问题上表现更好
💡 下一节我们将学习如何把检索器和生成器组装成一个完整的 RAG Pipeline,并解决“检索结果太长导致生成模型截断”的常见问题。
本节由 StudyAI8 AI 课程团队生成并审核。