成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MinerU部署實踐:從零開始搭建你的專屬PDF解析服務

人工智能
我將詳細介紹MinerU 的私有化部署流程、PDF 解析服務開發,以及如何通過 API 封裝實現便捷的文檔處理功能。

在多模態RAG(Retrieval-Augmented Generation)系統中,PDF文件的高效、安全解析與處理是實現高質量知識檢索和生成的關鍵環節。PDF文件通常包含豐富的文本、圖像和表格信息,這些多模態數據的有效提取和整合對于提升RAG系統的性能至關重要。然而,傳統的PDF解析工具往往存在解析精度不足、無法處理復雜格式(如圖像和表格)等問題,尤其是在涉及私密文檔時,數據安全和隱私保護也是一大挑戰。

今天,我將詳細介紹MinerU 的私有化部署流程、PDF 解析服務開發,以及如何通過 API 封裝實現便捷的文檔處理功能。

1、簡介

MinerU是一款將PDF轉化為機器可讀格式的工具(如markdown、json),可以很方便地抽取為任意格式。 主要具有以下功能:

  • 刪除頁眉、頁腳、腳注、頁碼等元素,確保語義連貫
  • 輸出符合人類閱讀順序的文本,適用于單欄、多欄及復雜排版
  • 保留原文檔的結構,包括標題、段落、列表等
  • 提取圖像、圖片描述、表格、表格標題及腳注
  • 自動識別并轉換文檔中的公式為LaTeX格式
  • 自動識別并轉換文檔中的表格為HTML格式
  • 自動檢測掃描版PDF和亂碼PDF,并啟用OCR功能
  • OCR支持84種語言的檢測與識別
  • 支持多種輸出格式,如多模態與NLP的Markdown、按閱讀順序排序的JSON、含有豐富信息的中間格式等
  • 支持多種可視化結果,包括layout可視化、span可視化等,便于高效確認輸出效果與質檢
  • 支持純CPU環境運行,并支持 GPU(CUDA)/NPU(CANN)/MPS 加速
  • 兼容Windows、Linux和Mac平臺

項目地址:https://github.com/opendatalab/MinerU

說明文檔:https://mineru.readthedocs.io/en/latest/index.html

2、私有化部署

MinerU官方提供的API,但是其API KEY需要14天要更換一次,并且在數據安全和隱私保護方面也很難控制。下面是對MinerU的私有化部署介紹:

安裝magic-pdf

conda create -n mineru pythnotallow=3.10 
conda activate mineru
pip install -U"magic-pdf[full]"-i https://mirrors.aliyun.com/pypi/simple

模型權重下載

方法一:從 Hugging Face 下載模型

使用python腳本 從Hugging Face下載模型文件

pip install huggingface_hub
wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models_hf.py -O download_models_hf.py
python download_models_hf.py

python腳本會自動下載模型文件并配置好配置文件中的模型目錄。也可以將MinerU代碼clone到本地,運行download_models_hf代碼

方法二:從 ModelScope 下載模型

pip install modelscope
wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models.py -O download_models.py
python download_models.py

也可以將MinerU代碼clone到本地,運行download_models代碼,可以通過配置一些參數,將模型下載到制定文件夾。

詳細參考如何下載模型文件。

修改配置文件以進行額外配置

完成下載模型權重文件步驟后,腳本會自動生成用戶目錄下的magic-pdf.json文件,并自動配置默認模型路徑。 可以在【用戶目錄】下找到magic-pdf.json文件。

windows的用戶目錄為 "C:\Users\用戶名", linux用戶目錄為 "/home/用戶名", macOS用戶目錄為 "/Users/用戶名"

可以修改該文件中的部分配置實現功能的開關,如表格識別功能:

如json內沒有如下項目,請手動添加需要的項目,并刪除注釋內容(標準json不支持注釋)

{
  // other config
  "layout-config": {
    "model": "doclayout_yolo"
  },
  "formula-config": {
    "mfd_model": "yolo_v8_mfd",
    "mfr_model": "unimernet_small",
    "enable": true // 公式識別功能默認是開啟的,如果需要關閉請修改此處的值為"false"
  },
  "table-config": {
    "model": "rapid_table",
    "sub_model": "slanet_plus",
    "enable": true, // 表格識別功能默認是開啟的,如果需要關閉請修改此處的值為"false"
    "max_time": 400
  }
}

