【LLM】解析pdf文档生成摘要

news2024/11/15 18:03:45

文章目录

  • 一、整体思路
  • 二、代码
  • 三、小结
  • Reference

一、整体思路

  • 非常简单的一个v1版本
    • 利用langchain和pdfminer切分pdf文档为k块,设置overlap等参数
    • 先利用prompt1对每个chunk文本块进行摘要生成,然后利用prompt2对多个摘要进行连贯组合/增删
    • 模型可以使用chatglm2-6b或其他大模型
  • 评测标准:信息是否涵盖pdf主要主题、分点和pdf一二级标题比大体是否一致、摘要是否连贯、通顺

在这里插入图片描述
Prompt1:分段总结

prompt1 = '''你是一个摘要生成器。请根据下文进行分段总结,请注意:
            1.输入数据为从pdf读入的文本,一句话可能存在跨越多行;
            2.要求每段内容不丢失主要信息, 每段的字数在50字左右;
            3.每段生成的摘要开头一定不要含有'第几段'的前缀文字;
            4.对下文进行分段总结:'''

Prompt2:内容整合

prompt2 = '''你是一个文章内容整合器,请注意:
            1.输入数据中含有多个已经总结好的段落;
            2.有的段落开头有这是第几段或者摘要的字样;
            2.请将每段信息进行优化,使得每段之间显得更加连贯,且保留每段的大部分信息;
            4.输入的的文章如下:'''

