简介

DeepKE 作为一个全面的知识提取工具包,不仅在构建知识图谱方面展现出卓越性能,还针对多种场景(如cnSchema、低资源环境、文档级处理和多模态分析)提供了强大支持。它能高效提取实体、关系和属性,并为初学者提供了详尽的使用手册

在当前的知识提取图谱构建领域,DeepKE迎合了ChatGPTLlaMABaichuan等大型语言模型的发展趋势,并推出了LLM版本DeepKE-LLM利用先进的闭源语言模型如ChatGPT执行零样本和少样本的知识提取任务,同时支持用户对LlaMABaichuan等模型进行指令数据集微调训练,进一步提升指令驱动的知识抽取效果。更多详情可见其 GitHub项目页面

DeepKE-LLM框架目前处于积极开发阶段,整合了In-Context Learning(ICL)技术和LoRAP-Tuning等大模型参数高效微调方法。框架支持与LLaMAChatGLMMOSSBaichuan等多个开源大型语言模型的兼容,并为每个模型设计了具体的应用案例,展示了微调后模型的能力。

DeepKE-LLM 的安装

conda create -n deepke-llm python=3.9    # 创建虚拟环境
conda activate deepke-llm                # 激活该环境
cd example/llm                           # 进入example/llm目录下
pip install -r requirements.txt          # 安装依赖

请注意,此处requirements.txt文件与DeepKE的有所不同,确保版本严格匹配以避免潜在错误。

torch==2.0.1
accelerate==0.20.3
transformers==4.30.2
bitsandbytes==0.39.1
peft==0.4.0
datasets==2.12.0
sentencepiece==0.1.98
scipy==1.10.1
protobuf==3.20.1
pydantic==1.10.7

注意版本一定要严格匹配,否则可能出现一些未知的错误!!!

方法一:In-Context Learning 上下文学习

本节聚焦于通过API调用ChatGPT等闭源大型语言模型所实现的上下文学习方法。在 DeepKE/example/llm/LLMICL 目录下,ICL技术被成功应用于大语言模型,以执行诸如信息抽取数据增强少样本关系抽取基于指令的知识图谱构建等关键任务。可以通过此目录下提供的案例,深入了解这些任务的实施细节和效果。

使用方法

1、安装所需的附加依赖包:

pip install easyinstruct
pip install hydra-core

2、按照DeepKE/example/llm/LLMICL/data目录下的各任务数据格式,准备上下文学习的示例,如关系抽取任务中的一个示例所示:

[
    {
        "text": "孔正锡,导演,2005年以一部温馨的爱情电影《长腿叔叔》敲开电影界大门。",
        "head_type": "电影名称",
        "head_entity": "长腿叔叔",
        "tail_type": "人名",
        "tail_entity": "孔正锡",
        "relation": "导演"
    }
]

3、在 DeepKE/example/llm/LLMICL/conf 目录下的run.yaml文件中,设置相应的参数,如下所示:

task: "ee"                    # 任务类型,选择[ner, re, ee, rte, da]中的一项
language: "en"                # 语言选择,["en", "ch"]中的一项
engine: "text-davinci-003"    # 选择大型语言模型的版本,支持多种选项
api_key: ""                   # OpenAI的API密钥
text_input: "输入文本示例"      # 需要处理的文本输入
zero_shot: True               # 是否为零样本或少样本学习
instruction: None             # 指令,即系统提示
data_path: ""                 # 示例数据的存储路径,默认为data目录
domain: "sport"               # 领域标签
labels: None                  # 实体标签,如['PER', 'ORG', 'LOC']

4、完成以上步骤后,运行python run.py命令开始执行任务。

方法二:Lora微调

LoRA通过学习秩分解矩阵对来减少可训练参数的数量,同时冻结原始权重。这大大降低了适用于特定任务的大型语言模型的存储需求,并在部署期间实现了高效的任务切换,而无需引入推理延迟。详细可查看论文LoRA: Low-Rank Adaptation of Large Language Models.

数据

