本文将会介绍如何使用fitz模块处理PDF文档,以及如何使用OpenAI大模型对PDF文档进行问答。
 
在文章NLP(六十一)使用Baichuan-13B-Chat模型构建智能文档 中笔者介绍如何使用大模型来构建智能文档问答助手,其中包括PDF文档。
在文本中,笔者将会介绍如何使用fitz模块来处理PDF文档,并基于此,再使用大模型对PDF文档内容进行智能问答,提升问答效果。
fitz模块介绍 
PyMuPDF和Fitz是用于在Python中处理PDF文件的相关模块。Fitz是PyMuPDF的子模块,提供了一个简化和封装版本的PyMuPDF功能。
关系: 
 
PyMuPDF:是一个强大灵活的Python库,用于处理PDF,不依赖其它Python包。 
Fitz:是PyMuPDF库的一个包装器,专门设计用于在Python中处理PDF文件。 
 
用途: 
 
PyMuPDF:提供了广泛的功能,用于操作PDF文档,包括方便的高级函数和底层操作。 
Fitz:简化和封装了PyMuPDF的功能,使在Python中处理PDF文件更加简单。 
 
安装: 
 
要使用Fitz,需要安装Fitz和PyMuPDF。如果未安装其中任何一个模块,可能会出现类似"ModuleNotFoundError:
No module named 'frontend'"的错误。 
可以使用pip进行安装,例如从清华镜像源安装PyMuPDF。 
 
总之,虽然PyMuPDF是一个全面的用于在Python中操作PDF文档的库,但Fitz是一个子模块,简化和封装了PyMuPDF的功能,使其更适合特定涉及PDF文件的任务,并且更易于使用。
PDF文档处理 
PyMuPDF模块的官方教程为:https://pymupdf.readthedocs.io/en/latest/tutorial.html
。
以下将会介绍如何使用fitz模块来获取PDF文档的基本信息、文本、图片、表格以及如何分割PDF文档。
本文所使用的PDF文档为:
demo1.pdf 
 
demo2.pdf 
 
获取PDF文档基本信息 
Python代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import  fitz"../data/demo1.pdf" open (pdf_path)"title" ]"author" ]"creationDate" ]0 )print (f"title: {title} \nauthor: {author} \ncreate_date: {create_date} \nnum_pages: {num_pages} \n" f"page_height: {page_height} \npage_width: {page_width} \n" )
输出结果为:
1 2 3 4 5 6 title : author : create_date : D:20240301052229 +00 '00 'num_pages : 1 page_height : 841 .9199829101562 page_width : 594 .9599609375 
获取文本 
Python代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 import  fitz"../data/demo1.pdf" open (pdf_path)for  page_index in  range (num_pages):print (f"第{page_index + 1 } 页的文本内容为:\n{text} \n" )
输出结果为:
1 2 3 4 5 6 7 第1 页的文本内容为:2024 /3/ 1  13 :22 //m d2pdf.netlify.app1 /1 1 st Match, 2024 .
获取图片 
获取PDF文档中的图片的Python代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import  fitz"../data/demo1.pdf" open (pdf_path)for  page_index in  range (num_pages):print (image_list)for  img in  image_list:0 ]print (pix.colorspace, '-->' , fitz.csRGB)f'../output/image{page_index + 1 } _{xref} .png' 
获取表格 
从demo2.pdf文档中提取表格数据的Python代码如下:
1 2 3 4 5 6 7 8 9 10 import  fitzopen ('../data/demo2.pdf' )0 ]   print (f"tables: {tables} " )for  i, table in  enumerate (tables):0 ].to_pandas()f'../output/table_pg_{1 } _{i + 1 } .csv' , index=False )
提取的表格数据将会保存为csv格式文件。
分割PDF 
处理book1.pdf文档(扫描版PDF文件),将其前三页分割形成新的PDF文档book_split.pdf,示例PDF代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import  fitzopen ("../data/book1.pdf" )f"../data/book_split.pdf" open ()0 , to_page=2 )
其中分割后PDF文档的第二页截图如下:
分割后PDF文档第二页截图 
 