3、解析代碼

process_pdf是核心解析函數,主要功能包括:

  • 自動識別PDF類型(普通文本PDF或掃描版PDF)
  • 提取文本內容和圖片資源
  • 生成Markdown格式的輸出
  • 可選生成可視化分析結果

參數

參數

類型

默認值

描述

pdf_file_name

str

要解析的PDF文件路徑

output_dir

str

"output"

輸出文件的主目錄

image_subdir

str

"images"

存放圖片的子目錄名稱

simple_output

bool

True

是否使用簡單輸出模式(True時只輸出Markdown和內容列表)

代碼

import os
from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader
from magic_pdf.data.dataset import PymuDocDataset
from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze
from magic_pdf.config.enums import SupportedPdfParseMethod




def process_pdf(pdf_file_name, output_dir="output", image_subdir="images", simple_output=True):
    """
    處理PDF文件,將其轉換為Markdown格式并保存相關資源
    :param pdf_file_name: PDF文件名
    :param output_dir: 輸出目錄,默認為'output'
    :param image_subdir: 圖片子目錄名,默認為'images'
    :param simple_output: 是否使用簡單輸出模式,默認為False
    """
    # 獲取不帶后綴的文件名
    name_without_suff = os.path.splitext(os.path.basename(pdf_file_name))[0]
    # 創建輸出子目錄名
    output_subdir = name_without_suff
    # 構建圖片目錄和markdown目錄的路徑
    local_image_dir = os.path.join(output_dir, output_subdir, image_subdir)
    local_md_dir = os.path.join(output_dir, output_subdir)
    # 創建必要的目錄
    os.makedirs(local_image_dir, exist_ok=True)
    os.makedirs(local_md_dir, exist_ok=True)
    # 創建文件寫入器
    image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter(local_md_dir)
    # 創建文件讀取器并讀取PDF文件
    reader1 = FileBasedDataReader("")
    pdf_bytes = reader1.read(pdf_file_name)
    # 創建數據集對象
    ds = PymuDocDataset(pdf_bytes)
    # 根據PDF類型選擇處理方式
    if ds.classify() == SupportedPdfParseMethod.OCR:
        # 使用OCR模式處理
        infer_result = ds.apply(doc_analyze, ocr=True)
        pipe_result = infer_result.pipe_ocr_mode(image_writer)
    else:
        # 使用文本模式處理
        infer_result = ds.apply(doc_analyze, ocr=False)
        pipe_result = infer_result.pipe_txt_mode(image_writer)
    # 構建markdown文件的完整路徑
    md_file_path = os.path.join(os.getcwd(), local_md_dir, f"{name_without_suff}.md")
    abs_md_file_path = os.path.abspath(md_file_path)
    if simple_output:
        # 簡單輸出模式:只輸出markdown和內容列表
        pipe_result.dump_md(md_writer, f"{name_without_suff}.md", os.path.basename(local_image_dir))
        pipe_result.dump_content_list(md_writer, f"{name_without_suff}_content_list.json",
                                      os.path.basename(local_image_dir))
        return abs_md_file_path
    else:
        # 完整輸出模式:輸出所有內容
        pipe_result.dump_md(md_writer, f"{name_without_suff}.md", os.path.basename(local_image_dir))
        pipe_result.dump_content_list(md_writer, f"{name_without_suff}_content_list.json",
                                      os.path.basename(local_image_dir))
    # 生成可視化文件
    infer_result.draw_model(os.path.join(local_md_dir, f"{name_without_suff}_model.pdf"))
    pipe_result.draw_layout(os.path.join(local_md_dir, f"{name_without_suff}_layout.pdf"))
    pipe_result.draw_span(os.path.join(local_md_dir, f"{name_without_suff}_spans.pdf"))
    return abs_md_file_path


if __name__ == "__main__":
    # 指定要處理的PDF文件名
    pdf_file_name = "/path/to/demo1.pdf"
    # 處理PDF文件并獲取生成的markdown文件路徑
    md_file_path = process_pdf(pdf_file_name, output_dir="/path/to/output", simple_output=False)
    # 打印生成的markdown文件路徑
    print(md_file_path)

輸出文件結構

