Generative AI for Beginners 第 18 课:LLM 微调(Fine-Tuning)从原理到动手实操
2026/9/10 2:23:41 网站建设 项目流程

Generative AI for Beginners 第 18 课:LLM 微调(Fine-Tuning)从原理到动手实操

【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners

本指南是开源课程 generative-ai-for-beginners 第 18 课「微调你的 LLM」的完整技术解读,核心对应 translations/fi/18-fine-tuning/README.md(本课芬兰语版)与 18-fine-tuning/README.md 的课程内容。本课回答四个关键问题:语言模型的微调是什么、何时与为何值得做、如何实际微调一个预训练模型、微调有哪些局限。课程配套的 OpenAI 端到端 Notebook(oai-assignment.ipynb)与训练数据(training-data.jsonl)将在文中完整展开,让你不仅理解概念,还能从数据准备、任务创建、进度监控到评估部署,亲手跑通一次真实的微调流程。

课程定位:为什么要引入微调这条新路线?

用大语言模型(LLM)构建生成式 AI 应用会带来新的挑战,核心问题之一是:确保模型针对用户请求生成的内容具备足够的质量(准确性与相关性)。此前课程已经讨论过两类应对技术:

  • 提示工程(Prompt Engineering):通过修改输入提示来引导模型输出;
  • 检索增强生成(RAG):通过注入检索结果来补充上下文。

这两类技术的共同点是修改送入既有模型的提示(prompt),模型本身的权重与行为不变。而本课介绍的第三种技术——微调(Fine-tuning)——走的是另一条路:用额外数据重新训练模型本身,让模型"内化"目标领域的行为模式。本课的学习目标包括:理解预训练语言模型中的微调概念、探索该方法的收益与挑战,并给出何时以及如何用微调提升生成式 AI 模型性能的实操指导。

语言模型的微调究竟是什么?

大语言模型在定义上就是**预训练(pre-trained)**的:它们在海量、多来源(包括互联网)的文本上完成预训练。因此,为了让模型对用户的问题给出更高质量的答案,我们需要提示工程、RAG 这类辅助技术。

从 few-shot 学习的两个局限说起

一种流行的提示工程技术是给模型更多"预期"——要么提供指令(显式引导),要么给出几个示例(隐式引导)。后者被称为few-shot 学习,但它有两个明显局限:

  1. Token 窗口限制:模型的 token 上限会限制你放入提示的示例数量,从而限制效果;
  2. Token 成本:每条提示都附带示例会显著增加 token 消耗,提高成本并降低灵活性。

微调的定义与附带收益

微调是机器学习系统中的常见做法:取一个预训练模型,用新数据对其重新训练,以提升它在特定任务上的表现。放到语言模型语境下,我们可以用针对特定任务或应用领域精心挑选的示例集对预训练模型进行微调,得到一个定制模型(custom model),它在该任务或领域中往往更准确、更相关。

微调还有一个"副作用"式的好处:它可以直接减少 few-shot 学习所需的示例数量——因为这些模式已经被训练进了模型权重,推理时无需再塞进提示里,从而降低 token 用量与相关成本。这正是 oai-assignment.ipynb 开头所强调的核心动机:微调允许使用的示例数量远超最大 token 窗口能容纳的量,部署的定制模型在推理时不再需要提供示例,既提升了提示设计的灵活性,又可能改善成本。

何时、以及为什么值得微调?

先厘清:这里说的是有监督微调

本课语境下的微调特指有监督微调(supervised fine-tuning)——通过添加不属于原始训练集的新数据进行重新训练。这与无监督式的微调不同(后者是用原始数据但换不同超参数重新训练)。

微调是高级技术,做错会适得其反

务必记住:微调是需要一定专业水平才能得到预期结果的进阶技术。如果操作不当,它可能无法带来预期的改进,甚至可能降低模型在你目标领域上的表现。所以在学"怎么微调"之前,先要回答"为什么选这条路"与"什么时候开始"。

