YomiTokuをGPUコンテナサービスのDOKで実行する

[YomiToku](https://github.com/kotaro-kinoshita/yomitoku)は日本語に特化して学習したAI OCRです。Pythonパッケージとして公開されており、インストールすればCLIで簡単にOCR解析が可能です。APIもありますので、Pythonからの操作も可能です。

今回は、さくらインターネット社の提供するGPUクラウドサービスである[DOK](https://www.sakura.ad.jp/koukaryoku-dok/)でYomiTokuを利用する手順を紹介します。

## DOKについて

[DOK](https://www.sakura.ad.jp/koukaryoku-dok/)はさくらインターネットの提供するGPUクラウドサービスです。高機能なGPUを使って、コンテナを実行します。課金は秒単位となっており、GPU向けのFaaS（Function as a Service）として利用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009607/ac8e78c8-9484-48a3-8d1f-5d93c3f7f8e0.png)

## Dockerイメージの作成

DOK上で利用するDockerイメージを作成します。ベースになるのは、[公式リポジトリにあるdockerfile](https://github.com/kotaro-kinoshita/yomitoku/blob/main/dockerfile)です。このDockerfileを使えば、以下のようにコマンドを実行できます。

```bash
$ git clone https://github.com/kotaro-kinoshita/yomitoku.git
$ cd yomitoku
$ docker build -t yomitoku .
$ docker exec -it --rm --gpus all yomitoku \
  yomitoku -o /path/to/results -f md /path/to/dir
```

今回はこの実行方法を多少カスタマイズして、DOK上で動かします。具体的には、 docker-entrypoint.sh をコンテナ内にコピーし、そのファイルを実行します。

```dockerfile
WORKDIR /workspace

# ここから追記
COPY dockker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/dockker-entrypoint.sh
ENTRYPOINT ["/usr/local/bin/dockker-entrypoint.sh"]
```

### docker-entrypoint.shの作成

`docker-entrypoint.sh` は、Dockerコンテナが起動したときに実行されます。これを使って、YomiTokuを実行します。

```bash
#!/bin/bash

# この下に記述します
```

まず、DOKから渡される環境変数を取得します。

- SAKEURA_ARTIFACT_DIR  
アウトプット先ディレクトリ（自動付与） /opt/artifact固定です
- SAKEURA_TASK_ID  
DOKのタスクID（自動付与）

この2つの環境変数は必ず送られてきますが、ローカルで試用する際などを考えて、デフォルト値を設定しておきます。

```bash
# アウトプット先ディレクトリ（自動付与） /opt/artifact固定です
if [ -z "${SAKURA_ARTIFACT_DIR:-}" ]; then
  echo "Environment variable SAKURA_ARTIFACT_DIR is not set" >&2
  SAKURA_ARTIFACT_DIR=/opt/artifact
fi

# DOKのタスクID（自動付与）
if [ -z "${SAKURA_TASK_ID:-}" ]; then
  echo "Environment variable SAKURA_TASK_ID is not set" >&2
  SAKURA_TASK_ID=0
fi
```

そして、解析したい帳票は `URL` という環境変数で指定します。これは必須です。

```bash
# 解析対象のファイルのURL
if [ -z "${URL:-}" ]; then
  echo "Environment variable URL is not set" >&2
  exit 1
fi
```

ファイルは、wgetでダウンロードします。

```bash
filename=$(basename "$URL")
wget -O $SAKURA_ARTIFACT_DIR/$filename $URL
```

これで、 `/opt/artifact` にファイルがダウンロードされました。

さらに、出力フォーマットを複数指定できるようにします。何も指定しない場合には、 `json` のみです。

```bash
# 出力フォーマット。,区切りで複数指定可能
FORMATS=()
if [ -z "${FORMAT:-}" ]; then

  # デフォルト
  FORMATS=("json")
else
  # ,で分割
  IFS=',' read -ra FORMATS <<< "$FORMAT"
fi
```

これで、 `FORMATS` に出力フォーマットが格納されました。そして、フォーマット毎に `yomitoku` を実行します。

```bash
for format in "${FORMATS[@]}"; do
  echo "SAKURA_ARTIFACT_DIR: $SAKURA_ARTIFACT_DIR"
  echo "filename: $filename"
  echo "format: $format"
  yomitoku -o $SAKURA_ARTIFACT_DIR -f $format -v $SAKURA_ARTIFACT_DIR/$filename
done
```

これで、指定されたフォーマットで解析が実行されます。 `docker-entrypoint.sh` は以下のようになります。

```bash
#!/bin/bash

# アウトプット先ディレクトリ（自動付与） /opt/artifact固定です
if [ -z "${SAKURA_ARTIFACT_DIR:-}" ]; then
  echo "Environment variable SAKURA_ARTIFACT_DIR is not set" >&2
  SAKURA_ARTIFACT_DIR=/opt/artifact
fi

# DOKのタスクID（自動付与）
if [ -z "${SAKURA_TASK_ID:-}" ]; then
  echo "Environment variable SAKURA_TASK_ID is not set" >&2
  SAKURA_TASK_ID=0
fi

# 解析対象のファイルのURL
if [ -z "${URL:-}" ]; then
  echo "Environment variable URL is not set" >&2
  exit 1
fi

filename=$(basename "$URL")
wget -O $SAKURA_ARTIFACT_DIR/$filename $URL

# 出力フォーマット。,区切りで複数指定可能
FORMATS=()
if [ -z "${FORMAT:-}" ]; then
  # デフォルト
  FORMATS=("json")
else
  # ,で分割
  IFS=',' read -ra FORMATS <<< "$FORMAT"
fi

for format in "${FORMATS[@]}"; do
  echo "SAKURA_ARTIFACT_DIR: $SAKURA_ARTIFACT_DIR"
  echo "filename: $filename"
  echo "format: $format"
  yomitoku -o $SAKURA_ARTIFACT_DIR -f $format -v $SAKURA_ARTIFACT_DIR/$filename
done
```

### コンテナレジストリの準備

さくらインターネットでは、Dockerイメージを保存しておくコンテナレジストリを提供しています。これは無料で利用でき、さくらインターネットのネットワーク内に保存されるので、DOK実行時に便利です。

[さくらインターネットのGPUサービスDOKでVALL\-E X（音声読み上げAI）を試す \#Python \- Qiita](https://qiita.com/goofmint/items/dc3927d18cd3273213cc)を参考にしています。

#### コンテナレジストリの用意

さくらのクラウドにログインしたら `さくらのクラウド` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009607/d5ad9ae5-b72b-4c85-877e-ee7b18b490a1.png)

左側のメニューの `グローバル` の中にある `コンテナレジストリ` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009607/5a86ebd5-1594-4dca-9df0-dda22c9e3fc4.png)

`追加` を押して、コンテナレジストリを作成します。

| 項目                 | 設定                                                        |
| -------------------- | ----------------------------------------------------------- |
| 名前                 | 任意の名前                                                  |
| コンテナレジストリ名 | サブドメイン名として利用されます 例： `example.sakuracr.jp` |
| 公開設定             | Pullのみで指定してください                                  |

#### 利用ユーザーの作成

作成したコンテナレジストリを一覧でダブルクリックし、詳細表示にてユーザータブをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009607/bb2af8a6-7698-4926-b513-d16399bce408.png)

追加ボタンを押し、ユーザーを作成します。

| 項目           | 設定           |
| -------------- | -------------- |
| ユーザー名     | 任意のユーザー名 |
| パスワード     | 任意のパスワード  |
| ユーザ権限設定 | All            |

#### Dockerイメージのビルド

DockerイメージはLinuxで行います。今回はUbuntu 24.04を使っています。 `example.sakuracr.jp` の部分は、作成したコンテナレジストリのURLに読み替えてください。また、 `yomitoku` は任意の名前です。

```bash
sudo docker build -t example.sakuracr.jp/yomitoku:latest .
```

#### コンテナレジストリへのログイン

作成したコンテナレジストリにログインします。認証が求められるので、作成したものを入力してください。

```bash
sudo docker login example.sakuracr.jp
```

#### イメージのプッシュ

ビルドしたイメージをコンテナレジストリにプッシュします。

```bash
sudo docker push example.sakuracr.jp/yomitoku:latest
```

これで、コンテナレジストリにDockerイメージが保存され、DOKで実行する準備が整いました。

## DOKでの実行

DOKは、タスクという単位で処理内容を指定します。その際に、Dockerイメージとコマンド、環境変数を指定します。今回は、以下のように設定します。

- イメージ  
example.sakuracr.jp/yomitoku
- 環境変数  
以下のように設定します

| 変数名  | 値                                           |
| ------- | -------------------------------------------- |
| URL     | 解析したい帳票ファイルのURL                  |
| FORMART | 出力フォーマット。カンマ区切りで複数指定可能 |

解析したいファイルはURLで指定できれば、どこにあっても大丈夫です。たとえばさくらインターネットのオブジェクトストレージや、Amazon S3などが利用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009607/f946fbf2-53bd-4079-a529-4050fc108092.png)

実行中です。ログが流れていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009607/6f4cda9e-5126-4a23-9c2f-443b6907906a.png)