output/
  ├── [PDF文件名]/
  │   ├── images/            # 存放提取的圖片
  │   ├── [PDF文件名].md     # 生成的Markdown文件
  │   ├── [PDF文件名]_content_list.json  # 內容列表JSON文件
  │   ├── [PDF文件名]_model.pdf   # 模型可視化結果(完整模式)
  │   ├── [PDF文件名]_layout.pdf  # 布局可視化結果(完整模式)
  │   └── [PDF文件名]_spans.pdf   # 文本塊可視化結果(完整模式)

4、API封裝

API 端點

  • URL:http://[host]:6601/process_pdf
  • 方法: POST
  • 內容類型: multipart/form-data

請求參數

參數:pdf_file

類型:文件

描述:要解析的PDF文件

響應

成功: 返回包含所有解析結果的ZIP文件

失敗: 返回JSON格式的錯誤信息

代碼

from flask import Flask, request, send_file, jsonify
import os
import shutil
import zipfile
from scripts.mineru_process_pdf import process_pdf
app = Flask(__name__)
def create_zip_from_directory(directory_path, zip_file_path):
    with zipfile.ZipFile(zip_file_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(directory_path):
            for file in files:
                file_path = os.path.join(root, file)
                arcname = os.path.relpath(file_path, directory_path)
                zipf.write(file_path, arcname)
@app.route('/process_pdf', methods=['POST'])
def process_pdf_api():
    if 'pdf_file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    file = request.files['pdf_file']
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400
    # Save the uploaded file to a temporary location
    input_pdf_path = os.path.join('temp', file.filename)
    os.makedirs('temp', exist_ok=True)
    file.save(input_pdf_path)
    try:
        # Process the PDF file
        output_dir = '/path/to/output'
        markdown_file_path = process_pdf(input_pdf_path, output_dir=output_dir, simple_output=False)
        # Create a zip file from the output directory
        temp_path = '/path/to/temp'
        os.makedirs(temp_path, exist_ok=True)
        zip_file_path = os.path.join(temp_path, f"{os.path.splitext(file.filename)[0]}.zip")
        create_zip_from_directory(os.path.join(output_dir, os.path.splitext(file.filename)[0]), zip_file_path)
        # Send the zip file as a response
        return send_file(zip_file_path, as_attachment=True)
    except Exception as e:
        return jsonify({'error': str(e)}), 500
    finally:
        # Clean up temporary files
        if os.path.exists(input_pdf_path):
            os.remove(input_pdf_path)
        if os.path.exists(zip_file_path):
            os.remove(zip_file_path)
        if os.path.exists(output_dir):
            shutil.rmtree(output_dir)
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=6601)

5、調用示例

下面對該解析服務API提供了三種調用示例,可以根據需要選擇使用:

代碼

import requests
import os
import zipfile
import io


def parse_pdf_api_to_path(pdf_file_path, output_dir):
    url = "http://localhost:6601/process_pdf"
    # 確保輸出目錄存在
    os.makedirs(output_dir, exist_ok=True)
    # 獲取 PDF 文件的基礎名稱(不帶擴展名)
    base_filename = os.path.splitext(os.path.basename(pdf_file_path))[0]
    with open(pdf_file_path, 'rb') as pdf_file:
        files = {'pdf_file': pdf_file}
        response = requests.post(url, files=files)
    if response.status_code == 200:
        # 保存返回的 zip 文件到指定目錄,使用與 PDF 相同的基礎文件名
        output_zip_path = os.path.join(output_dir, f'{base_filename}.zip')
        with open(output_zip_path, 'wb') as f:
            f.write(response.content)
        print(f"Test passed: Received zip file and saved to {output_zip_path}.")
    else:
        print(f"Test failed: {response.status_code} - {response.json()}")


def parse_pdf_api_to_content(pdf_file_path):
    url = "http://localhost:6601/process_pdf"
    # 獲取 PDF 文件的基礎名稱(不帶擴展名)
    base_filename = os.path.splitext(os.path.basename(pdf_file_path))[0]
    with open(pdf_file_path, 'rb') as pdf_file:
        files = {'pdf_file': pdf_file}
        response = requests.post(url, files=files)
    if response.status_code == 200:
        # 返回壓縮包內容
        print(f"Request successful: Received zip file for {base_filename}.")
        return response.content
    else:
        error_message = f"Request failed: {response.status_code} - {response.json()}"
        print(error_message)
        raise Exception(error_message)