动手前的四组自问

维度关键问题
用例(Use Case)我的微调用例是什么?现有预训练模型哪个方面需要改进?
替代方案(Alternatives)是否已经尝试过其他技术并建立基线?——提示工程(如带示例的 few-shot 提示)与 RAG(用检索结果增强提示)都应先试并评估响应质量
成本(Costs)微调的成本是否已厘清?——可调性(该预训练模型是否开放微调)、工作量(训练数据准备、模型评估与迭代)、算力(运行微调任务与部署微调模型)、数据(能否获得足够高质量的示例)
收益(Benefits)收益是否已确认?——质量(微调模型是否优于基线)、成本(是否通过简化提示降低了 token 消耗)、可扩展性(能否将基础模型复用到新领域)

理想情况下,只有当收益大于成本时,微调才是合理的路线。回答完这些问题,才能决定是否值得继续,进而思考"如何"微调。

如何微调一个预训练模型:四个必要条件

要完成一次微调,你需要准备:

  1. 一个可微调的预训练模型
  2. 一个用于微调的数据集
  3. 一个运行微调任务的训练环境
  4. 一个部署微调模型的托管环境

模型选型提醒(以课程当前内容为准):课程指出,部分教程中引用的gpt-35-turbo/gpt-3.5-turbo在推理与微调两个场景均已退役。如果今天要启动新的微调任务,应选择当前受支持的模型,例如gpt-4o-minigpt-4.1-mini。教程中的概念与步骤仍然适用——本仓库的 Notebook 输出即基于gpt-3.5-turbo生成,仅供演示流程。

微调实战:用 OpenAI SDK 跑通端到端流程

仓库提供了完整的实战 Notebook:18-fine-tuning/python/openai/oai-assignment.ipynb。微调共 4 大步:

  1. 准备训练数据并上传;
  2. 运行训练任务,得到微调模型;
  3. 评估微调模型并迭代质量;
  4. 满意后部署微调模型用于推理。

下面按这四步完整走一遍。

Step 1:准备训练数据(JSONL 单轮格式)

本教程构建一个用**打油诗(limerick)**介绍元素周期表元素的聊天机器人 "Elle"。为了让模型学会"元素 → 打油诗"的响应格式,需要准备符合 OpenAI 聊天补全格式的示例数据。

对于单轮(单次问答)响应,使用如下 JSONL 格式——每条记录占一行,每个记录是一个 JSON 对象:

{ "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"}]}

完整示例集(10 条,覆盖 Gallium、Hydrogen、Helium、Boron、Iron、Carbon、Cobalt、Titanium、Silver、Mercury)见 training-data.jsonl。两点重要说明:

  • 每条记录必须在单行内完成,不能像格式化 JSON 那样跨行;
  • 若场景是多轮对话,应改用多轮示例格式,并通过weight参数标记哪些消息参与(或不参与)微调。

真实场景中,你需要远多于 10 条的示例才能获得好效果——这需要在响应质量与微调的时间/成本之间做权衡;教程用小数据集是为了快速演示流程。

Step 2:环境准备与数据上传

运行代码前需完成:

  • 安装openaiPython 包(本仓库根目录 requirements.txt 中规定openai>=1.12.0,并包含python-dotenvtiktoken等依赖;本地环境搭建详见 00-course-setup/02-setup-local.md);
  • OPENAI_API_KEY设置为你的 OpenAI API 密钥。

仓库对密钥管理有专门的工程化支撑:共享模块 shared/python/env_utils.py 提供get_required_envvalidate_env_vars等工具,缺失环境变量时抛出带提示的ValueError;配套测试 tests/test_env_utils.py 验证了"缺失即报错、空值即报错、多变量一次性校验"等行为。建议把密钥放入.env文件(已加入.gitignore),再用python-dotenv加载,切勿硬编码在代码中。

接下来用 Files API 上传训练文件:

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)