相关内容在 DeepKE/example/llm/InstructKGC 目录下,本部分专注于采用指令数据集对开源大型语言模型如LlaMA、Baichuan等进行LoRA(Low-Rank Adaptation)微调,以优化模型在特定任务上的性能。DeepKE-LLM 提供了一个的信息抽取(IE)指令数据集 InstructIE,专门用于进行指令式微调。在此之前,需要使用数据转换脚本 DeepKE/example/llm/InstructKGC/kg2instruction/convert.py 来将数据集转换为模型可识别的格式,具体操作如 README.md 中所述,参数保持默认即可。执行以下命令以开始数据转换:

python kg2instruction/convert.py \
  --src_path data/NER/sample.json \
  --tgt_path data/NER/processed.json \
  --schema_path data/NER/schema.json \
  --language zh \      # 指定转换脚本和模板使用的语言, ['zh', 'en']
  --task NER \         # 指定任务类型:['RE', 'NER', 'EE', 'EET', 'EEA'] 中的一种
  --sample -1 \        # 如果为-1,则随机采样20种指令和4种输出格式中的一种;如果为指定数值,则使用对应的指令格式,取值范围为 -1<=sample<20
  --neg_ratio 1 \      # 设置所有样本的负采样比例
  --neg_schema 1 \     # 设置从schema中负采样的比例
  --random_sort        # 是否对指令中的schema列表进行随机排序

以下是一个实体识别(NER)任务数据转换的示例:

转换前:
{"input": "相比之下,青岛海牛队和广州松日队的雨中之战虽然也是0∶0,但乏善可陈。", "entity": [{"entity": "广州松日队", "entity_type": "组织机构"}, {"entity": "青岛海牛队", "entity_type": "组织机构"}]}

转换后:
{"id": "e88d2b42f8ca14af1b77474fcb18671ed3cacc0c75cf91f63375e966574bd187", "instruction": "请在所给文本中找出并列举['组织机构', '人物', '地理位置']提及的实体类型,不存在的类型请注明为NAN。回答应按(实体,实体类型)\n格式进行。", "input": "相比之下,青岛海牛队和广州松日队的雨中之战虽然也是0∶0,但乏善可陈。", "output": "(青岛海牛队,组织机构)\n(广州松日队,组织机构)\nNAN\nNAN"}

在转换之前,数据的格式需要符合DeepKE/example/llm/InstructKGC/data目录下为各项任务(如NER、RE、EE)规定的结构。以NER任务为例,输入文本应标记为input字段,而标注数据则应标记为entity字段,它是一个包含多个entityentity_type键值对的字典列表。

数据转换后,将得到包含input文本、instruction指令(详细说明了候选实体类型['组织机构', '人物', '地理位置']和期望的输出格式),以及output(以(实体,实体类型)形式列出input中识别的所有实体信息)的结构化数据

训练

DeepKE/example/llm/InstructKGC/ft_scripts目录中,提供了一系列针对各大开源模型的训练脚本。按照 README.md 作者已在RTX3090 GPU上成功运行了这些脚本,具体的脚本文件如下:

├── fine_baichuan.bash
├── fine_chatglm.bash
├── fine_cpmbee.bash
├── fine_llama.bash
├── fine_moss.bash
└── fine_vicuna.bash

fine_llama.bash脚本为例,下面展示了其内容和参数设置:

output_dir='path to save Llama Lora'
mkdir -p ${output_dir}
CUDA_VISIBLE_DEVICES="0,1" torchrun --nproc_per_node=2 --master_port=1331 src/finetune.py \
    --do_train --do_eval \
    --model_name_or_path 'path or name to Llama' \     
    --prompt_template_name 'alpaca' \     # 选择使用的模板名称,目前DeepKE-llm支持[alpaca, vicuna, moss]等模板。
    --model_name 'llama' \                # 指定模型名称,DeepKE-llm支持多种模型,如["llama", "falcon", "baichuan", "chatglm", "moss", "alpaca", "vicuna", "zhixi"]。
    --train_file 'data/train.json' \      # 训练集文件路径,系统会从中划分验证集。
    --output_dir=${output_dir} \          # 保存LoRA微调权重的目录。
    --per_device_train_batch_size 16 \    # 指定每个设备上的训练批量大小。
    --per_device_eval_batch_size 16 \     # 指定每个设备上的评估批量大小。
    --gradient_accumulation_steps 8 \     # 梯度累积步骤数,用以增大有效批量大小。
    --preprocessing_num_workers 8 \       # 预处理数据时的工作进程数。
    --num_train_epochs 10 \               # 训练迭代的总纪元。
    --learning_rate 1e-4 \                # 学习率。
    --optim "adamw_torch" \               # 优化器类型。
    --cutoff_len 512 \                    # 输入截断长度。
    --val_set_size 1000 \                 # 定义验证集的样本数量,默认为1000。
    --evaluation_strategy "epoch" \       # 评估策略,这里是每个epoch结束时进行评估。
    --save_strategy "epoch" \             # 保存策略,这里是每个epoch结束时保存模型。
    --save_total_limit 10 \               # 保存的模型文件总数限制。
    --lora_r 8 \                          # LoRA的秩r,用于确定LoRA适配器的大小。
    --lora_alpha 16 \                     # LoRA的缩放因子alpha。
    --lora_dropout 0.05 \                 # LoRA适配器中的dropout率。
    --max_memory_MB 24000 \               # 最大显存使用限制(以MB为单位)。
    --fp16 \                              # 使用半精度浮点数进行训练,以减少内存使用并提高训练速度。
    --bits 4 \                            # 使用混合精度的位数,这里是4位。
    | tee ${output_dir}/train.log \
    2> ${output_dir}/train.err

在执行微调过程中,系统首先输出了一些关键的配置信息。这包括了特殊的token,如bos(开始符号)、eos(结束符号)、pad(填充符号)及其相应的token id。这些token对于模型了解输入文本的开始、结束以及处理不同长度的文本至关重要。此外,还展示了训练的参数量及其在整体模型参数中的比例,这里大约是0.83%,这提供了微调的参数范围和对总参数量的影响程度的直观理解。

图1

随后,训练过程中的loss变化被记录并显示。图2显示了loss随训练时间稳定下降的情况,这是模型学习并逐步优化其权重的明确迹象,反映了训练过程的平稳进展。

图2

最终输出信息包含了训练完成后的汇总数据,这些数据为模型性能提供了评估基准,这些输出信息为了解模型训练效果和调整后续训练策略提供了宝贵的参考。

图3

KnowLM

该模型对LLaMA(13B)模型进行了定制化的增量预训练,专注于汉语语料,显著提升了模型对汉语的理解及其知识库的深度。此阶段成果是 KnowLM-13b-base-v1.0 基础模型,可在 Hugging Face的KnowLM-13b-base-v1.0页面 上找到。进一步,利用开源的信息抽取(IE)和常识指令数据集,对 KnowLM-13b-base-v1.0 进行了微调,以提升其对人类指令进行知识提取任务的适应性。微调后的KnowLM-13B-IE模型,在指令式信息抽取方面表现优异,该模型可通过Hugging Face的KnowLM-13B-IE页面获取。

预测

以下是使用KnowLM-13B-IE进行关系抽取的操作示例:

CUDA_VISIBLE_DEVICES="0" python src/inference.py \
    --model_name_or_path 'zjunlp/KnowLM-13B-IE' \
    --model_name 'zhixi' \
    --input_file 'data/valid.json' \
    --output_file 'results/results_valid.json' \
    --fp16 \
    --bits 8

这里model_name_or_path参数指定为Hugging Face的模型ID,即zjunlp/KnowLM-13B-IE,会自动下载模型,或者可以指向已下载至本地的模型目录。model_name设置为zhixi,以确保与模型架构相匹配。input_file对应已处理的数据格式,包含必要的instructioninput字段。一个典型的KnowLM-13B-IE输出如下:

{
    "id": "c15f97068c77d652041bc7531d35c93f45ec2adc5c624a8c76b72a32963efeaf", 
    "instruction": "Identify the head entities (subjects) and tail entities (objects) in the following text and provide the corresponding relation triples from relation list ['competition class', 'location', 'operating system', 'owned by', 'religion']. Please provide your answer as a list of relation triples in the form of (Subject,Relation,Object)\n.", 
    "input": "In 1689 , Konstanty was one of the judges who sentenced Kazimierz Lyszczyski to death for atheism .", 
    "output": "(Kazimierz Lyszczyski, competition class, atheism),(NAN, location, NAN),(NAN, operating system, NAN),(NAN, owned by, NAN),(NAN, religion, NAN)"
}