def save_zip_content_to_directory(zip_content, output_dir):
    # 確保輸出目錄存在
    os.makedirs(output_dir, exist_ok=True)
    # 使用 zipfile 模塊解壓縮內容
    with zipfile.ZipFile(io.BytesIO(zip_content)) as z:
        z.extractall(output_dir)
    print(f"Files extracted to {output_dir}")


def save_zip_and_content_to_directory(zip_content, output_dir, zip_filename):
    # 確保輸出目錄存在
    os.makedirs(output_dir, exist_ok=True)
    # 保存壓縮包到指定目錄
    zip_path = os.path.join(output_dir, zip_filename)
    with open(zip_path, 'wb') as f:
        f.write(zip_content)
    print(f"Zip file saved to {zip_path}")
    # 使用 zipfile 模塊解壓縮內容
    with zipfile.ZipFile(io.BytesIO(zip_content)) as z:
        z.extractall(output_dir)
    print(f"Files extracted to {output_dir}")

直接解壓并保存到指定目錄

pdf_file_path = "/path/to/your.pdf"
output_unzip_dir = "/path/to/output/dir"
# 獲取壓縮包內容
zip_content = parse_pdf_api_to_content(pdf_file_path)
# 解壓并保存到指定目錄
save_zip_content_to_directory(zip_content, output_unzip_dir)

保存壓縮包到指定目錄并解壓

pdf_file_path = "/path/to/your.pdf"
output_unzip_dir = "/path/to/output/dir"
# 獲取壓縮包內容
zip_content = parse_pdf_api_to_content(pdf_file_path)
# 定義壓縮包文件名
zip_filename = os.path.splitext(os.path.basename(pdf_file_path))[0] + ".zip"
# 保存壓縮包并解壓
save_zip_and_content_to_directory(zip_content, output_unzip_dir, zip_filename)

將解析內容保存到本地

pdf_file_path = "/path/to/your.pdf"
output_dir = "/path/to/output/dir"
# 直接調用API并將結果保存到指定目錄
parse_pdf_api_to_path(pdf_file_path, output_dir)


責任編輯:龐桂玉 來源: 小白學AI算法
相關推薦

2024-05-15 14:29:45

2015-10-15 14:16:24

2017-09-13 14:01:51

數據庫MongoDB數據庫即服務

2022-09-01 10:46:02

前端組件庫

2016-11-02 14:09:13

搭建論壇Web服務器網關接口

2015-11-17 16:11:07

Code Review

2019-01-18 12:39:45

云計算PaaS公有云

2018-04-18 07:01:59

Docker容器虛擬機

2016-11-02 13:33:43

2024-12-06 17:02:26

2020-07-02 15:32:23

Kubernetes容器架構

2024-01-16 11:08:56

2016-11-02 14:18:45

搭建論壇Flask框架

2023-12-27 08:47:41

PrometheusLinux架構

2025-04-17 09:00:00

2016-10-19 08:36:51

2016-08-12 14:18:49

Javascriptnode命令行

2011-04-19 13:32:01

jQueryjavascript

2021-05-17 22:40:56

區塊鏈比特幣技術

2023-10-27 11:01:31

網絡性能VLAN
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久久91 | 成人毛片在线视频 | 国产成人精品综合 | 国产情品 | 伊色综合久久之综合久久 | 欧美在线一二三 | 久久精品99| 黄色毛片免费看 | 中文字幕福利 | 精品综合久久久 | 国产成人精品一区二区在线 | 国产亚洲一区二区三区 | 一级毛片视频 | 午夜大片| 欧美一区二区三区久久精品 | 久久婷婷av | 成人黄色av网站 | 午夜精品一区二区三区三上悠亚 | 午夜一区二区三区在线观看 | 色频| 国产精彩视频 | 日韩在线小视频 | 一级高清免费毛片 | 午夜影院 | 国产成人精品免费视频大全最热 | 日韩成人在线电影 | 拍拍无遮挡人做人爱视频免费观看 | 亚洲v区 | 黄色在线免费观看 | 国产丝袜一区二区三区免费视频 | 国产成人精品一区二区三区 | 久久一级免费视频 | 在线 丝袜 欧美 日韩 制服 | 又黄又爽的网站 | 久久久91精品国产一区二区三区 | 国产一级片精品 | 亚洲欧美精 | 韩日一区 | 伊人欧美视频 | 久久久九九 | 精品一区二区三区在线观看国产 |