end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

Document AIの chandra for python & docker で png画像を markdown化

先日のentry群に続き、Datalab社の chandraのお試し。

処理が重いことが示しているのでしょうか、 これまでに試した、yomitoku、mineruより精度がグッと向上した気がします

環境 - windows & wsl & docker

chandraの modelである datalab-to/chandra-ocr-2 は、huggingface(hf) または、vllm で動作しますが、hf でのocr処理が、余りに遅かった為、 wslや dockerも用意。

尚、wsl内にあるosは、OracleLinux_9_5で、このwslからeGPUである geforce rtc4090へ接続

C:\Users\end0t\tmp\CHANDRA>python3.12\Scripts\chandra.exe --help
Usage: chandra [OPTIONS] INPUT_PATH OUTPUT_PATH

Options:
  --method [hf|vllm]              Inference method: 'hf' for local model,
                                  'vllm' for vLLM server.
  --page-range TEXT               Page range for PDFs (e.g., '1-5,7,9-12').
                                  Only applicable to PDF files.
  --max-output-tokens INTEGER     Maximum number of output tokens per page.
  --max-workers INTEGER           Maximum number of parallel workers for vLLM
                                  inference.
  --max-retries INTEGER           Maximum number of retries for vLLM
                                  inference.
  --include-images / --no-images  Include images in output.
  --include-headers-footers / --no-headers-footers
                                  Include page headers and footers in output.
  --save-html / --no-html         Save HTML output files.
  --batch-size INTEGER            Number of pages to process in a batch.
  --paginate_output
  --help                          Show this message and exit.
C:\Users\end0t\tmp\CHANDRA>wsl --list
Linux 用 Windows サブシステム ディストリビューション:
OracleLinux_9_5 (既定値)

C:\Users\end0t\tmp\CHANDRA>wsl

[end0tknr@a64 CHANDRA]$ cat /etc/redhat-release
Red Hat Enterprise Linux release 9.5 (Plow)

install docker to wsl

docker for windowsも実は、wslに依存しているようですので、 wslへ インストール

sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo dnf -y install docker-ce docker-ce-cli containerd.io
sudo systemctl enable --now docker

install NVIDIA Container Toolkit to wsl

curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
sudo dnf -y install nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

install vllm to wsl docker

vLLM イメージのコンテナを一時的に起動し、その中で nvidia-smi だけを実行して、 コンテナからGPUが見えるか確認。

※この実行時に Docker イメージ vllm/vllm-openai:v0.17.0がダウンロードされますが、 「--rm」オプションがある為、終了後、削除されます

※ vllm/vllm-openai:v0.27.1 のように新しいdocker imageもありますが、 chandra側が vllm/vllm-openai:v0.17.0 を指定している為、これを利用

[end0tknr@a64 end0t]$ sudo docker run --rm --runtime=nvidia --gpus all --entrypoint nvidia-smi vllm/vllm-openai:v0.17.0

+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.102.01             Driver Version: 581.57         CUDA Version: 13.0     |
+-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce RTX 4090        On  |   00000000:22:00.0 Off |                  Off |
|  0%   47C    P8             28W /  450W |       0MiB /  24564MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|  No running processes found                                                             |
+-----------------------------------------------------------------------------------------+
引数 説明
--rm container終了時にcontainerを自動削除
--runtime=nvidia NVIDIA Container Toolkitをruntimeに使用
--gpus all hostの全GPUをcontainerに開示。1枚なら --gpus device=0 も可
--entrypoint nvidia-smi 元々のvllm serveでなく nvidia-smi を起動に利用
vllm/vllm-openai:v0.17.0 使うイメージ名とタグ(バージョン)

vLLM サーバ起動

初回起動時、 datalab-to/chandra-ocr-2 が huggingfaceから ダウンロードされます

sudo docker run --runtime nvidia --gpus device=0 \
  -v ~/.cache/huggingface:/root/.cache/huggingface \
  -p 8000:8000 --ipc=host \
  vllm/vllm-openai:v0.17.0 \
  --model datalab-to/chandra-ocr-2 \
  --no-enforce-eager \
  --max-num-seqs 16 \
  --dtype bfloat16 \
  --max-model-len 18000 \
  --max_num_batched_tokens 18000 \
  --gpu-memory-utilization .85 \
  --served-model-name chandra
引数 説明
--gpus device=0 nvidia-smiで表示された No.0のRTX4090をコンテナに割当て
-v ~/.cache/huggingface:/root/.cache/huggingface volume mount。host(WSL)の HuggingFace cacheを containerの /root/.cache/huggingface に共有
-p 8000:8000 port公開。左=ホスト側、右=コンテナ側
--ipc=host containerがhostのIPC空間(共有mem)使用。docker既定(64MB)ではpytorchに不足する為
--model datalab-to/chandra-ocr-2 Chandraのocr model本体。HuggingFaceの repo id
--no-enforce-eager CUDA graph / torch.compile 有効化。推論を高速化
--max-num-seqs 16 並列度の上限
--dtype bfloat16 modelの計算精度
--max-model-len 18000 1 reqで扱える最大token長
--max_num_batched_tokens 18000 1stepで処理するtokenの上限。max-model-lenと同値
--gpu-memory-utilization .85 GPU memの 85% をvLLMが使用。重み+KV cache用
--served-model-name chandra API公開するmodel名。VLLM_MODEL_NAME=chandraと一致

pip install chandra-ocr[hf]

python3.12\python.exe -m pip install chandra-ocr[hf]

python3.12\python.exe -m pip uninstall -y torch torchvision
python3.12\python.exe -m pip install torch torchvision --index-url https://download.pytorch.org/whl/cu124

python3.12\python.exe -c "import torch; print(torch.cuda.is_available(), torch.version.cuda, torch.cuda.get_device_name(0))"

config chandra

vi C:\Users\end0t\tmp\CHANDRA\python3.12\Lib\site-packages\chandra\settings.py

172.18.129.236とは、wsl側のip

from dotenv import find_dotenv
from pydantic_settings import BaseSettings
import os


class Settings(BaseSettings):
    # Paths
    BASE_DIR: str = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    IMAGE_DPI: int = 192
    MIN_PDF_IMAGE_DIM: int = 1024
    MIN_IMAGE_DIM: int = 1536
    MODEL_CHECKPOINT: str = "datalab-to/chandra-ocr-2"
    TORCH_DEVICE: str | None = None
    MAX_OUTPUT_TOKENS: int = 12384
    TORCH_ATTN: str | None = None
    BBOX_SCALE: int = 1000

    # vLLM server settings
    VLLM_API_KEY: str = "EMPTY"
    VLLM_API_BASE: str = "http://172.18.129.236:8000/v1"
    #VLLM_API_BASE: str = "http://localhost:8000/v1"
    VLLM_MODEL_NAME: str = "chandra"
    VLLM_GPUS: str = "0"
    MAX_VLLM_RETRIES: int = 6

    class Config:
        env_file = find_dotenv("local.env")
        extra = "ignore"


settings = Settings()

chandra実行

C:\Users\end0t\tmp\CHANDRA>python3.12\Scripts\chandra.exe ./input ./output --method vllm --include-images --no-html
Chandra CLI - Starting OCR processing
Input: input
Output: output
Method: vllm

Loading model with method 'vllm'...
Model loaded successfully.

Found 1 file(s) to process.

[1/1] Processing: 26A001-02-000_240.png
  Loaded 1 page(s)
  Processing pages 1-1...
  Saved: output\26A001-02-000_240\26A001-02-000_240.md (1 page(s))
  Completed: 26A001-02-000_240.png

Processing complete. Results saved to: output