三种主流LoRA微调数据集格式通俗详解

一、先把你遇到的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)【国内中文首选】

优点

  1. 适配所有国产大模型(Qwen、百川、Yi、GLM),网上现成训练脚本直接跑,不用改代码;
  2. 社区中文数据集几乎全是这个格式,下载开源数据不用转换;
  3. 多轮对话天然适配,支持来回多轮聊天,工具、角色扮演微调兼容性拉满;
  4. 大部分中文QLoRA/LoRA训练脚本写死解析conversations,拿来就能训练。

缺点

  1. 国外库原生不识别,直接拿海外Llama训练脚本跑会报字段找不到,需要改代码适配;
  2. 没有行业国际统一标准,不同小众项目偶尔会乱改关键词(比如有人写bot代替gpt),容易踩坑;
  3. 如果你后续想做英文模型微调,必须全部转成role/content格式。

2. conversation(单数 role/content)【国际通用标准】

优点

  1. Hugging官方原生标准,transformers、peft、accelerate、trl全部内置支持,不用自己写解析逻辑;
  2. 全球统一规范,不管Llama、Mistral、GPT类模型全部通用,换模型不用改数据;
  3. 工具生态完善:数据集可视化、清洗、拆分工具默认识别这套格式,兼容性最强;
  4. 官方文档、原版开源代码全基于这套,出问题更容易搜到解决方案。

缺点

  1. 国产中文模型很多训练脚本不兼容 ,直接导入Qwen训练会提示找不到conversation字段,要改数据或代码;
  2. 国内开源中文数据集很少是这个格式,下载后需要批量转换字段名。

四、实操建议

  1. 训练Qwen2系列,保留你现有的conversations复数格式 ,不用转换
    • 国内所有Qwen微调教程、AutoDL脚本都是这套,减少改代码踩坑;
    • 我刚给你更新后的校验脚本已经兼容该格式,不会再判定数据错误。
  2. 未来如果要微调海外Llama/Mistral,再写一段简单代码批量转换格式:
    • 把外层键 conversationsconversation
    • from: humanrole: user
    • from: gptrole: assistant
    • valuecontent
  3. 区分使用场景:
    • 多轮聊天、角色扮演、工具调用 → 两种对话格式二选一
    • 单轮问答、摘要、翻译、分类 → 用 instruction 单轮格式更简单