二、代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Author : andy
@Date   : 2023/8/23 10:09
@Contact: 864934027@qq.com
@File   : chunk_summary.py
"""
import json
from langchain.text_splitter import CharacterTextSplitter
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LAParams, LTTextBoxHorizontal
from pdfminer.pdfpage import PDFPage
import os
import pandas as pd

def split_document_by_page(pdf_path):
    resource_manager = PDFResourceManager()
    codec = 'utf-8'
    laparams = LAParams()
    device = PDFPageAggregator(resource_manager, laparams=laparams)
    interpreter = PDFPageInterpreter(resource_manager, device)

    split_pages = []
    with open(pdf_path, 'rb') as file:
        for page in PDFPage.get_pages(file):
            interpreter.process_page(page)
            layout = device.get_result()
            text_blocks = []
            for element in layout:
                if isinstance(element, LTTextBoxHorizontal):
                    text = element.get_text().strip()
                    text_blocks.append(text)
            page_text = '\n'.join(text_blocks)
            split_pages.append(page_text)

    return split_pages

def callChatGLM6B(prompt):
    pass

def summary(pdf_path, num):
    # 使用示例
    # pdf_path = "/Users/guomiansheng/Desktop/LLM/LangChain-ChatLLM/pdf_test.pdf"
    # pdf_path = 'example.pdf'  # 替换为你的 PDF 文件路径
    one_dict = {}
    pages = split_document_by_page(pdf_path)
    add_page_data = ''
    page_ans = ""
    print(f"=============这是第{num}个pdf\n")
    for i, page_text in enumerate(pages):
        # page_ans = page_ans + f"这是第{i}页pdf:\n" + page_text
        page_ans = page_ans + page_text
        print(f"Page {i + 1}:", "当前page的字数:", len(page_text))
        print(page_text)
        print("--------------------")

    # 文本分片
    text_splitter = CharacterTextSplitter(
        separator="\n",
        chunk_size=1500,
        chunk_overlap=150,
        length_function=len
    )
    chunks = text_splitter.split_text(page_ans)
    # chunks
    prompt0 = '''请根据下文进行分段总结, 要求每段内容不丢失主要信息, 每段的字数在50字左右:'''
    prompt = '''你是一个摘要生成器。请根据下文进行分段总结,请注意:
                1.输入数据为从pdf读入的文本,一句话可能存在跨越多行;
                2.要求每段内容不丢失主要信息, 每段的字数在50字左右;
                3.每段生成的摘要开头一定不要含有'第几段'的前缀文字;
                4.对下文进行分段总结:'''

    prompt3 = '''你是一个文章内容整合器,请注意:
                1.输入数据中含有多个已经总结好的段落;
                2.有的段落开头有这是第几段或者摘要的字样;
                2.请将每段信息进行优化,使得每段之间显得更加连贯,且保留每段的大部分信息;
                4.输入的的文章如下:'''
    ans = ""
    for i in range(len(chunks)):
        # response = callChatGLM66B(prompt + chunks[i])
        response = callChatGLM6B(prompt + chunks[i])
        if 'data' not in response.keys():
            print(response.keys(), "\n")
            print("========this chunk has problem=======\n")
            continue
        temp_ans = response['data']['choices'][0]['content'] + "\n"
        ans += temp_ans

    ans = ans.replace("\\n", '\n')
    # save txt
    # save_path = "/Users/guomiansheng/Desktop/LLM/LangChain-ChatLLM/save_6b_ans3_all"
    save_path = "/Users/guomiansheng/Desktop/LLM/LangChain-ChatLLM/gpt_diction"
    with open(save_path + '/ans' + str(num) + '.txt', 'w', encoding='utf-8') as file:
        file.write(ans)
    print("======ans========:\n", ans)
    one_dict = {'input': page_ans, "output": ans}
    return ans, one_dict


def main():
    # find 10 file
    def find_files_with_prefix(folder_path, prefix):
        matching_files = []
        for root, dirs, files in os.walk(folder_path):
            for file in files:
                if file.startswith(prefix) and file.endswith('.pdf'):
                    matching_files.append(os.path.join(root, file))
        return matching_files

    # 示例用法
    folder_path = '/Users/guomiansheng/Desktop/LLM/LangChain-ChatLLM/pdf_data_all'  # 替换为你的大文件夹路径
    # prefixes = ['pdf_0', 'pdf_1', 'pdf_2']  # 替换为你想要匹配的前缀列表
    prefixes = []
    for i in range(10):
        prefixes.append('pdf_' + str(i))
    matching_files = []
    for prefix in prefixes:
        matching_files.extend(find_files_with_prefix(folder_path, prefix))
    # del matching_files[0]
    # del matching_files[0]

    ans_lst = []
    for i in range(len(matching_files)):
        one_ans, one_dict = summary(matching_files[i], i)
        ans_lst.append(one_dict)
    # pdf_path = "/Users/guomiansheng/Desktop/LLM/LangChain-ChatLLM/pdf_test.pdf"
    # summary(pdf_path)
    return ans_lst


def preprocess_data(ans_lst):
    json_path = "/Users/guomiansheng/Desktop/LLM/LangChain-ChatLLM/summary_ft_data.json"
    with open(json_path, "w", encoding='utf-8') as fout:
        for dct in ans_lst:
            line = json.dumps(dct, ensure_ascii=False)
            fout.write(line)
            fout.write("\n")


def read_data():
    json_path = "/Users/guomiansheng/Desktop/LLM/LangChain-ChatLLM/summary_ft_data.json"
    with open(json_path, "r", encodings='utf-8') as f:
        lst = [json.loads(line) for line in f]
        df = pd.json_normalize(lst)


if __name__ == '__main__':
    ans_lst = main()
    preprocess_data(ans_lst)

随便找了个介绍某个课程内容的pdf,结果如下,概括了课程的三天主题内容,同时也将pdf中的数据湖理念等概念进行分点概括:

" 教育即将推出名为“数据湖,大数据的下一场变革!”的超强干货课程。该课程分为三天,

第一天的主题是“数据湖如何助力企业大数据中台架构的升级”,内容包括数据处理流程和大数据平台架构,以及数据湖和数据仓库的理念对比和应用;

第二天的主题是“基于 Apache Hudi 构建企业级数据湖”,将介绍三个开源数据湖技术框架比较,Apache Hudi 的核心概念和功能,以及基于 Hudi 构建企业级数据湖的方法;

第三天的主题是“基于 Apache Iceberg 打造新一代数据湖”,将深入探讨 Apache Iceberg 的核心思想、特性和实现细节,以及如何基于 Iceberg 构建数据湖分析系统。该课程由前凤凰金融大数据部门负责人王端阳主讲,他具有多年的大数据架构经验,擅长 Hadoop、Spark、Storm、Flink 等大数据生态技术,授课特点为拟物化编程 + 强案例支撑,旨在帮助学生快速建立完备的大数据生态知识体系。课程将在今晚 20:00 准时开课。"

" 
1.开放性:Lakehouse 使用开放式和标准化的存储格式,提供 API 供各类工具和引擎直接访问数据。  
2.数据类型支持:Lakehouse 支持从非结构化数据到结构化数据的多种数据类型。  
3.BI 支持:Lakehouse 可直接在源数据上使用 BI 工具。  
4.工作负载支持:Lakehouse 支持数据科学、机器学习以及 SQL 和分析等多种工作负载。  
5.模式实施和治理:Lakehouse 有 Schema enforcement and governance 功能,未来能更好的管理元数据,schema 管理和治理。  
6.事务支持:Lakehouse 支持 ACID 事务,确保了多方并发读写数据时的一致性问题。  
7.端到端流:Lakehouse 需要一个增量数据处理框架,例如 Apache Hudi。  
8.数据湖和数据仓库对比:数据湖采用读时模式,满足上层业务的高效分析需求,且无成本修改 schema。  
9.数据湖落地方案:包括基于 Hadoop 生态的大数据方案,基于云平台数据湖方案,基于商业产品的数据湖方案。  
10.数据湖助力数仓解决痛点:数据湖可以解决离线数仓和实时数仓的痛点问题,提高数据处理效率。  
11.数据湖帮助企业大数据中台升级:数据湖可以实现底层存储标准统一化,构建实时化标准层,提高数据存储的安全性、全面性和可回溯性。  
12.大数据中台实时数据建设要求:开源数据湖架构 Day02 基于 Apache Hudi 构建企业级数据湖。"

三、小结

  1. 之前存在的问题:生成重复、杜撰了事件中的时间、截断现象、每个chunk文本块之间的摘要不太连贯等
  2. 优化点:使用pdfminer和Langchain切分chunk文本块,对文本块进行摘要生成,然后将分块的摘要结合prompt2进行内容整合,使得语句连贯并且控制字数;top_p=0.5 temperature=0.8等
  3. 后续可继续优化的点:使用streamlist提取pdf中的表格对象内容、使用篇章分析discourse parsing更加细粒度地切分文档等

Reference

[1] 基于LLM+向量库的文档对话痛点及解决方案
[2] LangChain - 打造自己的GPT(二)simple-chatpdf
[3] 徒手使用LangChain搭建一个ChatGPT PDF知识库
[4] LangChain+ChatGPT三分钟实现基于pdf等文档问答应用
[5] pdfminer: https://euske.github.io/pdfminer/
[6] Python+Streamlit在网页中提取PDF中文字、表格对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/935711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

keras深度学习框架通过简单神经网络实现手写数字识别

背景 keras深度学习框架,并不是一个独立的深度学习框架,它后台依赖tensorflow或者theano。大部分开发者应该使用的是tensorflow。keras可以很方便的像搭积木一样根据模型搭出我们需要的神经网络,然后进行编译,训练,测试…

4.22 TCP 四次挥手,可以变成三次吗?

目录 为什么 TCP 挥手需要四次呢? 粗暴关闭 vs 优雅关闭 close函数 shotdown函数 什么情况会出现三次挥手? 什么是 TCP 延迟确认机制? TCP 序列号和确认号是如何变化的? 在一些情况下, TCP 四次挥手是可以变成 T…

如何识别PCI/PCIE设备需要申请多大的地址空间?

1、PCI/PCIE设备的配置空间 (1)PCI/PCIE设备需要的资源都在配置空间里进行指定,其中需要的地址空间资源在配置空间的基地址寄存器里指定; (2)参考博客:《PCI设备和PCI桥的配置空间(header_type0、header_type1)和配置命令(type0、type1)详解》…

交叉编译 libzdb

参考博客:移植libzdb3.2.2到arm_configure: error: no available database found or s_酣楼驻海的博客-CSDN博客 编译时间 2023-08-23 libzdb 下载: 源码访问如下: https://bitbucket.org/tildeslash/libzdb/src/master/ git 下载链接 …

JavaScript设计模式(一)——构造器模式、原型模式、类模式

个人简介 👀个人主页: 前端杂货铺 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…

Lottery抽奖项目学习第二章第一节:环境、配置、规范

Lottery抽奖项目学习第二章第一节:环境、配置、规范 环境、配置、规范 下面以DDD架构和设计模式落地实战的方式,进行讲解和实现分布式抽奖系统的代码开发,那么这里会涉及到很多DDD的设计思路和设计模式应用,以及互联网大厂开发中…

【GoLang】go入门:go语言执行过程分析 常见数据类型(基本数据类型)

1、go语言执行过程分析 【1】执行流程分析 通过 go build 进行编译 运行上一步生成的可执行文件 通过 go run 命令直接运行 【2】上述两种执行流程的区别 在编译时,编译器会将程序运行时依赖的库文件包含在可执行文件中,所以可执行文件会变大很多通过g…

c++中的基本类型

专栏简介:为什么我要重新介绍c的相关知识,在此之前,我对于c的了解也仅仅是在表面。而在后来与c慢慢的接触中,c编程语言越来越让我觉得深奥,所以还是想要重新开创一个专栏来介绍c。对于c的介绍,本专栏会先介…

学会shell 基本语法,玩转linux

01、获取当前时间,年月日时分秒 now$(date %Y%m%d%H%M%S) echo "$now" 输出为:20181202222727 02、date 在脚本中的几种用法 date %Y 以 4 位数字格式打印年份 date %y 以 2 位数字格式打印年份 date %m 月份 date %d 日期 date %H 小时 d…

IO模型和NGINX安装升级

IO模型和NGINX安装升级 IO模型 IO概念 I/O在计算机中指Input/Output, IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。 Linux的IO类型 磁盘I/O 磁盘I/O是进程向内核发起系统调用,请求磁…

抖店出单后怎么操作?谈厂家话术与发货注意事项,抖店最新教程

我是王路飞。 当你的抖店出单后,你是怎么操作的? 还是像之前那样去拼多多代拍发货?这样做的商家,不知道你的店铺被封了几个了? 记住,现在抖店出单后,一定不要再去多多拍单发货了! 关于抖店…

0基础入门C++之类和对象下篇

目录 1.再谈构造函数1.1构造函数赋值1.2初始化列表1.3explicit关键字 2.static成员2.1概念2.1静态成员变量2.2静态成员函数2.3特性 3.匿名对象4.友元函数4.1友元函数4.2友元类 5.内部类6.再次理解类和对象 1.再谈构造函数 首先我们先来回忆一下构造函数: 构造函数是…

【springboot】springboot定时任务:

文章目录 一、文档:二、案例: 一、文档: 【cron表达式在线生成器】https://cron.qqe2.com/ 二、案例: EnableScheduling //开启任务调度package com.sky.task;import com.sky.entity.Orders; import com.sky.mapper.OrderMapper; …

CAN总线学习——物理层、数据链路层、CANopen协议

1、CAN总线介绍 1.1、CAN总线描述 (1)CAN总线支持多节点通信,但是节点不分区主从,也就是不存在一个节点来负责维护总线的通信;这点可以和I2C总线对对比,I2C是一主多从模式; (2)是差分、异步、串行总线,采用…

分布式—雪花算法生成ID

一、简介 1、雪花算法的组成: 由64个Bit(比特)位组成的long类型的数字 0 | 0000000000 0000000000 0000000000 000000000 | 00000 | 00000 | 000000000000 1个bit:符号位,始终为0。 41个bit:时间戳,精确到毫秒级别&a…

Python slice(切片)

在Python中,切片(slice)是对序列型对象(如list, string, tuple)的一种高级索引方法。普通索引只取出序列中一个下标对应的元素,而切片取出序列中一个范围对应的元素,这里的范围不是狭义上的连续片段。 切片的基本语法为: object…

ChromeOS 的 Linux 操作系统和 Chrome 浏览器分离

导读科技媒体 Ars Technica 报道称,谷歌正在将 ChromeOS 的浏览器从操作系统中分离出来 —— 让它变得更像 Linux。虽然目前还没有任何官方消息,但这项变化可能会在本月的版本更新中推出。 据介绍,谷歌将该项目命名为 "Lacros"——…

防溺水预警识别系统算法

防溺水预警识别系统旨在通过opencvpython网络模型深度学习算法,防溺水预警识别系统算法实时监测河道环境,对学生等违规下水游泳等危险行为进行预警和提醒。Python是一种由Guido van Rossum开发的通用编程语言,它很快就变得非常流行&#xff0…

strcat函数

目录 函数介绍: 函数声明: 具体使用: 注意事项: 字符串⾃⼰给⾃⼰追加,如何? 模拟实现strcat函数: 函数介绍: 被称为字符串的追加/链接函数,它的功能就是在一个字符…

gcc/linux下的c++异常实现

概述 本文不一定具有很好的说教性,仅作为自我学习的笔记。不妨可参阅国外大神博文C exceptions under the hood链接中包含了大量的例子。 偶有在对ELF做分析的时候看到如下图一些注释,部分关键字看不懂,比如什么FDE, unwind , __gxx_perso…