GraphGen:训练数据合成实践
任务来源:https://aicarrier.feishu.cn/wiki/GZG8wHdA5ickHQkQjJhcPr9Pnzh
任务完成标准:复现
在垂域模型(如医疗、农业)训练中,常常会面临数据短缺的问题。
用 SFT(Supervised Fine-Tuning)给模型注入新知识,需要数十万的样本量。同时,领域数据的标注需要专业背景,普通人难以胜任。此时数据合成手段是刚需。
1. GraphGen介绍
GraphGen是一个基于知识图谱的SFT数据生成框架。
该框架通过构建细粒度知识图谱、识别 LLMs 的知识盲点、并生成多风格的内容来提高模型在知识密集型任务上的表现。GraphGen 适用于三种关键问答场景:原子问答(atomic QA)、聚合问答(aggregated QA)和多跳问答(multi-hop QA)。
等待生成完成后,将会得到一个结果文件。
-
Atomic QA:最基础的问答形式,专注于单一知识点或事实。
-
Aggregated QA:涉及多个知识点或复杂信息的整合。
-
Multi-hop QA:需要通过多步推理,结合多个知识点才能回答。
-
-
步骤 名称 说明 步骤1 数据输入 提供原始图结构数据(节点、边)或相关文本数据作为输入。 步骤2 数据预处理 对文本进行分词、实体识别、关系抽取;对图结构进行格式化和构建。 步骤3 模型训练 使用图神经网络(GNN)和文本表示学习对输入数据建模,训练生成图结构的能力。 步骤4 图生成 输入新问题或样例,基于训练模型自动生成图结构,包括新增节点、边及其属性。 步骤5 后处理与优化 对生成图进行规范化处理,清理冗余信息,增强结构合理性与语义一致性。 步骤6 输出结果 生成最终图数据(如JSON、GraphML格式),可用于训练、可视化或其他下游任务。 -
Github仓库:https://github.com/open-sciencelab/GraphGen
-
2. GraphGen流程解析
1. 知识图谱构建
- 文本分割:将原始文档分割成语义连贯的小片段。
- 实体与关系提取:使用 Synthesizer Model 从片段中识别和提取实体及其关系。
- 知识图谱聚合:将不同片段中的相同实体或关系的描述自动合并,形成知识图谱。
2. 理解能力评估
- 知识表示:将知识图谱中的每个关系视为一个知识陈述 Ri,并生成其改写版本及否定版本。
- 置信度量化:通过 Trainee Model 对这些陈述的置信度进行评估,计算其对每个知识点的理解程度。
- 理解损失计算:通过计算真实分布与预测分布之间的交叉熵,来衡量 Trainee Model 对知识的理解差距。
3. 图组织
- 子图提取:执行 k-hop 子图提取,以有效组织知识图谱。采用深度策略、长度策略和选择策略来平衡子图的复杂性、相关性和计算可行性。
4. 问答对生成
- 原子 QA 生成:从单个节点或边生成基础问答对。
- 聚合 QA 生成:组织和改写子图中的数据,生成涉及多个实体和关系的综合性问答对。
- 多跳 QA 生成:明确实体间关系,生成需要多步推理的问答对。
步骤 名称 子模块 说明 举例 步骤1 知识图谱构建 文本分割 将原始文档按语义切分为较小的片段,便于处理。 “刘备与关羽桃园结义,张飞在场。”→ 分成两句。 实体与关系提取 使用 Synthesizer Model 提取片段中的实体及三元组关系。 提取出:〈刘备,结义,关羽〉,〈张飞,在场,结义〉 知识图谱聚合 自动合并不同片段中对相同实体/关系的表述,统一节点和边的表示。 “刘备” 与 “刘玄德” 归为同一节点“刘备”。 步骤2 理解能力评估 知识表示 将图中的关系表示成句子,并生成其改写版本与否定版本。 〈刘备,结义,关羽〉 →“刘备与关羽结义”,“刘备没有与关羽结义”。 置信度量化 使用 Trainee Model 对句子进行判断,输出模型置信度。 模型对正例给 0.92,反例给 0.05,说明理解较准确。 理解损失计算 用交叉熵比较真实分布与模型输出分布,衡量模型理解的偏差。 模型给正例 0.4、反例 0.6,损失高,说明理解有偏差。 步骤3 图组织 子图提取 从知识图谱中提取 k-hop 子图,构建更紧凑的图结构。 从“刘备”出发提取 2-hop 子图:刘备→关羽→张飞。 策略选择 控制子图的深度、边数、重要性等,平衡语义丰富性与计算复杂度。 使用 max_depth=2
、max_tokens=256
、edge_sampling=max_loss
。步骤4 问答对生成 原子 QA 生成 从单个节点或边生成基础问答。 Q: 刘备和谁结义?A: 关羽 聚合 QA 生成 整合多个关系,生成多实体多边的问答对。 Q: 桃园结义包括哪些人?A: 刘备、关羽、张飞 多跳 QA 生成 生成需要多步推理才能得出答案的问题。 Q: 谁与结义者一起参加了黄巾之乱?A: 张飞(需多跳推理) -
3. 环境
使用conda创建环境
-
conda create -n graphgen python=3.10 -y conda activate graphgen
-
下载GraphGen仓库,并安装依赖
-
git clone https://github.com/open-sciencelab/GraphGen.git cd GraphGen pip install -r requirements.txt
-
4. 运行GraphGen
3.1 使用Gradio Demo进行简单数据合成
1. 运行Gradio Demo,执行下述命令
-
python webui/app.py
-
本地打开cmd命令框进行本地与云端通信传输
-
填入调用LLM接口的base url、model和api key。
使用硅基流动https://siliconflow.cn/
进入API密钥页面,点击“新建API密钥”,创建您的API key
-
使用 internlm/internlm2_5-7b-chat 进行数据生成,分别修改下面三处:
Synthesizer URL: https://api.siliconflow.cn/v1
Synthesizer Model: internlm/internlm2_5-7b-chat
API Key: 申请的API Key
-
选择任意一个example file,或者上传格式相同的文件
-
点击
Run GraphGen
-
-
3.2 运行源码进行数据合成(我用了50%A100)
3.2.1 使用vllm部署Synthesizer Model和Trainee Model
-
conda create -n vllm python=3.12 -y conda activate vllm pip install vllm==0.8.5.post1
部署 internlm/internlm3-8b-instruct 的 OpenAI Compatible Server
vllm serve internlm/internlm3-8b-instruct --trust-remote-code
3.2.2 完成配置文件
在根目录中创建一个 .env 文件
-
cp .env.example .env
-
填入环境变量
-
SYNTHESIZER_MODEL=your-path/internlm3-8b-instruct SYNTHESIZER_BASE_URL=http://0.0.0.0:8000/v1 SYNTHESIZER_API_KEY= TRAINEE_MODEL=your-path/internlm3-8b-instruct TRAINEE_BASE_URL=http://0.0.0.0:8000/v1 TRAINEE_API_KEY=
说明:
-
1.上面_model使用vllm部署后会默认进行安装,一般按照如下填写即可
-
2.
-
检查/修改配置文件
configs/graphgen_config.yaml
-
data_type: raw input_file: resources/examples/raw_demo.jsonl tokenizer: cl100k_base quiz_samples: 2 traverse_strategy:qa_form: aggregatedbidirectional: trueedge_sampling: max_lossexpand_method: max_widthisolated_node_strategy: ignoremax_depth: 1max_extra_edges: 2max_tokens: 256loss_strategy: only_edge web_search: false re_judge: true
运行脚本生成数据(此处注意,运行环境不是vllm,应该是conda activate graphgen) -
bash scripts/generate.sh
运行效果
-
最后多说一下,bash scripts/generate.sh命令执行后我有很多次生成的数据都是0,后来我认为是jsonl文件的问题自己创建了新的数据文件就可以执行了,但是。。。再没有任何修改的情况下回头执行原本的数据命令,竟然成功了!!!可能原因如下吧
-
graphgen.generate
背后的流程调用了 Synthesizer 模型(如InternLM3-8B-Instruct
),如果第一次执行a.jsonl
没有触发模型初始化成功或未正常返回结果,就会导致生成数为 0。而执行
b.jsonl
成功之后,模型已经: -
成功 load 到内存(如 vLLM 实例已激活)
-
token 缓存、词典加载、分词器构建完
-