一、先把你遇到的2种对话格式完整举例
格式1:conversations(复数,from/value)------你现在val.jsonl在用的格式
全网Qwen通义千问、Llama中文社区、AutoDL大量教程最常用
json
{"conversations": [{"from": "human", "value": "import导入几种写法?"}, {"from": "gpt", "value": "import 模块;from 模块 import 函数/类;from 模块 import *(不推荐,污染命名空间)。"}]}
{"conversations": [{"from": "human", "value": "filter函数作用?"}, {"from": "gpt", "value": "filter(判断函数,可迭代对象),过滤保留返回True的元素,生成过滤后的迭代器。"}]}
关键词:外层键 conversations复数 ,角色键 from,内容键 value
角色固定两种:human 用户提问 / gpt AI回答
注意: 一个 conversations 放在一行, 不要换行。
格式2:conversation(单数,role/content)------HuggingFace官方标准格式
transformers/peft/trl原生支持,国外Llama、Mistral原版通用
json
{"conversation": [{"role": "user","content":"Python多进程如何传递数据?"},{"role":"assistant","content":"使用multiprocessing.Queue管道、Manager共享容器..."},{"role":"user","content":"那跨机器呢?"},{"role":"assistant","content":"跨机器用RPC、Redis队列或者Celery"}]}
{"conversation": [{"role":"user","content":"venv创建虚拟环境命令?"},{"role":"assistant","content":"python3 -m venv xxx"}]}
关键词:外层键 conversation单数 ,角色键 role,内容键 content
角色固定两种:user 用户提问 / assistant AI回答
注意: 一个 conversation 放在一行, 不要换行。
格式3:单轮指令格式 instruction/input/output(补充,单轮问答专用)
json
{"instruction":"Python多进程如何传递数据?","input":"","output":"使用multiprocessing.Queue管道、Manager共享容器..."}
{"instruction":"Python多进程如何传递数据?","input":"","output":"使用multiprocessing.Queue管道、Manager共享容器..."}
3种 jsonl 格式统一校验
py
import json
import sys
def check_all_format_jsonl(file_path):
total_lines = 0
json_syntax_err = [] # JSON语法错误行
invalid_data_lines = [] # 字段/内容无效行
valid_samples = []
with open(file_path, "r", encoding="utf-8") as f:
for line_num, raw_text in enumerate(f, start=1):
total_lines += 1
line = raw_text.strip()
# 跳过纯空行
if not line:
continue
# 第一步:校验单行JSON语法是否合法
try:
data = json.loads(line)
except Exception as e:
# 区分典型json数组报错,给用户提示格式混淆问题
err_str = str(e)
tip = ""
if "Extra data" in err_str or "Expecting value" in err_str:
tip = "【提示:疑似写成普通JSON数组,JSONL要求一行一条完整对话对象,不能多行拆分单个JSON】"
json_syntax_err.append((line_num, f"{err_str} {tip}", line[:120]))
continue
format_ok = False
# ====================== 格式1:国内Qwen conversations复数 from/value ======================
if "conversations" in data and isinstance(data["conversations"], list):
conv_list = data["conversations"]
if len(conv_list) == 0:
invalid_data_lines.append((line_num, "【格式1】conversations对话数组为空"))
continue
turn_valid = True
for turn in conv_list:
if "from" not in turn or "value" not in turn:
turn_valid = False
break
if turn_valid:
format_ok = True
# ====================== 格式2:HF国际标准 conversation单数 role/content ======================
elif "conversation" in data and isinstance(data["conversation"], list):
conv_list = data["conversation"]
if len(conv_list) == 0:
invalid_data_lines.append((line_num, "【格式2】conversation对话数组为空"))
continue
turn_valid = True
for turn in conv_list:
if "role" not in turn or "content" not in turn:
turn_valid = False
break
if turn_valid:
format_ok = True
# ====================== 格式3:单轮指令 instruction + output ======================
elif "instruction" in data and "output" in data:
ins_text = str(data.get("instruction", "")).strip()
out_text = str(data.get("output", "")).strip()
if len(ins_text) == 0 and len(out_text) == 0:
invalid_data_lines.append((line_num, "【格式3】instruction和output全部为空"))
continue
format_ok = True
# 三种格式都不匹配
if not format_ok:
invalid_data_lines.append((
line_num,
"不匹配任意支持格式!支持:1.conversations(from/value) 2.conversation(role/content) 3.instruction+output"
))
continue
# 校验整体文本不能全为空
full_text = "".join(str(v) for v in data.values()).strip()
if len(full_text) < 3:
invalid_data_lines.append((line_num, "样本有效文本太短,无训练价值"))
continue
# 全部校验通过,存入合格列表
valid_samples.append(data)
# ====================== 输出校验汇总报告 ======================
print("=" * 70)
print(f"校验文件:{file_path}")
print(f"文件总行数:{total_lines}")
print(f"✅ 完全合格样本:{len(valid_samples)}")
print(f"❌ JSON语法错误行数:{len(json_syntax_err)}")
print(f"⚠️ 字段/内容无效行数:{len(invalid_data_lines)}")
print("=" * 70)
# 打印JSON语法错误详情
if json_syntax_err:
print("\n【JSON语法错误(必须修复,否则无法训练)】")
for idx, err_msg, snippet in json_syntax_err:
print(f"行{idx} 报错:{err_msg}")
print(f"片段预览:{snippet}\n")
# 打印无效样本详情
if invalid_data_lines:
print("\n【无效样本(建议修改/删除)】")
for idx, reason in invalid_data_lines:
print(f"行{idx} 问题:{reason}")
# 导出清洗后的纯合格数据
output_file = "clean_valid_data.jsonl"
with open(output_file, "w", encoding="utf-8") as fw:
for item in valid_samples:
fw.write(json.dumps(item, ensure_ascii=False) + "\n")
print(f"\n✅ 校验结束!干净数据集已输出至:{output_file}")
if __name__ == "__main__":
# 命令行传参用法:python check_all_format_jsonl.py val.jsonl
if len(sys.argv) > 1:
target_file = sys.argv[1]
# 默认读取train.jsonl
else:
target_file = "train.jsonl"
check_all_format_jsonl(target_file)
二、实际微调场景:哪个用的最多?
国内中文模型(Qwen、通义、Baichuan、Yi)
第一名:conversations 复数 from/value(你现在的格式)
90%国内云教程、AutoDL、开源中文微调项目全是这套,专门适配阿里Qwen系列,开箱即用。
国外英文模型(Llama2/3、Mistral、Phi)
第一名:conversation 单数 role/content
Hugging Face、peft、trl库原生默认解析这套,国外开源项目统一标准。
单轮简单问答(小任务、分类、翻译)
instruction单轮格式用得多,不需要多轮对话场景。
三、两种对话格式优缺点(大白话,无专业黑话)
1. conversations(复数 from/value)【国内中文首选】
优点
- 适配所有国产大模型(Qwen、百川、Yi、GLM),网上现成训练脚本直接跑,不用改代码;
- 社区中文数据集几乎全是这个格式,下载开源数据不用转换;
- 多轮对话天然适配,支持来回多轮聊天,工具、角色扮演微调兼容性拉满;
- 大部分中文QLoRA/LoRA训练脚本写死解析
conversations,拿来就能训练。
缺点
- 国外库原生不识别,直接拿海外Llama训练脚本跑会报字段找不到,需要改代码适配;
- 没有行业国际统一标准,不同小众项目偶尔会乱改关键词(比如有人写
bot代替gpt),容易踩坑; - 如果你后续想做英文模型微调,必须全部转成role/content格式。
2. conversation(单数 role/content)【国际通用标准】
优点
- Hugging官方原生标准,transformers、peft、accelerate、trl全部内置支持,不用自己写解析逻辑;
- 全球统一规范,不管Llama、Mistral、GPT类模型全部通用,换模型不用改数据;
- 工具生态完善:数据集可视化、清洗、拆分工具默认识别这套格式,兼容性最强;
- 官方文档、原版开源代码全基于这套,出问题更容易搜到解决方案。
缺点
- 国产中文模型很多训练脚本不兼容 ,直接导入Qwen训练会提示找不到
conversation字段,要改数据或代码; - 国内开源中文数据集很少是这个格式,下载后需要批量转换字段名。
四、实操建议
- 训练Qwen2系列,保留你现有的conversations复数格式 ,不用转换
- 国内所有Qwen微调教程、AutoDL脚本都是这套,减少改代码踩坑;
- 我刚给你更新后的校验脚本已经兼容该格式,不会再判定数据错误。
- 未来如果要微调海外Llama/Mistral,再写一段简单代码批量转换格式:
- 把外层键
conversations→conversation from: human→role: userfrom: gpt→role: assistantvalue→content
- 把外层键
- 区分使用场景:
- 多轮聊天、角色扮演、工具调用 → 两种对话格式二选一
- 单轮问答、摘要、翻译、分类 → 用 instruction 单轮格式更简单