注意purpose="fine-tune"是微调用途上传的固定参数。Notebook 中的运行示例返回了FileObject(id='file-...', purpose='fine-tune', status='processed', ...),即文件上传并被处理成功。

Step 3:创建微调任务

用 Fine-tuning API 创建任务,传入训练文件 ID 与基础模型:

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)

从 Notebook 记录的任务对象可以看到微调任务的默认超参数配置:hyperparameters=Hyperparameters(n_epochs='auto', batch_size='auto', learning_rate_multiplier='auto'),即轮次、批次大小、学习率乘数默认均为auto(由服务端自动确定),同时任务会分配一个seed用于可复现性。

Step 4:监控任务进度

client.fine_tuning.jobs提供一组常用 API:

  • 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>)—— 列出任务事件。

任务创建后首先进入**训练文件校验(validating_files)**阶段,确认数据格式无误后转为running。通过retrieve可查看状态与已训练 token 数:

response = client.fine_tuning.jobs.retrieve(ft_filejob.id) print("Job ID:", response.id) print("Status:", response.status) print("Trained Tokens:", response.trained_tokens)

想要更细粒度地观察进展,可以用list_events轮询事件消息,直到看到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逐轮下降,随后在 80/90 步创建检查点(Checkpoint created at step 80 with Snapshot ID: ft:...:ckpt-step-80),最终生成新模型(New fine-tuned model created: ft:gpt-3.5-turbo-0125:bitnbot::...)。这些训练损失与检查点信息同样可以在 OpenAI 平台 Dashboard 的 Fine-tuning 面板中可视化查看(也可用client.fine_tuning.jobs.cancel中止不满意的任务)。

Step 5:取回模型 ID 并用代码推理测试

任务完成后,通过retrieve取回微调模型 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 直接做推理(Notebook 示例用的是responses.create,传入与训练数据一致的 system 提示与新的用户问题):

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)

Notebook 中微调模型对 "Tell me about Strontium" 的回答是一首完整的打油诗("Strontium, a metal so bright - It's in fireworks, a dazzling sight...")——这正是训练数据所定义的输出风格,证明模型已经学会了示例中的格式。

Step 6:在 Playground 中对比基础模型与微调模型

除了用代码测试,还可以在 OpenAI Playground 中用模型下拉框选择微调模型,或通过 Fine-tuning 面板的 Playground 入口启动并排对比视图:左右两侧填入相同的 system 上下文与测试问题,同时运行,直观对比基础模型与微调模型的输出差异。

要点与解读:

  • 对比界面会展示每个模型的 token 数(本例中两者一致,因为 system 上下文与用户问题相同)与推理耗时;微调模型作为定制模型可能耗时更长;
  • 本例是为了演示流程而刻意简化的玩具示例,并非真实场景;真实场景中,微调模型不再需要在提示中塞入 few-shot 示例,而基础模型要达到同等质量往往需要更复杂的提示工程,从而增加 token 用量与推理时间——这正是微调在质量与成本上的实际价值所在。

Step 7:部署

评估满意后,将微调模型部署到托管环境用于生产推理。课程 18-fine-tuning/README.md 提示的部署考虑包括区域可用性模型速率限制(详见速写图第 06 模块),部署后即可在 Playground 或 SDK/应用中直接使用。

其他微调路线:多供应商实操对照

课程整理了一张"微调实战"教程对照表,覆盖托管 API 与开源工具两条路线,本仓库的 18-fine-tuning/RESOURCES.md 收录了完整资源清单:

供应商/工具教程内容特点
OpenAI如何微调聊天模型gpt-35-turbo(当前可用替代为gpt-4o-mini等)微调出"配方助手"领域模型:准备训练数据 → 运行微调任务 → 用微调模型做推理
Azure OpenAIGPT-3.5 Turbo 微调教程在 Azure 上完成训练数据的创建与上传、运行微调任务、部署并使用新模型
Hugging Face用 transformers + TRL 微调开源 LLM面向开源模型(如CodeLlama 7B),使用 transformers 库与 Transformer Reinforcement Learning(TRL)工具、配合 Hugging Face 开放数据集
🤗 AutoTrain用 AutoTrain 微调 LLMHugging Face 出品的 Python 库,支持多种任务的微调,属于无代码方案:可在自有云、Hugging Face Spaces 或本地运行,支持 Web GUI、CLI 与 yaml 配置训练
🦥 Unsloth用 Unsloth 微调 LLM开源框架,支持 LLM 微调与强化学习(RL),通过现成 Notebook 简化本地训练、评估与部署,还支持 TTS、BERT 与多模态模型

作业:选择上表中的一个教程完整走一遍。仓库中的 Notebook 版本仅供参考,最新版本请以官方来源为准。

进阶方向与延伸资源

本课的 RESOURCES.md 为自学提供了丰富延伸,主要包括:

  • OpenAI 微调概览:解释微调相对 few-shot 学习如何在远超提示窗口容量的更多示例上训练,从而节省成本、提升响应质量并降低延迟;
  • Azure OpenAI 微调概念与流程:涵盖什么是微调、为何值得做、该用什么数据、如何度量质量;
  • 连续微调(Continuous Fine-Tuning):以已微调模型为基础模型,在新训练示例上进一步迭代微调
  • 微调与函数调用(Function Calling):用带函数调用的示例微调模型,可得到更准确、更一致的输出格式并节省成本;
  • 面向 RAG 的微调:OpenAI Cookbook 展示了结合 Qdrant 与 few-shot 学习、为检索增强生成微调模型以减少幻觉(fabrication)的完整示例;
  • 小语言模型微调(Phinetuning 2.0):基于 Microsoft Phi-2,使用 QLoRA 构建定制数据集并微调小模型;
  • 可观测性集成:Weights & Biases 与 OpenAI / Azure OpenAI 微调的对接,用于详细追踪与分析模型性能;
  • 模型可微调性清单:哪些模型可在 Azure OpenAI 中微调、在哪些区域可用、token 上限与训练数据过期时间。

环境支撑与源码佐证

如果你想在本地复现本课 Notebook,仓库提供了完整的工程化支撑:

  • 依赖:根目录 requirements.txt 规定openai>=1.12.0,并含python-dotenvtiktokenipywidgetspandas等;
  • 环境变量管理:shared/python/env_utils.py 的get_required_env/validate_env_vars会在OPENAI_API_KEY等变量缺失时给出明确报错,tests/test_env_utils.py 用 monkeypatch 覆盖了缺失、空值、多变量校验等全部边界;
  • 本地环境搭建:00-course-setup/02-setup-local.md 提供了原生 Python + venv、VS Code Dev Container、Miniconda、Jupyter 四条路径,并给出.env创建与python-dotenv加载的标准姿势。

总结:微调的边界与正确打开方式

回顾本课的核心结论:

  • 微调是什么:用精选示例集对预训练模型重新训练,得到针对特定任务/领域的定制模型,能突破 few-shot 学习的 token 窗口与成本限制;
  • 何时值得做:先试提示工程与 RAG 建立基线,只有在用例明确、成本可控、且收益(质量/成本/可扩展性)大于成本时才动手;
  • 如何做:准备好"预训练模型 + 数据集 + 训练环境 + 托管环境"四要素,按"准备上传数据 → 创建任务 → 监控评估 → 部署推理"四步走,用仓库的 oai-assignment.ipynb 即可端到端复现;
  • 局限:微调是高级技术,需要专业水平;数据质量与规模直接决定效果,做错甚至可能损害目标领域性能;部署还受区域可用性、速率限制等约束。

至此,你已经掌握了"为什么要微调、什么时候微调、以及如何用 OpenAI SDK 亲手完成一次微调"的完整闭环,可以在此基础上结合自己的业务数据,把通用基础模型变成真正懂你领域的定制模型。

【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询