• 赛题名称:标书实体抽取挑战赛
  • 赛题类型:自然语言处理
  • 赛题链接👇:

https://challenge.xfyun.cn/topic/info?type=physical-extraction-of-tender&ch=vWxQGFU

赛事背景

目前,能源行业在非招标采购业务过程中,标准化不够、结构化不足,难以满足自动化评审,为促进非招标采购业务无人自动化评审,开展采购业务标准化、评审因素结构化治理,进而研究采购文件、报价文件、资质证照和业绩合同等文档的智能解析与结构化,实现评审过程自动化、智能化,提升采购效率,实现降本增效。

通过本次比赛,推动参赛者对非标采购文件进行智能解析和结构化处理,提取关键信息,促进自动化评审。我们希望通过这样的方式,激发行业创新,推动非招标采购业务的标准化和智能化发展研究。

赛事任务

本次比赛需要参赛选手对给定的非标采购文件进行实体抽取,衡量标准是抽取非标采购文件实体要素准确率。该比赛的研究内容包括学术文档的版面分析、要素抽取及语义理解等,要求参赛选手能够将非标采购文件里定量定性的技术指标和非定量定性的详述类指标信息识别与提取。

赛题数据集

本次比赛为参赛选手提供了50份能源行业非招标采购业务的采购文件脱敏数据作为训练数据,50份作为测试集。

评价指标

任务采用F1-score进行评价,抽取的实体要素完全一致视为准确提取。

基础思路

赛题输入的pdf是扫码版本,因此首先需要对图片提取文字,然后从文字中提取到待匹配的要素。

  • 步骤1:使用paddleocr识别文本
  • 步骤2:使用chatgpt抽取指定要素
  • 步骤3:将结果进行汇总,得到最终输出
# 导入基础环境库
import glob
from pdf2image import convert_from_path
import pandas as pd
import requests
from io import StringIO

# 训练集路径
train_pdf = glob.glob('./标书实体抽取挑战赛公开数据/train/pdf/*')
train_label = glob.glob('./标书实体抽取挑战赛公开数据/train/label/*')

train_pdf.sort()
train_label.sort()

# 测试集路径
test_pdf = glob.glob('./标书实体抽取挑战赛公开数据/test/pdf/*')
test_label = glob.glob('./标书实体抽取挑战赛测试集要素名称/*')

test_pdf.sort()
test_label.sort()

# 加载paddleocr环境
from paddleocr import PaddleOCR, draw_ocr
ocr = PaddleOCR(use_angle_cls=True, lang="ch")
# 对测试集每个pdf和待pip要素
for pdf_path, label_path in zip(test_pdf[:], test_label[:]):
    
    # 读取待提取的信息
    df = pd.read_excel(label_path)
    df['要素点'] = ''
    
    # 提取pdf内容
    # 这里可以对pdf内容进行筛选,可以重点关注开始页和结束页
    pages = convert_from_path(pdf_path, 200)
    pages = [pages[0], pages[1], pages[-1]]
    
    # 存储提取好的内容
    content = ''
    for count, page in enumerate(pages):
        page.save(f'out.jpg''JPEG')

        result = ocr.ocr('out.jpg', cls=True)
        for idx in range(len(result)):
            res = result[idx]
            for line in res:
                content += line[1][0] + '\n'

        content += '\n'
    
    # 将pdf内容分页提取要素
    # api申请购买:https://api2d.com/
    url = "https://oa.api2d.site/v1/chat/completions"
    headers = {
        'Content-Type''application/json',    
        'Authorization''Bearer 替换为申请的chatgpt-key',
    }
    table_extract_result = []
    total_page = len(content.split('\n'))
    for idx in range(total_page // 50 + 1):
        input_content = '\n'.join(content.split('\n')[idx*50:(idx+1)*50])

        data = {
            "model""gpt-3.5-turbo",

            "messages": [{"role""user""content"
            f"""
            【任务】帮我从内容中提取信息,填充下面的表格,如果无法填充,则填无。只需要输出待填充表格。

            【输入信息】
            {input_content}

            【待填充表格内容】
            {df.to_markdown()}
            "
""}]
        }

        response = requests.post(url, headers=headers, json=data)
        table_extract_result.append(response.json()['choices'][0]['message']['content'])
    
    # 将最终结果汇总为最终格式
    table_extract_result = '\n\n'.join(table_extract_result)

    data = {
        "model""gpt-3.5-turbo",
        "messages": [{"role""user""content"
        f"""
        【任务】帮将表格信息进行合并,只需要输出待填充表格。

        【输入信息】
        {table_extract_result}

        【表格最终格式】
        {df.to_markdown()}
        "
""}]
    }

    response = requests.post(url, headers=headers, json=data)
    
    print(pdf_path)
    print(response.json()['choices'][0]['message']['content'])
    
    try:
        pd.read_csv(
            StringIO(response.json()['choices'][0]['message']['content'].replace(' ''')),  # Get rid of whitespaces
            sep='|',
            index_col=1
        ).dropna(
            axis=1,
            how='all'
        ).iloc[1:]['要素点'].to_csv('./submit/' + pdf_path.split('/')[-1][:-4] + '.csv', index=None, header=None)
    except:
        pass

这里只是一个初步思路,但已经是排行榜第一的分数。需要同学自己使用chatgpt或chatglm来提取要素并进行合并。

上述思路还有很多可以改进的地方,如对文本段落进行合并,或则修改prompt。

完整代码见👇:

https://github.com/datawhalechina/competition-baseline/tree/master/competition/%E7%A7%91%E5%A4%A7%E8%AE%AF%E9%A3%9EAI%E5%BC%80%E5%8F%91%E8%80%85%E5%A4%A7%E8%B5%9B2023

 竞赛交流群 邀请函  #

△长按添加竞赛小助手

每天大模型、算法竞赛、干货资讯

与 36000+来自竞赛爱好者一起交流~

内容中包含的图片若涉及版权问题,请及时与我们联系删除