微调圈子里有句老话:数据决定上限,参数只是逼近上限。同样的模型、同样的配置,换一份数据,效果可能天差地别。
课程助教要学的是"像这门课一样讲解"。最好的数据,当然是真实学员的提问和老师的回答。但大多数人手上没有几百条整理好的问答,只有讲义。
我们的做法是用大模型把讲义变成问答数据:先切块,再请大模型出题作答,最后清洗、去重、划分。这份数据已经做好,打包成了一个 zip 文件,下载下来就能用。
这一节先讲清楚数据长什么样、是怎么一步步做出来的,再把它下载下来,自己抽几条读一读。
学完你能做到:说清楚几种常见的数据格式,知道一份微调数据从讲义到成品要经过哪几步、什么样的数据该扔掉,并且把课程助教的数据集准备好。
本节的产出是训练课程助教所需的数据,以及一小份评测数据。
一、三种常见格式
微调数据就是一条条"输入和期望的输出"。常见的写法有三种:
Alpaca 格式,适合单轮问答:
{"instruction": "什么是 KV Cache?", "input": "", "output": "KV Cache 是……"}ShareGPT 格式,适合多轮对话,最早来自分享 ChatGPT 对话记录的网站:
{"conversations": [{"from": "human", "value": "什么是 KV Cache?"}, {"from": "gpt", "value": "KV Cache 是……"}]}OpenAI 格式,和调用接口时的消息列表一模一样:
{"messages": [{"role": "user", "content": "什么是 KV Cache?"}, {"role": "assistant", "content": "KV Cache 是……"}]}三种格式表达的信息差不多,LLaMA-Factory 都支持。我们用 OpenAI 格式:它和调用接口时的写法一致,以后把线上真实的对话记录整理成训练数据,几乎不用转换。
三种写法里,花括号括起来的是一组"名字: 内容",比如 "role": "user" 表示这条消息是用户说的;方括号括起来的是一串,可以放好几条消息。
把同一条问答放进三种格式,问题和回答的位置是这样的:

每条数据占一行,这种文件叫 JSON Lines,扩展名是 .jsonl。数据量大了也能一行一行地读,不用一次全部载入内存。
二、数据从哪来
| 来源 | 质量 | 数量 | 说明 |
|---|---|---|---|
| 真实的问答记录 | 最高 | 看积累 | 学员群、工单、客服记录,最贴近真实需求;要先去掉个人信息 |
| 人工编写 | 高 | 少 | 慢,但最可控,适合写最重要的几十条 |
| 用大模型合成 | 中到高 | 想要多少有多少 | 快且便宜,但要清洗和抽查 |
| 公开数据集 | 看情况 | 多 | 通用能力有用,领域风格帮助有限;注意许可证 |
实际项目通常是混合的:先用大模型合成一批打底,再把真实记录和人工编写的高质量数据加进去,后者的比重可以适当调高。
合成数据要注意两件事:
- 服务条款。 有的服务商不允许用它的输出训练其他模型。比如 OpenAI 的使用条款就写明,不得用其服务的输出开发与 OpenAI 竞争的模型。用之前,看一眼你所用服务的条款。
- 合成的上限是出题的模型。 出题模型讲错了,训练出来的模型也会跟着错。出题用能力强的大模型,并且一定要抽查。
三、课程助教的数据是怎么做出来的
课程助教的数据,是用 Claude Opus 5.5 从课程讲义合成的,一共走了五步:
| 步骤 | 做了什么 |
|---|---|
| ① 切块 | 每篇讲义按二级标题切开,一块大约就是一个小节 |
| ② 出题 | 每块请大模型出 3 道题并作答 |
| ③ 清洗 | 丢掉长度不合适、像是拒答、提到原材料的 |
| ④ 去重 | 问题重复的只留第一次出现的 |
| ⑤ 划分 | 每 10 条留 1 条做评测,其余做训练 |
画成一条流水线是这样的:

① 切块:按二级标题把每篇讲义切开,一块大约就是讲义里的一个小节。
二级标题就是 Markdown 里以 ## 开头的那一行,比如这一节的"三、课程助教的数据是怎么做出来的"。
切之前去掉了代码块。大段代码对生成讲解类问答帮助不大,而且具体的命令和版本号会变,交给后面的 RAG 更合适。
"小结"和"拓展阅读"也跳过了:前者和正文重复,后者只是一串链接。
每块最多取 3000 个字。太长的话,模型出的题容易只集中在开头。
② 出题:每块讲义配上下面这段提示词,交给大模型。这段提示词看懂就行,不用照着敲: