发布时间:2025-06-20 18:07:58编辑:123阅读(16)
如何构建高质量数据集?
微调的基础模型是 Qwen2.5-7B-Instruct ,目标是微调后让其在特定场景下具备一定的推理能力,并且在 Web 安全领域具备专家级水准。
注意:在非 Web 安全领域下,模型并不一定能够稳定输出推理过程,因为仅针对 Web 安全领域的数据集进行了训练,这在一定程度上激发了模型的推理能力,想要让模型在更多领域稳定输出推理过程,需要更丰富的数据集。
对于企业内部的代码、需求文档等一般都属于企业内部的机密数据,若直接使用外部模型可能存在隐私泄漏风险,因此此类任务一般需要私有部署的模型承担,而满血版模型的部署成本非常昂贵,所以选择使用对小参数模型进行微调。 希望微调后的模型可用于在企业内部私有部署,回答 Web 安全相关问题,对可能引发安全问题的业务场景以及代码进行预警,并且在 Web 安全领域的能力上可和满血版模型持平甚至超越满血版模型。
数据集在微调任务中起着至关重要的作用。毫不夸张的说,要想得到好的微调效果,数据集的质量要远大于其他参数的设置,如果数据集太小、多样性不足、数据噪声太大、样本偏差严重等问题都会导致微调任务失败。按照经验来讲,在一次微调任务中,大概 80% 的时间应该花在数据集的准备和处理上,因为微调的工具、流程和参数的调整都是有经验可循的,而数据集的构建却需要结合具体业务场景。从数据采集时需覆盖多维度场景,到清洗时剔除噪声与偏差样本,再到标注时确保一致性与准确性,每个环节都影响最终效果。此外,还需合理划分训练/验证/测试集,通过数据增强扩充样本多样性,让模型在微调中真正学习到关键特征。
数据集格式要求
在不同的微调阶段,使用的数据集的格式要求是不一样的。
本次进行的是指令监督微调(SFT),在 LLaMA Factory 中主要支持 Alpaca 格式和 ShareGPT 两种格式:
Alpaca 格式的指令微调数据集
格式要求:
[
{
"instruction": "人类指令(必填)",
"input": "人类输入(选填)",
"output": "模型回答(必填)",
"system": "系统提示词(选填)",
"history": [
["第一轮指令(选填)", "第一轮回答(选填)"],
["第二轮指令(选填)", "第二轮回答(选填)"]
]
}
]
实际案例:
[
{
"instruction": "将这句英文翻译成中文",
"input": "Hello,how are you?",
"output": "你好,你好吗?",
"system":"翻译任务,请确保翻译准确,自然",
"history": [
["将这句英文翻译成中文","你好,你好吗?"],
["将这句中文翻译成英文","How are you?"]
]
}
]
ShareGPT格式的指令微调数据集:
[
{
"conversations": [
{
"from": "human",
"value": "人类指令"
},
{
"from": "function_call",
"value": "工具参数"
},
{
"from": "observation",
"value": "工具结果"
},
{
"from": "gpt",
"value": "模型回答"
}
],
"system": "系统提示词(选填)",
"tools": "工具描述(选填)"
}
]
实际案例:
[
{
"conversations": [
{
"from": "human",
"value": "帮我计算一下2+2"
},
{
"from": "function_call",
"value": "calculator:1|operation=addition|a=2|b=2"
},
{
"from": "observation",
"value": "calculator:1|result=4"
},
{
"from": "gpt",
"value": "2+2的结果是4"
}
],
"system": "使用计算器工具完成数学计算任务",
"tools": "calculator:执行基本数学运算"
}
]
数据集配置文件
看到 LLaMA Factory 提供了两个数据集相关的配置:数据路径和数据集(名称)
数据集处理过程
LLaMA Factory 基于 dataset_info.json 实现了对多种不同的数据集格式兼容,一般情况下大家只需要了解 dataset_info.json 是怎么配置的即可,但是为了加深大家对数据集的理解,下面用一个具体的例子告诉大家一个你自定义的数据集最终会被处理成什么样子。假定我们的原始原始数据结构是这样的(Alpaca 格式):[
{
"instruction": "今天的天气怎么样?",
"input": "",
"output": "今天的天气不错,是晴天。",
"history": [
["今天会下雨吗?", "今天不会下雨,是个好天气。"],
["今天适合出去玩吗?", "非常适合,空气质量很好。"]
]
}
]
在数据加载阶段,通过 dataset_info.json 配置数据集文件的路径:
"my_dataset": {
"file_name": "my_dataset.json",
"formatting": "alpaca"
}
在微调任务开始后, LLaMA Factory 首先会将数据集转换诶标准格式:{
"_prompt": [
{"role": "user", "content": "今天会下雨吗?"},
{"role": "assistant", "content": "今天不会下雨..."},
{"role": "user", "content": "今天适合出去玩吗?"},
{"role": "assistant", "content": "非常适合..."},
{"role": "user", "content": "今天的天气怎么样?"}
],
"_response": [{"role": "assistant", "content": "今天的天气不错..."}]
}
然后根据上面选择的对话模版,将数据集按照模版进行格式化,比如本次选择的模版是 Qwen:
format_user = "<|im_start|>user\n{{content}}<|im_end|>\n<|im_start|>assistant\n"
format_assistant = "{{content}}<|im_end|>\n"
format_system = "<|im_start|>system\n{{content}}<|im_end|>\n"
格式化后数据集就是这样的:
<|im_start|>system
You are Qwen...<|im_end|>
<|im_start|>user
今天会下雨吗?<|im_end|>
<|im_start|>assistant
今天不会下雨...<|im_end|>
<|im_start|>user
今天适合出去玩吗?<|im_end|>
<|im_start|>assistant
非常适合...<|im_end|>
<|im_start|>user
今天的天气怎么样?<|im_end|>
<|im_start|>assistant
今天的天气不错...<|im_end|>
随后, LLaMA Factory 将会对数据进行分词处理,将文本转换为数字序列(token IDs)。这一步骤至关重要,因为模型仅能处理数字而非原始文本:
[151, 8243, 29973, 29901, 29871, 29896, 29889, 29877, 29889, 29889, 152, 151, 8251, 29901, 29871, 29896, 29889, 29877, 29889, 29889, 152]
随后,LLaMA Factory 会对数据集进行标签分配,标签分配是微调过程的核心环节,决定模型在哪些部分计算损失并学习生成内容。在对话模型训练中,模型需学会:理解用户输入(不生成用户输入)、生成助手回复,因此,需明确标记模型应生成的部分(助手回复)和仅需理解的部分(用户输入)。所以这一步就是把不参与损失计算(用户输入)的部分标记出来,LLaMA Factory 使用特殊值IGNORE_INDEX(值为-100)标记不参与损失计算的位置。以示例文本为例:
<|im_start|>user
今天会下雨吗?
<|im_end|>
<|im_start|>assistant
今天不会下雨,是个好天气。
<|im_end|>
标签分配规则为: 用户部分(含特殊标记):全部为-100 助手部分(含回复内容和结束标记):实际 token ID 。
训练时,模型仅因未正确预测助手回复而计算损失,避免因未预测用户输入而受惩罚。
数据完成分词和标签分配后,组织为以下格式传递给训练循环:
{
"input_ids": [所有token IDs],
"attention_mask": [全部为1的序列,表示所有token都需要关注],
"labels": [混合了-100和实际token ID的序列]
}
前向传播:模型接收完整input_ids输入,生成每个位置的预测。
损失计算:仅在labels不为-100的位置计算损失。
反向传播:基于损失更新模型参数
数据集的构造思路
数据集的质量好坏直接决定着微调任务的成败,根据最近我收集的各种微调后效果不好的案例中,大部分也都是数据集质量的问题,我总结了以下几个可能会导致微调任务失败的问题:
数据量太小: 数据量不足时,模型无法学习到足够的特征规律,如果你调的训练轮数很大,非常容易出现过拟合(仅记住少量样本的噪声信息),导致泛化能力差,在新数据上表现不佳。当然不同的微调任务对数据量的要求不一样,如果是领域知识注入类任务,(7B模型)至少要 1000 条数据起步,数据集的数量的扩大也要随着模型参数的变大而增加。另外也别迷信 “数据越多越好”,若数据质量差,海量数据反而会放大噪声影响。优先保证单条数据的有效性,再考虑扩充数量。
噪声数据多:如文本数据中存在大量错别字、格式混乱,图像数据模糊、标注错误等,会误导模型学习错误的映射关系。所以数据集一定要进行清洗,文本数据重点筛除乱码、重复内容、与任务无关的段落(比如微调法律模型时混入娱乐新闻);标注数据需检查标签 - 内容一致性(如情感分类中 “好评” 文本误标为 “差评”)。
样本偏差严重: 数据分布与实际应用场景差异大(如训练数据中 90% 是正面评论,而实际测试数据正负比例均衡),导致模型在真实场景下失效。
任务相关性不够:要模型学会一个领域的知识,不是说这个领域的所有数据都建议用于训练,比如你要微调一个金融问答模型时,就不要混入大量的财经新闻,因为新闻侧重事件描述,而问答侧重问题解答,数据形式需贴近实际应用场景(如 “问题 - 答案” 对)。
数据多样性不足: 样本覆盖的场景、特征维度单一(如文本数据仅包含短句子,缺乏长句或复杂句式;图像数据仅包含晴天场景,没有雨天、夜晚等),模型无法适应真实应用中的多样性需求。此外,若指令类型单一(如仅包含「解释型」指令),缺乏「推理型」「操作型」指令,会导致模型在实际应用中能力受限。
在本地微调任务中,以下是数据集构造思路:为确保模型能学习到专业的 Web 安全知识,选择从 Web 安全领域的专业书籍来提取部分数据集;为确保模型能学习到 Web 安全领域最前沿的知识,精选几篇 Web 安全相关的最新论文来提取部分数据集:
《The Hidden Risks of LLM-Generated Web Application Code: A Security-Centric Evaluation of Code Generation Capabilities in Large Language Models》
《WASP: Benchmarking Web Agent Security Against Prompt Injection Attacks》
《A Human Study of Cognitive Biases in Web Application Security》
《Web安全深度剖析》
《白帽子讲Web安全》
为确保模型能够学习均衡,不遗漏 Web 安全领域的知识,弥补和满血版大模型的差距,选取更为强大的满血版大模型(DeepSeek R1 0528)作为教师模型来蒸馏部分数据集;同时将提取教师模型的推理过程(COT)来作为数据集的一部分,用于训练基础模型的推理能力;为确保数据集的多样性,在数据集构造过程中将使用 GA(Genre-Audience)的思路来对数据集进行增强;在数据集构造完成后,邀请 Web 安全领域专家来对数据集进行 Review(人工审核),确保数据集最终质量。
在本次任务中,将使用如下模型:
Qwen3-235B-A22B:用于建立领域树、从文本块中提取问题(速度快、结构化输出更稳定)
DeepSeek-r1-250528:用户从文本块中为指定问题提取答案(推理模型,可获取思维链)
MinerU:用于自定义视觉模型解析 PDF文件(比基础解析效果更好)
MinerU下载地址:https://github.com/opendatalab/MinerU/blob/master/README_zh-CN.md
MinerU本地部署:https://py3study.com/Article/details/id/20108.html
上一篇: MinerU-linux环境本地部署
下一篇: 没有了
48966
48099
38839
35966
30382
27169
26162
20997
20831
19184
16°
24°
39°
723°
793°
772°
774°
753°
699°
826°