★★★ 本文源自AlStudio社区精品项目,【点击此处】查看更多精品内容 >>>
0 项目背景
信息抽取任务旨在从非结构化的自然语言文本中提取结构化信息。在本系列项目中,将讨论如何又好又快地实现一个简历信息提取任务。
在前置项目中,我们已经基于简历数据集,完成了文本格式简历抽取模型的微调和部署应用。
作为该系列文章的第七篇,我们将聚焦于更接近真实需求的应用场景,展开进一步的研究。
不妨假设一下,如果我们是企业的HR,或者某个小组里的PM,面对汹涌而来的简历,最关心的是什么?
通常情况下,如果是缺人的情况下招人,应该是有明确目的,想要找到符合相应要求的人。比如,缺一个搞过网络安全的专家、缺一个会写SQL画BI报表的开发者、缺一个熟悉C++的运维……
我们要招个C++后端运维,肯定不会优先看只有Java开发经验的人员,对吧?所以,简历的筛选,不仅仅是把常规个人信息汇总下,如果能够针对我们特定的需求进行筛选,才更符合企业需要,对不?
接下来,在本项目中,我们就尝试用ERNIE-Layout强大的文档智能能力,完成基于特定问答的简历筛选任务。
0.1 参考资料
- 简历信息提取(一):PDFPlumber和PP-Structure
- 简历信息提取(二):HR救星!用UIE Taskflow快速完成简历信息批量抽取
- 简历信息提取(三):文本抽取的UIE格式转换与微调训练
- 简历信息提取(四):文本抽取微调模型的部署应用
- 简历信息提取(五):用VI-LayoutXLM提升关键信息抽取效果
- 简历信息提取(六):基于VI-LayoutXLM识别结果的微调训练和部署
1 环境准备
1.1 安装依赖库
# 安装依赖库
!pip install paddlenlp==2.5 --user
!pip install --upgrade paddleocr --user
!pip install PyMuPDF==1.19
1.2 数据准备
# 解压缩数据集
!unzip data/data40148/train_20200121.zip
import datetime
import os
import cv2
import shutil
import numpy as np
import pandas as pd
import json
import fitz
from tqdm import tqdm
2 ERNIE-Layout文档智能问答
文档智能(DI, Document Intelligence)主要指对于网页、数字文档或扫描文档所包含的文本以及丰富的排版格式等信息,通过人工智能技术进行理解、分类、提取以及信息归纳的过程。
在实际应用中,需要解决文档格式繁杂、布局多样、信息模态多样、需求开放、业务数据少等多重难题。在这方面,基于多语言跨模态布局增强的文档智能大模型ERNIE-Layout的表现显然是非常出色的。
接下来,我们就尝试下直接用PaddleNLP.Taskflow调用ERNIE-Layout,看看它简历数据集的问答表现。
from pprint import pprint
from paddlenlp import Taskflow
docprompt = Taskflow("document_intelligence")
pprint(docprompt([{"doc": "./0c9c7d0b1170_0.jpeg", "prompt": [ "姓名是什么?", "出生时间?", "毕业于哪里?","开发什么报表?", "负责什么视频工作?"]}]))
[2023-02-16 17:26:17,304] [ INFO] - We are using <class 'paddlenlp.transformers.ernie_layout.tokenizer.ErnieLayoutTokenizer'> to load 'ernie-layoutx-base-uncased'.
[2023-02-16 17:26:17,309] [ INFO] - Already cached /home/aistudio/.paddlenlp/models/ernie-layoutx-base-uncased/vocab.txt
[2023-02-16 17:26:17,312] [ INFO] - Already cached /home/aistudio/.paddlenlp/models/ernie-layoutx-base-uncased/sentencepiece.bpe.model
[2023-02-16 17:26:18,044] [ INFO] - tokenizer config file saved in /home/aistudio/.paddlenlp/models/ernie-layoutx-base-uncased/tokenizer_config.json
[2023-02-16 17:26:18,048] [ INFO] - Special tokens file saved in /home/aistudio/.paddlenlp/models/ernie-layoutx-base-uncased/special_tokens_map.json
[{'prompt': '姓名是什么?',
'result': [{'end': 190, 'prob': 0.99, 'start': 189, 'value': '伍雁'}]},
{'prompt': '出生时间?',
'result': [{'end': 384, 'prob': 1.0, 'start': 382, 'value': '1949.12'}]},
{'prompt': '毕业于哪里?',
'result': [{'end': 23, 'prob': 1.0, 'start': 14, 'value': '北京市海淀区职工大学'}]},
{'prompt': '开发什么报表?',
'result': [{'end': 725, 'prob': 0.76, 'start': 718, 'value': '年度财务决算报表'}]},
{'prompt': '负责什么视频工作?',
'result': [{'end': 108, 'prob': 0.85, 'start': 97, 'value': '公司视频录制、拍摄制作;'}]}]
频录制、拍摄制作;'}]}]
通过运行上面这段代码,我们成功从下面的简历图片中抓取到了报表制作和视频开发这两个极有可能和岗位需求密切相关的工作经验。
相比于传统的简历筛选要HR一个个看过去,显然这种高效的方法更加有应用潜力。
而且,它还能避免简历筛选可能存在的“一刀切”问题——HR简历看不过来,直接筛选学历学位,对候选人一刀切,但是忽略了企业有时候会更加关注的相关工作经验问题。
接下来,我们就尝试对批量简历数据集进行处理,都用上智能文档问答能力,帮助HR/PM们快速锁定需求对口的应聘者。
3 简历批量筛选实现
在这里,我们主要基于前置项目的pdf批量转图片脚本进行开发。
prompt = [ "姓名是什么?", "出生时间?", "毕业于哪里?","电话是多少?", "邮箱是什么?","开发什么报表?"]
def get_pic_answer(path, prompt, filename):
# 将整理后的抽取结果返回为字典
if os.path.splitext(path)[-1]=='.pdf':
pdfDoc = fitz.open(path)
result = []
flag = 0
for pg in range(pdfDoc.page_count):
page = pdfDoc[pg]
rotate = int(0)
zoom_x = 4 # (1.33333333-->1056x816) (2-->1584x1224)
zoom_y = 4
mat = fitz.Matrix(zoom_x, zoom_y).prerotate(rotate)
pix = page.get_pixmap(matrix=mat, alpha=False)
# 保存过渡图片
pix.save('temp.jpeg')
# 读取图片进行智能文档问答
res = docprompt([{"doc": 'temp.jpeg', "prompt": prompt}])
if len(res[0]['result'][0]['value']) > 0 and (res[0]['result'][0]['prob'] > 0.5):
result.append("姓名:" + res[0]['result'][0]['value'])
if len(res[1]['result'][0]['value']) > 0:
result.append("出生时间:" + res[1]['result'][0]['value'])
if len(res[2]['result'][0]['value']) > 0:
result.append("毕业院校:" + res[2]['result'][0]['value'])
if len(res[3]['result'][0]['value']) > 0:
result.append("联系方式:" + res[3]['result'][0]['value'])
if len(res[4]['result'][0]['value']) > 0:
result.append("邮箱:" + res[4]['result'][0]['value'])
# 设置关键问答搜索条件
if len(res[5]['result'][0]['value']) > 3 and (res[5]['result'][0]['prob'] > 0.5):
result.append("相关经验:" + res[5]['result'][0]['value'])
flag = 1
if flag==1:
print(result)
# 把具备相关经验的人员简历筛选出来
shutil.copy(path,filename)
def get_answer(dir_path, prompt):
filenames = os.listdir(dir_path)
result = []
for filename in tqdm(filenames):
get_pic_answer(os.path.join(dir_path,filename), prompt, filename)
get_answer('resume_train_20200121/pdf', prompt)
由于简历文件较多,项目展示部分输出结果如下:
0%| | 2/2001 [00:18<5:19:21, 9.59s/it]
['姓名:雷磊鸣', '出生时间:1962.05', '毕业院校:中华女子学院', '联系方式:C13905722419', '邮箱:w1f3aw@126.com', '相关经验:资金报表', '相关经验:编制每月财务报表']
0%| | 10/2001 [01:29<4:41:16, 8.48s/it]
['姓名:贾良', '毕业院校:北京戏曲艺术职业学院', '联系方式:15100164319', '邮箱:slujm7bu@yahoo.com', '相关经验:资金报表']
4 模型部署
本项目的部署效果读者可以在【应用体验】中查看,相关代码保存在untitled.streamlit.py
中。
读者可上传简历图片并设置要抽取的工作经验信息。
5 小结
在本项目中,我们使用PaddleNLP提供的ERNIE-Layout文档智能问答能力,完成了针对特定业务需求的简历问答筛选功能开发,使用ERNIE-Layout的预训练模型,在简历文档问答任务上已经有了不错的表现。
当然,在项目中我们也发现,要真真正正能够实现这个场景模型落地,完全满足业务需要,还是绕不开针对ERNIE-Layout的微调训练。
在后续项目中,我们将对此进行进一步的探索。