另一种方法是结合基础大模型与LoRA技术来执行关系抽取任务:

CUDA_VISIBLE_DEVICES="0" python src/inference.py \
    --model_name_or_path 'zjunlp/knowlm-13b-base-v1.0' \
    --model_name 'zhixi' \
    --lora_weights 'zjunlp/knowlm-13b-ie-lora' \
    --input_file 'data/valid.json' \
    --output_file 'results/results_valid.json' \
    --fp16 \
    --bits 4

在这种情况下,lora_weights参数被设置LoRA权重,例如可以使用已提供的训练后的LoRA权重knowlm-13b-ie-lora,而model_name_or_path则使用基础模型 zjunlp/knowlm-13b-base-v1.0。下面是使用 knowlm-13b-base-v1.0 + knowlm-13b-ie-lora 的一个输出示例:

1、在指令中指定了候选关系列表:
{
    "id": "16e9a2d071d55413a3afb1e84c464d5e1e3d31330d6e0ab37ac5758390a6594c", 
    "instruction": "你是专门进行关系三元组提取的专家。已知候选的关系列表:['事件', '位于', '创建时间', '创建者', '别名', '名称由来', '宽度', '成就', '长度', '面积', '高度'],请你根据关系列表,从以下输入中抽取出可能存在的头实体与尾实体,并给出对应的关系三元组,如果不存在某关系就输出NAN。请按照(头实体,关系,尾实体)\n的格式回答。", 
    "input": "韦瓦克机场又叫博勒姆机场,是一座位于巴布亚新几内亚韦瓦克的机场。IATA代码:WWK;ICAO代码:AYWK。", 
    "output": "NAN\n(韦瓦克机场,位于,韦瓦克)\n(韦瓦克,位于,巴布亚新几内亚)\nNAN\nNAN\n(韦瓦克机场,别名,博勒姆机场)\nNAN\nNAN\nNAN\nNAN\nNAN\nNAN"
}

2、未在指令中指定候选关系列表:
{
    "id": "16e9a2d071d55413a3afb1e84c464d5e1e3d31330d6e0ab37ac5758390a6594c", 
    "instruction": "请从文本中抽取出所有关系三元组,并根据(头实体,关系,尾实体)\n的格式呈现结果。忽略那些不符合标准关系模板的实体。", 
    "input": "韦瓦克机场又叫博勒姆机场,是一座位于巴布亚新几内亚韦瓦克的机场。IATA代码:WWK;ICAO代码:AYWK。", 
    "output": "(韦瓦克机场,别名,博勒姆机场)\n(韦瓦克机场,位于,韦瓦克)"
}

在这个例子中,knowlm-13b-ie-lora版本在处理不存在的关系时做了优化:与KnowLM-13B-IE输出"(NAN,关系,NAN)"的格式不同,knowlm-13b-ie-lora简洁地输出"NAN",有效减少了输出token的长度,从而减少了单个样本推理所需的时间,提高了推理效率。此外,还支持在指令中不指定候选关系列表的命令

方法三:P-Tuning微调

PT方法,即P-Tuning方法,参考ChatGLM官方代码 ,是一种针对于大模型的soft-prompt方法。 P-Tuning,仅对大模型的Embedding加入新的参数。 P-Tuning-V2,将大模型的Embedding和每一层前都加上新的参数。

训练

要使用P-Tuning方法微调模型,DeepKE-llm提供了以下的命令:

deepspeed --include localhost:0 src/finetuning_pt.py \
  --train_path data/train.json \
  --model_dir /model \
  --num_train_epochs 20 \
  --train_batch_size 2 \
  --gradient_accumulation_steps 1 \
  --output_dir output_dir_pt \
  --log_steps 10 \
  --max_len 768 \
  --max_src_len 450 \
  --pre_seq_len 16 \
  --prefix_projection true

参数保持默认的即可。

预测

完成训练后,可以通过以下命令使用P-Tuning模型进行预测:

CUDA_VISIBLE_DEVICES=0 python src/inference_pt.py \
  --test_path data/valid.json \
  --device 0 \
  --ori_model_dir /model \
  --model_dir /output_dir_lora/global_step- \
  --max_len 768 \
  --max_src_len 450
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