PDF文档智能问答

在文本中,将会介绍如何使用fitz模块来处理PDF文档,并基于此,再使用大模型对PDF文档内容进行智能问答,提升问答效果。

技术逻辑

文字版PDF智能问答

  • fitz模块来处理PDF文档
  • 用大模型对PDF文档内容进行智能问答

扫描版PDF

  • 将PDF转化为图片
  • PaddleOCR模型进行文字识别
  • 用大模型对PDF文档内容进行智能问答

PDF文档处理

请参考:https://blog.csdn.net/zhanghan11366/article/details/137471811?spm=1001.2014.3001.5502(中的PDF部分)

基于上述的PDF文档处理,我们将结合大模型(OpenAI)对PDF文档进行回答。

文字版PDF

文字版PDF可使用fitz轻松获取PDF文档中的纯文字内容,再使用大模型进行问答(简化版RAG)。

示例Python代码如下:

复制代码
# -*- coding: utf-8 -*-

import os
import openai
import fitz

###设置代理,本地vpn
os.environ["http_proxy"] = "http://127.0.0.1:7890"
os.environ["https_proxy"] = "http://127.0.0.1:7890"

openai.api_key = "api key" 


def get_pdf_content(pdf_path: str) -> str:
    doc = fitz.open(pdf_path)
    num_pages = doc.page_count
    text_content_list = []
    # 读取PDF的全部文本内容
    for page_index in range(num_pages):
        page = doc.load_page(page_index)
        text = page.get_text()
        text_content_list.append(text)

    # 合并全部页面的文本
    return ''.join(text_content_list)

def get_answer(pdf_content: str, query: str) -> str:
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"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}
        ],
        max_tokens=1000
    )
    answer = response['choices'][0]['message']['content']
    return answer

if __name__ == '__main__':
    # Example usage --- make sure to update the PDF path
    pdf_content = get_pdf_content("../data/oppo_n3_flip.pdf")
    queries = [
        "OPPO Find N3 Flip的价格?",
        "蚂蚁集团发布的大模型叫什么?",
        "混元大模型是什么时候发布的?"
    ]

    # 打印所有问题的答案
    for query in queries:
        answer=get_answer(pdf_content=pdf_content, query=query)
        print(f"query:{query},\n RAG answer:{answer}")

结果如下:

扫描版PDF

而扫描版PDF(也称为影印版PDF)想要使用fitz来获取PDF中的文字内容是困难的,因此,需要先将每一页PDF转化为图片,再使用OCR技术获取图片中的文字,这样就能获取扫描版PDF中的文字,当然,获取文本的质量主要取决于PDF文档的质量及OCR识别效果。

可以使用fitz模块将每一页PDF转化为图片,同时,本文中采用PaddlePaddle的PaddleOCR模型进行文字识别。

运行paddleOCR

复制代码
hub serving start -m ch_pp-ocrv3

PDF转化为图片

复制代码
def convert_pdf_2_img(pdf_file: str, pages: int) -> None:
    pdf_document = fitz.open(pdf_file)

    # Iterate through each page and convert to an image
    for page_number in range(pages):
        # Get the page
        page = pdf_document[page_number]
        # Convert the page to an image
        pix = page.get_pixmap()
        # Create a Pillow Image object from the pixmap
        image = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
        # Save the image
        image.save(f"../output/book1_{page_number + 1}.png")

    # Close the PDF file
    pdf_document.close()

完整代码

复制代码
# -*- coding: utf-8 -*-
import fitz
from PIL import Image
import cv2
import json
import base64
import requests
from openai import OpenAI
import httpx
from pprint import pprint

client = OpenAI(
    base_url="https://api.xty.app/v1",
    api_key="api_key ",
    http_client=httpx.Client(
        base_url="https://api.xty.app/v1",
        follow_redirects=True,
    ),
)


def convert_pdf_2_img(pdf_file: str, pages: int) -> None:
    pdf_document = fitz.open(pdf_file)

    # Iterate through each page and convert to an image
    for page_number in range(pages):
        # Get the page
        page = pdf_document[page_number]
        # Convert the page to an image
        pix = page.get_pixmap()
        # Create a Pillow Image object from the pixmap
        image = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
        # Save the image
        image.save(f"../output/book1_{page_number + 1}.png")

    # Close the PDF file
    pdf_document.close()


def cv2_to_base64(image):
    data = cv2.imencode('.jpg', image)[1]
    return base64.b64encode(data.tobytes()).decode('utf8')


def image_ocr(image_path):
    data = {'images': [cv2_to_base64(cv2.imread(image_path))]}
    headers = {"Content-type": "application/json"}
    url = "http://0.0.0.0:8866/predict/ch_pp-ocrv3"
    r = requests.post(url=url, headers=headers, data=json.dumps(data))
    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:
    response = client.chat.completions.create(
        model="gpt-4-vision-preview",
        messages=[
            {"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}
        ],
        max_tokens=1000
    )
    content = response.choices[0].message.content
    return content


if __name__ == '__main__':
    test_pdf_file = "../data/book1.pdf"
    convert_pdf_2_img(pdf_file=test_pdf_file, pages=2)
    page1_ocr_result = image_ocr("../output/book1_2.png")
    print(f"识别文字内容: {page1_ocr_result}")

    query1 = "破浪理论的创始人是谁,他的出生年月?"
    predict_answer = get_answer(pdf_content=page1_ocr_result, query=query1)
    print("回答:", predict_answer)

    query2 = "这本书的作者是谁?"
    predict_answer = get_answer(pdf_content=page1_ocr_result, query=query2)
    print("回答:", predict_answer)

结果如下:

相关推荐
Java面试题总结21 小时前
基于 Java 的 PDF 文本水印实现方案(iText7 示例)
java·python·pdf
傻啦嘿哟1 天前
Python操作PDF页面详解:删除指定页的完整方案
开发语言·python·pdf
m5655bj1 天前
使用 C# 修改 PDF 页面尺寸
java·pdf·c#
geovindu1 天前
python: 简单提取PDF文档内文字
开发语言·python·pdf
m0_694845571 天前
HandBrake 是什么?视频转码工具使用与服务器部署教程
服务器·前端·pdf·开源·github·音视频
yivifu2 天前
使用PyMuPdf删除PDF文档中的水印
pdf·pymupdf·去水印
ComPDFKit2 天前
ComPDF的产品升级:从工具包到PDF服务
pdf
占疏2 天前
pdf文件解析
pdf
开开心心_Every2 天前
音频视频转文字工具,离线语音识别免费
人工智能·游戏·微信·pdf·excel·语音识别·memcache
开开心心_Every2 天前
电脑网速加速工具,无线有线叠加网络
网络·游戏·微信·pdf·电脑·excel·语音识别