OCRFlux

repository·main·Indexed 25 days ago

https://github.com/chatdoc-com/ocrflux

A multimodal large language model toolkit designed to convert PDFs and images into high-quality Markdown. OCRFlux specializes in preserving natural reading order, complex tables, and equations, featuring native support for cross-page table and paragraph merging. It provides a pipeline for batch inference via CLI, offline inference using vLLM, and an online server deployment option. The toolkit includes utilities for page-to-markdown conversion, element merge detection, and HTML table merging.

Tokens
6.1K
Snippets
5
Records
37
Agent score
82%

What's inside ocrflux

  1. Reusable code components in OCRFlux

    main

    OCRFlux provides several reusable scripts for high-scale document processing, inference, and evaluation. You can leverage these components for your own projects:

    • Large-scale Processing: Use pipeline.py to process millions of PDFs using the released model via VLLM.
    • Data Conversion: Use jsonl_to_markdown.py to generate final Markdown files from .jsonl data files.
    • Inference:
      • inferencer.py for running offline inference using VLLM.
      • server.sh to launch a VLLM server.
      • client.py for running online inference using VLLM.
    • Evaluation:
      • eval_page_to_markdown.py: Evaluates single-page parsing.
      • eval_table_to_html.py: Evaluates table parsing.
      • eval_element_merge_detect.py: Evaluates detection of paragraph/table merging.
      • eval_html_table_merge.py: Evaluates table merging tasks.
  2. Install OCRFlux

    main

    OCRFlux requires a recent NVIDIA GPU with at least 12 GB of VRAM and 20GB of free disk space. It is highly recommended to use a clean Conda environment due to complex dependencies.

    1. Install System Dependencies (Ubuntu/Debian): Install poppler-utils and necessary fonts for PDF rendering.

    2. Setup Python Environment: Create a Python 3.11 environment and install the package in editable mode.

    3. Install FlashInfer: Use the provided --find-links to ensure compatibility with your CUDA/PyTorch setup.

    # Install system dependencies
    sudo apt-get update
    sudo apt-get install poppler-utils poppler-data ttf-mscorefonts-installer msttcorefonts fonts-crosextra-caladea fonts-crosextra-carlito gsfonts lcdf-typetools
    
    # Setup Conda environment
    conda create -n ocrflux python=3.11
    conda activate ocrflux
    
    git clone https://github.com/chatdoc-com/OCRFlux.git
    cd OCRFlux
    
    pip install -e . --find-links https://flashinfer.ai/whl/cu124/torch2.5/flashinfer/
  3. Convert Pipeline JSONL results to Markdown

    main

    After running the pipeline, the results are stored in JSONL format. To generate the final human-readable Markdown files, run the ocrflux.jsonl_to_markdown module pointing to your workspace.

    python -m ocrflux.jsonl_to_markdown ./localworkspace
  4. Deploy OCRFlux as an Online Server

    main

    You can deploy OCRFlux as a server using the provided shell script, which starts a vLLM server. Once running, you can use the ocrflux.client.request function to interact with it asynchronously.

    # Start the server
    bash ocrflux/server.sh ChatDOC/OCRFlux-3B 30024
    import asyncio
    from argparse import Namespace
    from ocrflux.client import request
    
    args = Namespace(
        model="/path/to/OCRFlux-3B",
        skip_cross_page_merge=False,
        max_page_retries=1,
        url="http://localhost",
        port=30024,
    )
    
    file_path = 'test.pdf'
    result = asyncio.run(request(args, file_path))
    if result != None:
        document_markdown = result['document_text']
        print(document_markdown)
  5. How the OCRFlux pipeline orchestrates inference

    main

    OCRFlux uses a producer-consumer model to process large volumes of documents efficiently:

    1. Work Queue Initialization: Files are grouped into 'work items' (aiming for pages_per_group) and placed in a LocalWorkQueue within the workspace.
    2. vLLM Server Management: The pipeline automatically starts a vllm serve subprocess. It monitors the server logs to detect readiness and handles automatic restarts if the server encounters specific errors (like IndexError in the model).
    3. Worker Concurrency: Multiple worker tasks consume items from the queue. A Semaphore(1) is used to throttle requests; it ensures that while many workers are active, they only saturate the GPU when the vLLM request queue is empty, preventing deadlocks and ensuring steady throughput.
    4. Task Lifecycle:
      • PDF to Markdown: Renders pages as images $\rightarrow$ sends to vLLM $\rightarrow$ parses PageResponse $\rightarrow$ converts tables to HTML.
      • Merging: After initial parsing, the pipeline performs cross-page detection (element_merge_detect) and table merging (html_table_merge) to ensure continuity across page breaks.
  6. How the OCR pipeline stages work

    main

    The OCRFlux client operates in a multi-stage pipeline to ensure high-fidelity document reconstruction:

    1. Stage 1: Page to Markdown: Each page is sent to the model to generate a PageResponse. This includes natural_text which is parsed into a list of markdown elements. Tables are converted from a custom matrix format to HTML using table_matrix2html.

    2. Stage 2: Element Merge Detect: The client compares adjacent pages. It sends pairs of text lists to the model to detect if elements at the end of page $N$ and the start of page $N+1$ should be merged.

    3. Stage 3: HTML Table Merge: If the merge detection identifies that two adjacent elements are both HTML tables (<table ...> ... </table>), a specific merge task is triggered to combine them into a single valid HTML table.

    Finally, build_document_text aggregates all processed and merged elements into a single continuous string.

  7. Understand the error handling and retry logic

    main

    The pipeline implements two distinct layers of retries to ensure robustness during massive batch jobs:

    1. Model/Content Retries (max_page_retries): If a model produces invalid JSON or poor quality results, the process_task function retries the specific page. It uses an increasing temperature strategy (TEMPERATURE_BY_ATTEMPT = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]) to help the model overcome repetitive generation issues.
    2. Server/Connection Retries: If a ConnectionError or OSError occurs (e.g., the vLLM server is restarting), the worker performs an exponential backoff (10 * (2**exponential_backoffs)) to allow the server to recover without failing the entire document.
    3. Document Discarding: If the number of failed pages exceeds --max_page_error_rate, the entire document is discarded to prevent corrupt data from entering the final dataset.
  8. Run the OCRFlux pipeline via CLI

    main

    The OCRFlux pipeline is managed through a command-line interface that supports three primary tasks: converting PDFs to Markdown, merging text elements across pages, and merging HTML tables. The pipeline orchestrates a vLLM server to perform batch inference on documents.

    Available Tasks:

    • pdf2markdown: Converts PDF or image files into structured Markdown text.
    • merge_pages: Uses JSON input to detect and merge text elements across page boundaries.
    • merge_tables: Uses JSON input to merge HTML tables across page boundaries.

    Basic Usage Pattern:

    python -m ocrflux.pipeline <workspace_path> --task <task_name> --data <file_paths>
  9. Use OCRFlux for Offline Inference

    main

    You can integrate OCRFlux directly into your Python code using the ocrflux.inference.parse function without running a separate vLLM server. This requires initializing a vllm.LLM instance first.

    If parsing fails or certain pages are skipped, use the max_page_retries argument in parse() to improve results at the cost of higher inference time.

    from vllm import LLM
    from ocrflux.inference import parse
    
    file_path = 'test.pdf'
    # Initialize vLLM
    llm = LLM(model="model_dir/OCRFlux-3B", gpu_memory_utilization=0.8, max_model_len=8192)
    
    # Perform parsing
    result = parse(llm, file_path)
    if result != None:
        document_markdown = result['document_text']
        print(document_markdown)
        with open('test.md', 'w') as f:
            f.write(document_markdown)
    else:
        print("Parse failed.")
  10. Configure OCRFlux request arguments

    main

    When calling request, you must provide an args object (typically a Namespace) with the following configuration keys:

    KeyTypeDescription
    modelstrThe name of the model to use (e.g., ChatDOC/OCRFlux-3B).
    urlstrThe base URL of the OCR service.
    portintThe port of the OCR service.
    max_page_retriesintNumber of times to retry a failed task (used in process_task).
    skip_cross_page_mergeboolIf True, skips the cross-page element and table merging stages.
  11. Reference: OCRFlux Pipeline CLI Arguments

    main

    The ocrflux.pipeline module accepts the following arguments for batch processing:

    ArgumentDescription
    workspace (pos)Filesystem path where work is stored
    --taskTask name: pdf2markdown, merge_pages, or merge_tables
    --dataList of paths to files to process
    --max_page_retriesNumber of times to retry rendering a page
    --gpu_memory_utilizationFraction of GPU memory to use (default: 0.8)
    --tensor_parallel_sizeNumber of tensor parallel replicas
    --dtypeData type: auto, half, float16, float, bfloat16, float32
    --skip_cross_page_mergeWhether to skip cross-page merging
    --modelPath to the model
  12. Reference: Pipeline Output JSONL Schema

    main

    Each line in the JSONL files generated by the pipeline is a JSON object with the following structure:

    {
        "orig_path": "str",  // path to the raw file
        "num_pages": "int",  // number of pages
        "document_text": "str", // full Markdown text
        "page_texts": {"int": "str"}, // key: page index, value: page Markdown
        "fallback_pages": ["int"], // indexes of failed pages
    }