generative-ai-for-beginners 第 18 课:LLM 微调(Fine-Tuning)原理、决策框架与 OpenAI 实战全流程
本篇技术指南聚焦于生成式 AI 课程第 18 课「微调你的 LLM」。你将理解什么是语言模型微调、它在「提示工程 / RAG」之外的独特价值、何时应当启动微调的完整决策框架,以及一套可复制的 OpenAI 微调实战流程(从 JSONL 训练数据、文件上传、训练任务、事件追踪,到模型 ID 提取与 Playground 对比验证)。学完本篇,你既能建立「是否微调」的工程判断力,也能动手跑通一个真实微调任务。
为什么需要微调:从「改提示」到「重训模型」
大型语言模型(LLM)本身是预训练(pre-trained)模型——它们在来自互联网等海量文本上完成训练。前序课程已经介绍了两类「不改动模型本身、只修改提示输入」来提升响应质量的技术:
- 提示工程(Prompt Engineering):通过指令(显式引导)或示例(隐式引导)来约束模型输出。
- 检索增强生成(RAG):用检索到的数据对提示进行增强。
其中一种流行的提示技巧是「少样本学习」(few-shot learning)——给模型若干示例(指令或示例对)来引导期望输出。但它有两个固有限制:
- Token 上限限制:模型上下文窗口有限,能塞进提示的示例数量受限,从而影响效果;
- Token 成本限制:每次请求都要附带示例,会增加 token 开销,并降低灵活性。
微调(fine-tuning) 正是针对这些痛点的第三种技术路线:它不再修改提示,而是用额外数据对模型本身进行再训练。在语言模型语境下,我们用「面向特定任务或应用领域的精选示例集」来微调预训练模型,产出一个定制模型(custom model)——它对特定任务/领域通常更准确、更相关。附带收益是:微调后模型对少样本示例的依赖下降,从而减少 token 使用与相关成本。
说明:上图是官方为该课绘制的学习路线插图,覆盖七大环节——基础概念、为何微调(Why Fine-Tune)、流程与挑战(数据收集/格式化/训练/评估/迭代/部署)、数据准备、训练与评估、部署与使用、最佳实践。它可作为本文的总览导航。
何时、为何应当微调:一个可落地的决策框架
本课程的「微调」特指监督式微调(supervised fine-tuning)——即通过加入不属于原始训练集的新数据来再训练模型。它与「无监督微调」不同:后者是在原始数据上、用不同超参数重新训练。
需要牢记:微调是一项进阶技术,需要一定专业水平才能拿到理想效果。如果操作不当,它可能无法带来预期提升,甚至降低模型在目标领域的表现。因此,在学「怎么微调」之前,先要回答「为什么」和「何时」开始。官方给出的自检清单如下:
- 使用场景(Use Case):你微调的用途是什么?你希望改进当前预训练模型的哪个方面?
- 替代方案(Alternatives):你是否尝试过其他技术达到相同目标?用它们建立对比基线。
- 提示工程:尝试 few-shot(附相关提示/响应示例),并评估响应质量。
- RAG:尝试用检索到的查询结果增强提示,并评估响应质量。
- 成本(Costs):你识别出微调的成本了吗?
- 可微调性(Tunability)——目标预训练模型是否支持微调?
- 工作量(Effort)——准备训练数据、评估与迭代模型的人力成本。
- 算力(Compute)——跑微调任务、部署微调模型所需的计算资源。
- 数据(Data)——是否能获取足够数量、足够质量的示例来支撑微调效果。
- 收益(Benefits):你确认了微调的收益吗?
- 质量(Quality)——微调模型是否胜过基线?
- 成本(Cost)——是否通过简化提示降低了 token 使用?
- 可扩展性(Extensibility)——能否把基座模型复用到新领域?
决策原则:只有当收益大于成本时,微调才是合理路线。理想情况下,你应当先有基线(提示工程/RAG),再判断微调是否值得投入。
微调一个预训练模型需要哪些要素
官方将微调的「四要素」归纳为:
- 一个可供微调的预训练模型(并非所有基座模型都支持微调,需先确认);
- 一份用于微调的数据集(精选的训练示例);
- 一个可运行微调任务的训练环境;
- 一个可部署微调模型的主机环境。
对应到 OpenAI 平台的完整流程,可拆解为四步:
- 准备训练数据并上传;
- 运行训练任务,得到微调模型;
- 评估微调模型并迭代优化质量;
- 满意后部署微调模型用于推理。
实战:用仓库自带样例跑通一个 OpenAI 微调任务
本仓库在 微调任务 Notebook 中提供了一个可参考的完整样例,配套训练数据见 training-data.jsonl。它要训练一个聊天机器人 「Elle」——用五行打油诗(limerick) 回答元素周期表中某个元素的问题。这是一个刻意简化的「玩具样例」,目的是快速演示流程而非真实生产数据集;真实场景需要大得多的示例集(质量与成本/时间之间的权衡)。
适用前提与重要提示:该 Notebook 的示例输出是在
gpt-3.5-turbo上生成的,而gpt-3.5-turbo如今已同时退出推理与微调(Azure OpenAI / OpenAI 均已弃用)。若你现在要开启一个新微调任务,请改用一个当前受支持的模型(例如gpt-4o-mini或gpt-4.1-mini),并以官方「可微调模型列表」为准。本文的流程与概念仍然适用。
步骤一:准备并上传训练数据
针对 gpt-3.5-turbo 这类单轮(single-turn) 聊天补全场景,训练数据采用 JSONL 格式:每行一条记录,每条记录是一个 JSON 对象,必须写在一行内(不能像普通格式化 JSON 那样拆多行)。样例中一条记录长这样(来自 training-data.jsonl):
{ "messages": [{"role": "system", "content": "Elle is a factual chatbot that answers questions about elements in the periodic table with a limerick"}, {"role": "user", "content": "Tell me about Gallium"}, {"role": "assistant", "content": "Gallium, oh gallium, so light - Melts in your hand, oh what a sight - At 86 degrees - Its liquid with ease - And in semiconductors, it's out of sight"}]}
{ "messages": [{"role": "system", "content": "Elle is a factual chatbot that answers questions about elements in the periodic table with a limerick"}, {"role": "user", "content": "Tell me about Hydrogen"}, {"role": "assistant", "content": "Hydrogen, the first in the line - The lightest of all, so divine - It's in water, you see - And in stars, it's the key - The universe's most common sign"}]}
其中 system 定义助手人设(Elle 用 limerick 回答元素问题),user 是问题,assistant 是期望输出格式。完整样例集共 10 条元素示例(Gallium、Hydrogen、Helium、Boron、Iron、Carbon、Cobalt、Titanium、Silver、Mercury)。
若期望多轮对话内容,则应改用「多轮示例格式」,其中包含一个
weight参数,用于标记哪些消息应(或不应)参与微调过程。本教程为简化起见采用单轮格式。
上传前,需满足两个前置条件(来自 课程本地配置指南):
- 已安装
openaiPython 包(为获得最新特性,使用版本>= 0.28.0); - 已设置
OPENAI_API_KEY环境变量为你的 API 密钥。
随后用 Files API 上传本地 JSONL 文件:
from openai import OpenAI
client = OpenAI()
ft_file = client.files.create(
file=open("./training-data.jsonl", "rb"),
purpose="fine-tune"
)
print(ft_file)
print("Training File ID: " + ft_file.id)
上传成功后会返回一个文件对象(含 id、filename='training-data.jsonl'、purpose='fine-tune'、status='processed' 等字段),记下其中的 File ID 供后续创建任务使用。
步骤二:创建并跟踪微调任务
用 fine_tuning.jobs.create 创建任务,传入训练文件 ID 与目标基座模型:
from openai import OpenAI
client = OpenAI()
ft_filejob = client.fine_tuning.jobs.create(
training_file=ft_file.id,
model="gpt-3.5-turbo"
)
print(ft_filejob)
print("Fine-tuning Job ID: " + ft_filejob.id)
从返回的任务对象可观察到关键信息:hyperparameters 初始为全 auto(n_epochs、batch_size、learning_rate_multiplier 均由平台自动选择),status 初始为 validating_files(平台会先校验训练文件格式)。
client.fine_tuning.jobs 提供一组常用操作,便于管理与监控:
client.fine_tuning.jobs.list(limit=<n>)—— 列出最近 n 个微调任务;client.fine_tuning.jobs.retrieve(<job_id>)—— 获取某个任务的详情/状态;client.fine_tuning.jobs.cancel(<job_id>)—— 取消一个任务;client.fine_tuning.jobs.list_events(fine_tuning_job_id=<job_id>, limit=<b>)—— 列出最多 n 条任务事件。
轮询状态直到训练完成:
# 训练数据校验通过后,跟踪任务状态
response = client.fine_tuning.jobs.retrieve(ft_filejob.id)
print("Job ID:", response.id)
print("Status:", response.status)
print("Trained Tokens:", response.trained_tokens)
也可以以更细粒度方式通过「事件」跟踪进度(反复刷新直到出现 The job has successfully completed 消息):
response = client.fine_tuning.jobs.list_events(ft_filejob.id)
events = response.data
events.reverse()
for event in events:
print(event.message)
事件流会输出每一步的训练 loss(如 Step 85/100: training loss=0.14 … Step 100/100: training loss=0.00)、检查点创建信息(如 Checkpoint created at step 80 with Snapshot ID: ft:gpt-3.5-turbo-0125:...:ckpt-step-80),最终以 New fine-tuned model created: ft:gpt-3.5-turbo-0125:bitnbot::9OFWzNjz 与 The job has successfully completed 收尾。
在 OpenAI 控制台(平台的 Fine-tuning 分区)可可视化查看任务状态、历史运行、训练指标(训练 token 数、epochs、batch size、LR multiplier、seed、checkpoints、训练 loss 曲线等)。该截图同时展示了「上一次因 JSON 记录格式错误而失败、修正后第二次运行成功」的真实经历——这正说明了数据格式正确性是微调成败的关键之一。
步骤三:提取模型 ID 并验证微调效果
任务完成后,先从任务对象里取出微调模型的 ID:
response = client.fine_tuning.jobs.retrieve(ft_filejob.id)
fine_tuned_model_id = response.fine_tuned_model
print("Fine-tuned Model ID:", fine_tuned_model_id)
随后有两种验证方式:
方式一:在代码中直接调用。 用微调后的模型 ID 发起补全请求:
from openai import OpenAI
client = OpenAI()
completion = client.responses.create(
model=fine_tuned_model_id,
input=[
{"role": "system", "content": "You are Elle, a factual chatbot that answers questions about elements in the periodic table with a limerick"},
{"role": "user", "content": "Tell me about Strontium"},
],
store=False,
)
print(completion.output_text)
方式二:在 Playground 中并排对比。 在 Playground 的模型下拉框里选择新微调模型,或直接在微调面板里点击「Playground」入口,会进入一个对比视图(comparitive view),把基座模型与微调模型并排放置,快速评估差异:
填入训练数据中使用的 system 上下文与测试问题,两侧会自动填入相同的上下文与问题。运行对比后可以观察到:微调模型按你示例中提供的格式(limerick 结构)渲染响应,而基座模型只是泛泛地遵循 system 提示。同时对比视图还会给出每个模型的 token 数与推理耗时。
客观提醒(与仓库说明一致):这是一个用来演示流程的极简样例,并不代表真实数据集或场景;本例中两侧 token 数相同(system 上下文与 user 提示一致),而微调模型推理耗时反而更长(自定义模型)。在真实场景(如面向客服的产品目录)里,要达到同等质量,基座模型往往需要更复杂的提示工程,从而增加 token 使用与潜在推理耗时——这正是微调「简化提示、降低成本」价值的体现。
微调生态与工具选型
除了仓库自带的 OpenAI 样例,官方还梳理了多套可用于实际微调的提供商/工具,它们覆盖不同技术栈与使用习惯:
- OpenAI:通过 Cookbook 的「如何微调聊天模型」示例,用「食谱助手(recipe assistant)」这一特定领域做完整演练——准备训练数据、运行微调任务、用微调模型做推理。
- Azure OpenAI:提供 GPT 系列微调教程,涵盖创建并上传训练数据、运行微调任务、部署并使用新模型的完整链路(支持门户 / Python SDK / 命令行 / REST)。
- Hugging Face:面向开源 LLM(如
CodeLlama 7B)的微调,使用transformers、TRL(Transformer Reinforcement Learning)与 Hugging Facedatasets库,支持在 Hugging Face 上微调开放模型。 - AutoTrain(AutoTrain Advanced):Hugging Face 的 Python 库,支持包括 LLM 微调在内的多种任务;提供**无代码(no-code)**方案,支持 Web GUI、CLI 以及基于 YAML 配置文件训练,可部署在你自己的云、Hugging Face Spaces 或本地。
- Unsloth:开源框架,支持 LLM 微调与强化学习(RL),提供开箱即用的 notebook,并支持文本转语音(TTS)、BERT 与多模态模型,简化本地训练、评估与部署流程。
选型建议:若目标是托管闭源模型(OpenAI / Azure OpenAI),走平台 API + JSONL 数据集路线;若目标是开源/本地模型,优先考虑 Hugging Face 生态(TRL + transformers)或 AutoTrain / Unsloth 等降低门槛的工具。
数据准备与训练评估的关键检查项
结合该课插图指南与 RESOURCES 页的自我引导资料,微调工程落地的核心检查点可以归纳为:
- 数据准备:训练数据规模(示例数量)、示例格式(依模型而定)、数据表征(广度 vs 质量)、需求覆盖度(质量)。
- 训练与评估:上传训练数据 → 创建微调任务 → 监控任务状态 → 测试微调模型。
- 部署与使用:区域可用性(约束条件)、模型速率限制(共享)、在 Playground 中验证、集成到 SDK/应用。
- 最佳实践:拥有明确用例、先尝试其他替代方案、评估成本与收益、制定维护策略。
其中「成本/数据准备/质量度量」三类官方参考资料尤其值得深入:数据准备与分析(格式校验、基本统计、token 估算以预估微调成本)、连续微调(continuous fine-tuning,即把已微调模型作为新的基座继续微调)、以及与函数调用(function calling)结合的微调(可获得更准确、一致、格式统一且更省成本的输出)。
小结
微调是继提示工程、RAG 之后的第三类「提升 LLM 输出质量」的技术,其本质是用新数据重训模型本身,以换取更强的任务/领域表现与潜在的 token 成本下降。落地时应遵循「先建基线(提示工程/RAG)→ 评估成本收益 → 再决定是否微调」的决策框架,并严格把控数据格式正确性、训练质量评估与迭代、部署验证三个环节。本仓库的 微调任务 Notebook 与 样例数据集 提供了一个端到端、可参考的 OpenAI 微调实例;配套延伸阅读见 RESOURCES。注意:样例所基于的 gpt-3.5-turbo 已退出微调,实际作业请改投当前受支持的模型,并以官方可微调模型列表为准。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00