PDF文档问答 
基于上述的PDF文档处理,我们将结合大模型(OpenAI)对PDF文档进行回答。
文字版PDF 
文字版PDF可使用fitz轻松获取PDF文档中的纯文字内容,再使用大模型进行问答(简化版RAG)。
示例Python代码如下(使用PDF文件为oppo_n3_flip.pdf):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import  osimport  fitzfrom  openai import  OpenAIdef  get_pdf_content (pdf_path: str  ) -> str :open (pdf_path)for  page_index in  range (num_pages):return  '' .join(bg_content_list)def  get_answer (pdf_content: str , query: str  ) -> str :"OPENAI_API_KEY" ))"gpt-3.5-turbo" ,"role" : "system" , "content" : "You are a helpful assistant." },"role" : "user" , "content" : f"The full text of PDF file is: {pdf_content} " },"role" : "user" , "content" : query}1000 0 ].message.contentreturn  answerif  __name__ == '__main__' :"../data/oppo_n3_flip.pdf" )"OPPO Find N3 Flip的价格?" print (get_answer(pdf_content=content, query=query1))"蚂蚁集团发布的大模型叫什么?" print (get_answer(pdf_content=content, query=query2))"混元大模型是什么时候发布的?" print (get_answer(pdf_content=content, query=query3))
输出结果如下:
1 2 3 OPPO  Find  N3  Flip 有两个版本可选,分别是12 GB + 256 GB 和12 GB + 512 GB 。起售价为6799 元人民币。"大图模型" (Large  Graph  Model ,简称LGM )。2023 年9 月7 日,在2023 腾讯全球数字生态大会上正式对外亮相的。
扫描版PDF 
而扫描版PDF(也称为影印版PDF)想要使用fitz来获取PDF中的文字内容是困难的,因此,需要先将每一页PDF转化为图片,再使用OCR技术获取图片中的文字,这样就能获取扫描版PDF中的文字,当然,获取文本的质量主要取决于PDF文档的质量及OCR识别效果。
可以使用fitz模块将每一页PDF转化为图片,同时,本文中采用PaddlePaddle的PaddleOCR模型进行文字识别。
示例的PDF文档为book_split.pdf,我们仅使用其中的第二页,Python代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 import  fitzfrom  PIL import  Imageimport  osimport  cv2import  jsonimport  base64import  requestsfrom  openai import  OpenAIdef  convert_pdf_2_img (pdf_file: str , pages: int  ) -> None :open (pdf_file)for  page_number in  range (pages):"RGB" , [pix.width, pix.height], pix.samples)f"../output/book1_{page_number + 1 } .png" )def  cv2_to_base64 (img ):'.jpg' , img)[1 ]return  base64.b64encode(data.tobytes()).decode('utf8' )def  image_ocr (image_path ):'images' : [cv2_to_base64(cv2.imread(image_path))]}"Content-type" : "application/json" }"http://localhost:50076/predict/ch_pp-ocrv3" if  r.json()["results" ]:return  "\n" .join([ocr_record["text" ].strip() for  ocr_record in  r.json()["results" ][0 ]["data" ]])else :return  "" def  get_answer (pdf_content: str , query: str  ) -> str :"OPENAI_API_KEY" ))"gpt-3.5-turbo" ,"role" : "system" , "content" : "You are a helpful assistant." },"role" : "user" , "content" : f"The full text of PDF file is: {pdf_content} " },"role" : "user" , "content" : query}1000 0 ].message.contentreturn  answerif  __name__ == '__main__' :"../data/book1.pdf" 2 )"../output/book1_2.png" )print (f"识别文字内容: {page1_ocr_result} " )"破浪理论的创始人是谁,他的出生年月?" print ("回答:" , predict_answer)"这本书的作者是谁?" print ("回答:" , predict_answer)
输出结果为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 识别文字内容: 作者简介 回答: 破浪理论的创始人是R.N.艾略特,他出生于1871年。 回答: 这本书的作者是 R.N.艾略特,他是波浪理论的创始人。 
可以看到,此时的回答效果是非常好的。
总结 
本文主要介绍了如何使用fitz模块来处理PDF文档,以及如何结合大模型对文字版、扫描版PDF文档进行智能回答。
本文的亮点之一在于可使用OCR技术获得扫描版PDF文本内容,在大模型加持下回答效果表现很好。
在后续的文章中,我们将会处理PDF文档中的多模态部分,比如表格、图片等,这将会是一项很有挑战性并且很有趣的事情。
本文给出的Python代码均已开源,可访问Github网址:https://github.com/percent4/pdf-llm_series 
.
欢迎关注我的公众号NLP奇幻之旅 ,原创技术文章第一时间推送。
 
欢迎关注我的知识星球“自然语言处理奇幻之旅 ”,笔者正在努力构建自己的技术社区。