generative-ai-for-beginners 第 18 课:Fine-Tuning 你的 LLM——从概念到端到端实战
【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners
导读
本篇文章对应本仓库(21 Lessons, Get Started Building with Generative AI)第 18 课,深入讲解fine-tuning(微调)这一生成式 AI 应用开发中的进阶技术:它不是修改 prompt,而是用额外数据重新训练模型本身,为特定任务或领域打造更准确、更贴合场景的自定义模型。读完本文,你将理解微调与提示工程、检索增强生成(RAG)的边界,掌握"何时该微调、为何微调、如何微调"的完整决策与实操流程,并能基于仓库中的 oai-assignment.ipynb 亲手跑通"准备数据 → 上传 → 创建训练任务 → 评估 → 部署"的全过程。
学习目标
本课引入面向预训练语言模型的微调概念,探讨该方法的收益与挑战,并给出何时以及如何使用微调来提升生成式 AI 模型性能的指引。学完本课,你应该能够回答以下问题:
- 什么是语言模型的微调?
- 微调在何时、以及为什么有用?
- 如何对预训练模型进行微调?
- 微调有哪些局限性?
什么是语言模型的微调?
按定义,大语言模型(LLM)是预训练在来自互联网等多样来源的大量文本之上的。正如前面课程所学,我们需要提示工程(prompt engineering)和检索增强生成(RAG)等技术来改善模型对用户问题("prompt")的响应质量。
一种流行的提示工程技术是给模型更详细的指引,说明响应中期望得到什么——要么通过指令(显式指引),要么给出几个示例(隐式指引)。这就是few-shot learning(少样本学习),但它有两个局限:
- 模型 token 限制:可能限制你能给出的示例数量,从而影响效果。
- 模型 token 成本:在每个 prompt 中都附加示例可能很昂贵,限制了灵活性。
微调是机器学习系统中的常见实践:取一个预训练模型,用新数据重新训练它,以提升其在特定任务上的表现。在语言模型的语境下,我们可以用针对某任务或应用领域精心整理的一组示例对预训练模型进行微调,创建出一个自定义模型(custom model),它对该任务或领域可能更准确、更相关。微调的一个附带好处是:它可以减少 few-shot learning 所需的示例数量——从而降低 token 用量及相关成本。
何时以及为什么应该微调模型?
在本课语境中,我们谈论的是监督式微调:通过添加不属于原始训练数据集的新数据来重新训练。这与无监督微调不同——后者是在原始数据上用不同超参数重新训练模型。
关键要记住:微调是一项高级技术,需要一定的专业水平才能获得理想结果。如果操作不当,它可能无法带来预期改进,甚至可能降低模型在你目标领域上的性能。
因此,在学"如何"微调语言模型之前,你需要先知道"为什么"要走这条路,以及"何时"启动微调流程。先问自己这些问题:
- 用例(Use Case):你的微调_用例_是什么?你想改进当前预训练模型的哪一方面?
- 替代方案(Alternatives):你尝试过_其他技术_来达成预期结果吗?用它们建立对比的 baseline。
- 提示工程:尝试 few-shot prompting 等技巧,给出相关响应的示例,评估响应质量。
- 检索增强生成(RAG):尝试用检索你数据得到的查询结果来增强 prompt,评估响应质量。
- 成本(Costs):你识别出微调的各项成本了吗?
- 可调性(Tunability)——预训练模型是否开放微调?
- 投入(Effort)——准备训练数据、评估与迭代模型所需的人力。
- 算力(Compute)——运行微调任务、以及部署微调后模型所需的计算资源。
- 数据(Data)——能否获取足够质量、足以产生微调影响的示例。
- 收益(Benefits):你确认了微调带来的收益吗?
- 质量(Quality)——微调后的模型是否超越了 baseline?
- 成本(Cost)——是否通过简化 prompt 降低了 token 用量?
- 可扩展性(Extensibility)——能否把基础模型复用到新领域?
回答完这些问题,你应该能判断微调是否适合你的用例。理想情况下,只有当收益大于成本时,这个方案才成立。一旦决定推进,就该思考_如何_对预训练模型进行微调。
如何对预训练模型进行微调?
要对预训练模型做微调,你需要具备:
- 一个可供微调的预训练模型;
- 一个用于微调的数据集;
- 一个运行微调任务的训练环境;
- 一个部署微调后模型的托管环境。
Fine-Tuning 实战:端到端四步流程
仓库中的 oai-assignment.ipynb 基于 OpenAI 官方微调文档,把整个流程归纳为清晰的 4 个步骤:
- 准备训练数据并上传;
- 运行训练任务,得到微调后的模型;
- 评估微调后的模型并迭代质量;
- 满意后部署微调模型用于推理。
注意:下述教程示例输出基于
gpt-3.5-turbo,该模型现已退役(不再支持推理与微调)。如果今天启动新的微调任务,请选择当前受支持的模型,例如gpt-4o-mini或gpt-4.1-mini。不过,本教程展示的概念与步骤依然适用。
步骤 1:准备你的数据集(JSONL 格式)
本仓库的教程要构建一个能"用打油诗(limerick)回答元素周期表问题"的聊天机器人,以展示微调如何教会模型遵循一种特定输出格式。真实场景中你需要远多于示例的数据量,也可以寻找目标领域的开放数据集并重新格式化后使用。
由于目标是单轮对话(chat completion),我们使用 OpenAI 推荐的单轮 chat 格式:数据采用 JSONL 格式 提供了 10 条完整示例,以下为其中两条:
{ "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"}]}如果你预期多轮对话内容,则应使用多轮示例格式,其中包含weight参数,用于指示在微调过程中哪些消息应被使用(或不使用)。
值得注意的是:微调训练示例的数量与质量直接决定了输出质量与微调成本之间的权衡——示例太少,模型学不到稳定的格式;示例太多,时间与费用随之上升。仓库中的 10 条示例仅用于快速跑通流程。
步骤 2:上传你的数据集
使用 Files API 上传数据。运行前需要先完成:
- 安装
openaiPython 包(建议使用较新版本,以获取最新特性); - 设置
OPENAI_API_KEY环境变量为你的 OpenAI API 密钥。
环境搭建可参考仓库的 本地环境配置指南(含虚拟环境、依赖安装与 API Key 管理方式)。仓库的 api_utils.py 中提供了create_openai_client()封装:若未显式传入 API Key,它会从OPENAI_API_KEY环境变量读取,缺失时抛出ValueError,帮你避免硬编码密钥的隐患。
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)上传成功后会返回FileObject,其中的id(如file-JdAJcagdOTG6ACNlFWzuzmyV)是后续创建训练任务的凭据。
步骤 3:创建并监控微调任务
用 SDK 创建微调任务,指定训练文件与基础模型:
ft_filejob = client.fine_tuning.jobs.create( training_file=ft_file.id, model="gpt-3.5-turbo" # 新任务请替换为当前支持的模型,如 gpt-4o-mini ) print("Fine-tuning Job ID: " + ft_filejob.id)创建任务时可观察返回的超参数对象Hyperparameters(n_epochs='auto', batch_size='auto', learning_rate_multiplier='auto')——训练轮数、批次大小、学习率倍率默认均为auto,由平台自动选择;seed字段则用于可复现性。
任务提交后,client.fine_tuning.jobsAPI 还提供以下常用操作:
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)从仓库 notebook 记录的真实事件流可以看到典型的完成轨迹:Step 85/100: training loss=0.14→ 逐 step 逼近training loss=0.00→ 在 step 80、90 处生成检查点(Checkpoint,附带 Snapshot ID)→ 最终New fine-tuned model created。训练过程中的 loss 曲线与检查点,是判断模型是否收敛、是否值得回滚到中间快照的重要依据。
你也可以在 OpenAI 平台网站的Fine-tuning栏目查看任务状态与历史记录。仓库截图展示了一个有代表性的场景:第一次运行因 JSON 记录格式错误而失败,修正格式后第二次运行成功并使模型可用。任务面板下方还能查看消息与指标(loss 等)面板。
步骤 4:评估微调后的模型
训练完成后,从任务对象中取出微调模型的 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)然后直接通过 Responses API 测试该模型:
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)仓库记录的示例输出是一首关于 Strontium(锶)的打油诗——模型严格遵循了训练数据中的格式约定。
除了在代码中测试,还可以在 Playground 中通过模型下拉框选择新模型,或从 Fine-tuning 面板直接启动并排对比视图(如上图),同时填充相同的系统上下文与测试问题,观察基础模型与微调模型的输出差异。对比视图还会给出两者的 token 数与推理耗时。注意:本教程是刻意简化的"玩具"示例,用于展示流程而非真实世界数据集;真实场景(如用产品目录微调客服模型)中,基础模型要达到同等响应质量通常需要更复杂的提示工程,从而消耗更多 token 与推理时间——这正是微调的价值所在。
在 Azure OpenAI 上,完成训练后还需要将微调模型部署到托管环境才能通过推理 API 调用,这也是"如何微调"四要素中"托管环境"的落地点。
各主流平台的微调教程对照
以下资源提供分步教程,带你用精选数据集和选定模型走完真实示例。操作这些教程需要你在对应提供商拥有账号,并能访问相关模型与数据集。
| 提供商 | 教程 | 描述 |
|---|---|---|
| OpenAI | 如何微调 chat 模型(OpenAI Cookbook) | 学习微调gpt-35-turbo用于特定领域("菜谱助手"):准备训练数据、运行微调任务、用微调后的模型做推理。 |
| Azure OpenAI | GPT 3.5 Turbo 微调教程 | 学习在 Azure 上微调gpt-35-turbo-0613:创建并上传训练数据、运行微调任务、部署并使用新模型。 |
| Hugging Face | 用 Hugging Face 微调 LLM | 使用 transformers 与 TRL 库,结合 Hugging Face 上的开放数据集微调_开放 LLM_(例如CodeLlama 7B)。 |
| 🤗 AutoTrain | 用 AutoTrain 微调 LLM | AutoTrain(AutoTrain Advanced)是 Hugging Face 开发的 Python 库,支持包括 LLM 在内的多种任务微调。它是 no-code 方案,可在自有云、Hugging Face Spaces 或本地运行,同时支持 Web GUI、CLI 与 yaml 配置文件训练。 |
| 🦥 Unsloth | 用 Unsloth 微调 LLM | Unsloth 是支持 LLM 微调与强化学习(RL)的开源框架,通过开箱即用的 notebook 简化本地训练、评估与部署,还支持 TTS、BERT 与多模态模型。 |
更深一步:本主题的扩展资源
仓库在 18-fine-tuning/RESOURCES.md 中整理了面向自主学习的资源清单,其中值得关注的方向包括:
- 数据准备与成本估算:OpenAI Cookbook 提供了 chat 模型微调的数据预处理与分析 notebook,可检查格式错误、输出基础统计并估算 token 成本;
- 连续微调(Continuous Fine Tuning):以已微调模型为基座、在新训练示例上继续微调的迭代流程;
- 微调与函数调用(Function Calling):用函数调用示例微调模型,可获得更准确、格式更一致的输出并降低成本;
- 微调与 RAG 结合:针对检索增强生成场景微调模型,结合向量数据库与 few-shot 提升性能、减少幻觉;
- 小语言模型(SLM)微调:如针对 Phi-2 等紧凑模型使用 QLoRA 构建专属数据集并微调(本仓库第 19 课即覆盖 SLM 主题);
- 可微调模型清单:查询 Azure OpenAI 中当前哪些模型支持微调、可用区域、token 上限与训练数据有效期。
作业与完成建议
选择上文教程表中的一个教程并完整走一遍。仓库中的 oai-assignment.ipynb 与 training-data.jsonl 仅作为参考副本,建议直接使用原始来源以获取最新版本——尤其注意:开始新微调任务前,务必确认所选模型当前是否仍支持微调(例如gpt-35-turbo已退役,应改用gpt-4o-mini等当前受支持模型)。
完成本课后,回顾第 18 课的学习目标,检验自己是否已经能够回答:什么是语言模型的微调、微调何时与为何有用、如何对预训练模型做微调、以及微调的局限。把微调放进本课程"提示工程 → RAG → 微调"的完整技术谱系中理解——三者分别通过修改 prompt 输入与重新训练模型本身来提升生成质量,而微调是其中最进阶、也最需要权衡成本与收益的一环。
【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考