大模型数据集构建:零基础本地实操流程与避坑
做模型微调时,数据集质量往往比模型结构更影响最终效果。
本文面向零基础用户,用一台普通 Linux 机器和 Python 脚本,把“原始文本 → 清洗 → 指令对格式化 → 去重 → 质量检查”这条链路完整跑一遍。
适合准备尝试 LoRA 微调、但不知道数据从哪下手的人。
先确认环境和数据来源
开始前需要准备三样东西:一台能运行 Python 的 Linux 或 macOS 机器(Windows 可用 WSL)、一份你有权使用的原始文本、以及基本的命令行操作能力。
检查 Python 版本:
python3 --version
建议 Python 3.8 以上。
然后建一个独立目录,避免污染系统环境:
mkdir -p ~/dataset-build && cd ~/dataset-build
python3 -m venv venv
source venv/bin/activate
pip install pandas datasets
原始数据可以来自自己整理的文档、公开授权的语料或业务问答记录。不要直接使用来源不明或含个人隐私的文本,后续清洗很难完全补救。
从原始文本到结构化指令对
大模型微调常用 JSONL 格式,每行一个 JSON 对象,至少包含 instruction、input、output 三个字段。
先准备一个 raw.txt,每段之间用空行分隔:
请解释什么是 HTTP 状态码 404。
404 表示服务器找不到请求的资源。
把下面这句话翻译成英文:今天天气很好。
The weather is nice today.
用脚本把“问题行 + 答案行”转成 JSONL:
import json
with open('raw.txt', encoding='utf-8') as f:
blocks = [b.strip() for b in f.read().split('\n\n') if b.strip()]
with open('train.jsonl', 'w', encoding='utf-8') as out:
for block in blocks:
lines = [l.strip() for l in block.splitlines() if l.strip()]
if len(lines) < 2:
continue
item = {
'instruction': lines[0],
'input': '',
'output': '\n'.join(lines[1:])
}
out.write(json.dumps(item, ensure_ascii=False) + '\n')
运行后检查输出:
python build.py
head -n 2 train.jsonl
每行应是一个合法 JSON 对象。
如果出现乱码或空行,优先检查原始文件编码是否为 UTF-8。
清洗、去重与长度控制
真实数据通常有重复、空白过多、答案过短等问题。
下面这段脚本做三件事:去掉完全重复的指令、去掉答案少于 5 个字符的样本、统计长度分布:
import json
from collections import Counter
seen = set()
kept = []
with open('train.jsonl', encoding='utf-8') as f:
for line in f:
item = json.loads(line)
key = item['instruction'].strip()
if key in seen or len(item['output'].strip()) < 5:
continue
seen.add(key)
kept.append(item)
with open('clean.jsonl', 'w', encoding='utf-8') as out:
for item in kept:
out.write(json.dumps(item, ensure_ascii=False) + '\n')
lengths = [len(i['output']) for i in kept]
print('保留条数:', len(kept))
print('答案长度中位数:', sorted(lengths)[len(lengths)//2] if lengths else 0)
注意:去重只按指令文本判断,如果同一问题有多种合理答案,可以改用“指令 + 答案”组合去重,避免误删有效样本。
常见报错与避坑点
json.decoder.JSONDecodeError:通常是某行混入了非 JSON 内容,用sed -n '行号p' train.jsonl定位后手动修正或删除。- 中文显示为
\uXXXX:写出时漏了ensure_ascii=False,补上即可。 - 训练时报字段缺失:检查每行是否都包含
instruction和output,可用python -c "import json;[json.loads(l) for l in open('clean.jsonl')]"快速校验。 - 不要用测试集数据参与训练,划分时按指令文本去重后再切分,避免同一问题同时出现在训练和验证集。
验证数据集是否可用
完成清洗后,至少做三项检查:
- 行数与预期一致:
wc -l clean.jsonl - 随机抽查 5 条:
shuf -n 5 clean.jsonl - 用
datasets库加载一次,确认格式能被训练脚本识别:
from datasets import load_dataset
ds = load_dataset('json', data_files='clean.jsonl', split='train')
print(ds)
print(ds[0])
如果加载成功且字段完整,这份数据就可以进入微调流程。
若后续训练损失异常,优先回头检查答案长度分布和重复率,而不是先调模型参数。
数据集构建不是一次性的活,建议把清洗脚本保留在项目里,每次新增原始文本后重新跑一遍,保证格式和去重规则一致。