実行完了すると、「アーティファクト」という項目にダウンロードのリンクが表示されます。これは `/opt/artifact` に保存されたファイルを圧縮したもので、 `tar.gz` 形式でダウンロードできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009607/9aeb6b70-8c0a-4052-97a7-823d430929bc.png)


解凍すると、指定したフォーマットの解析結果ファイルと、レイアウトなどの画像ファイルがダウンロードできます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009607/de68904e-c8c8-4d30-95cb-380e4a7d176b.png)

たとえば、以下はMarkdown出力結果です。

![Markdown出力結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009607/72d1d1a3-71b0-4666-a91b-f5f8ee538cb9.png)

## ライセンス

YomiTokuのライセンスは[コモンズ証 \- 表示 \- 非営利 \- 継承 4\.0 国際 \- Creative Commons](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.ja)です。非商用での個人利用、研究目的においては、ご自由に利用できます。商用目的での利用に関しては、商用ライセンスが必要です。

## まとめ

今回は[DOK](https://www.sakura.ad.jp/koukaryoku-dok/)を使って、YomiTokuを実行しました。DOKはタスクベースなので、複数のタスクを立ち上げて並行処理させられます。また、URL上に圧縮ファイルを置いて、解凍してから一括実行と言った利用も考えられます。

DOKは秒単位で課金されるので、短時間で処理が終わるYomiTokuと相性が良さそうです。ぜひ参考にしてください。

[kotaro\-kinoshita/yomitoku: Yomitoku is an AI\-powered document image analysis package designed specifically for the Japanese language\.](https://github.com/kotaro-kinoshita/yomitoku)