Skip to content

Commit 3ed450c

Browse files
authored
Merge pull request #19 from artiz/fix/tableformer-silent-fallback
fix(ci,scripts): fix publish-models.yml export/staging + download_dependencies.sh sidecar gap
2 parents 6afeec2 + 8952e78 commit 3ed450c

6 files changed

Lines changed: 90 additions & 31 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
name: fmt · clippy (pinned)
3434
runs-on: ubuntu-latest
3535
steps:
36-
- uses: actions/checkout@v5
36+
- uses: actions/checkout@v7
3737

3838
- uses: dtolnay/rust-toolchain@master
3939
with:
@@ -52,7 +52,7 @@ jobs:
5252
name: test (stable)
5353
runs-on: ubuntu-latest
5454
steps:
55-
- uses: actions/checkout@v5
55+
- uses: actions/checkout@v7
5656

5757
# Tests stay on the current stable so they catch real compiler breakage.
5858
- uses: dtolnay/rust-toolchain@stable
@@ -75,7 +75,7 @@ jobs:
7575
permissions:
7676
contents: write # push the version-bump commit + tag
7777
steps:
78-
- uses: actions/checkout@v5
78+
- uses: actions/checkout@v7
7979
with:
8080
fetch-depth: 0 # full history + tags, for the semantic version bump
8181
# Push the release commit + tag as an admin PAT so it satisfies the

.github/workflows/npm-publish.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
- target: x86_64-pc-windows-msvc
6262
host: windows-latest
6363
steps:
64-
- uses: actions/checkout@v5
64+
- uses: actions/checkout@v7
6565
with:
6666
ref: ${{ inputs.tag || github.ref }}
6767

@@ -75,7 +75,7 @@ jobs:
7575
key: ${{ matrix.target }}
7676
workspaces: "."
7777

78-
- uses: actions/setup-node@v5
78+
- uses: actions/setup-node@v6
7979
with:
8080
node-version: 20
8181

@@ -94,7 +94,7 @@ jobs:
9494
run: npx napi build --platform --release --target ${{ matrix.target }} --js native.js --dts native.d.ts
9595

9696
- name: Upload prebuilt binary
97-
uses: actions/upload-artifact@v5
97+
uses: actions/upload-artifact@v7
9898
with:
9999
name: bindings-${{ matrix.target }}
100100
path: crates/fleischwolf-node/fleischwolf.*.node
@@ -104,7 +104,7 @@ jobs:
104104
# linux-x64 build) for the publish job to include in the main package.
105105
- name: Upload JS binding
106106
if: matrix.target == 'x86_64-unknown-linux-gnu'
107-
uses: actions/upload-artifact@v5
107+
uses: actions/upload-artifact@v7
108108
with:
109109
name: js-binding
110110
path: |
@@ -117,11 +117,11 @@ jobs:
117117
needs: build
118118
runs-on: ubuntu-latest
119119
steps:
120-
- uses: actions/checkout@v5
120+
- uses: actions/checkout@v7
121121
with:
122122
ref: ${{ inputs.tag || github.ref }}
123123

124-
- uses: actions/setup-node@v5
124+
- uses: actions/setup-node@v6
125125
with:
126126
node-version: 20
127127
registry-url: "https://registry.npmjs.org"
@@ -131,14 +131,14 @@ jobs:
131131

132132
# Prebuilt binaries → artifacts/<name>/fleischwolf.<triple>.node
133133
- name: Download prebuilt binaries
134-
uses: actions/download-artifact@v5
134+
uses: actions/download-artifact@v8
135135
with:
136136
pattern: bindings-*
137137
path: crates/fleischwolf-node/artifacts
138138

139139
# The JS loader + types → the package root.
140140
- name: Download JS binding
141-
uses: actions/download-artifact@v5
141+
uses: actions/download-artifact@v8
142142
with:
143143
name: js-binding
144144
path: crates/fleischwolf-node

.github/workflows/publish-models.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ jobs:
4040
GH_TOKEN: ${{ github.token }}
4141
TAG: ${{ inputs.tag }}
4242
steps:
43-
- uses: actions/checkout@v5
43+
- uses: actions/checkout@v7
4444

45-
- uses: actions/setup-python@v5
45+
- uses: actions/setup-python@v6
4646
with:
4747
python-version: "3.11"
4848

@@ -57,7 +57,7 @@ jobs:
5757
- name: Install TableFormer export deps
5858
continue-on-error: true
5959
id: tf-deps
60-
run: pip install docling_ibm_models onnxscript onnxruntime huggingface_hub
60+
run: pip install docling_ibm_models onnxscript onnxruntime huggingface_hub opencv-python-headless
6161

6262
- name: Export TableFormer
6363
if: steps.tf-deps.outcome == 'success'
@@ -90,8 +90,8 @@ jobs:
9090
run: |
9191
mkdir -p release-assets
9292
stage() { # <source-path> <asset-name>
93-
[ -f "$1" ] && cp "$1" "release-assets/$2"
94-
[ -f "$1.data" ] && cp "$1.data" "release-assets/$2.data"
93+
if [ -f "$1" ]; then cp "$1" "release-assets/$2"; fi
94+
if [ -f "$1.data" ]; then cp "$1.data" "release-assets/$2.data"; fi
9595
}
9696
stage third-party/lib/libpdfium.so libpdfium.so
9797
stage third-party/ocr_rec.onnx ocr_rec.onnx

README.md

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -192,16 +192,8 @@ const json = await convertFileAsync('report.docx', { to: 'json' })
192192

193193
Declarative formats (Markdown, HTML, DOCX, XLSX, …) work out of the box. The
194194
PDF/image pipeline needs pdfium + the ONNX models (not bundled), so it throws
195-
until you fetch them — a one-liner from your app's directory (pdfium and OCR
196-
from their own upstream releases; the layout model and TableFormer —
197-
PyTorch→ONNX exports of docling-project's own models,
198-
Apache-2.0/CDLA-Permissive-2.0, see [`MODELS_NOTICE.md`](./MODELS_NOTICE.md)
199-
from fleischwolf's own hosted release), straight into `./models` and
200-
`./.pdfium`, which the package looks for by default — no env vars needed:
201-
202-
```bash
203-
curl -fsSL https://raw.githubusercontent.com/artiz/fleischwolf/master/scripts/download_dependencies.sh | sh
204-
```
195+
until you fetch them with `scripts/download_dependencies.sh` — see
196+
[Getting the ML models](#getting-the-ml-models) below.
205197

206198
A reusable `Pipeline` keeps those models warm across many PDFs.
207199

@@ -211,6 +203,68 @@ Runnable Node + Bun examples are in
211203
[`crates/fleischwolf-node/README.md`](./crates/fleischwolf-node/README.md) for
212204
the full API.
213205

206+
## Getting the ML models
207+
208+
The PDF/image pipeline needs native assets that aren't bundled in the crate or
209+
the npm addon: [pdfium](https://pdfium.googlesource.com/pdfium/) (text
210+
extraction + page rendering) and three ONNX models — RT-DETR layout, PP-OCRv3
211+
recognition, and TableFormer (optional; tables fall back to geometric
212+
reconstruction without it). `scripts/download_dependencies.sh` fetches all of
213+
them from this repo's [GitHub Releases](https://github.com/artiz/fleischwolf/releases)
214+
(tag `models-v1`) straight into `./models` and `./.pdfium`, relative to the
215+
current directory — both the Rust CLI/library and the Node.js/Bun bindings
216+
look there by default, so no env vars or extra setup are needed afterwards:
217+
218+
```bash
219+
# from a checkout of this repo, or any directory you'll run fleischwolf from:
220+
scripts/download_dependencies.sh
221+
222+
# or, without a checkout — e.g. a container build step, or a fresh npm project:
223+
curl -fsSL https://raw.githubusercontent.com/artiz/fleischwolf/master/scripts/download_dependencies.sh | sh
224+
```
225+
226+
| Asset | Destination |
227+
| --- | --- |
228+
| pdfium (Linux x64) | `.pdfium/lib/libpdfium.so` |
229+
| RT-DETR layout | `models/layout_heron.onnx` |
230+
| PP-OCRv3 rec + dictionary | `models/ocr_rec.onnx`, `models/ppocr_keys_v1.txt` |
231+
| TableFormer (optional) | `models/tableformer/{encoder,decoder,bbox}.onnx` (+ `.data` sidecars where the export needs them) |
232+
233+
Idempotent — safe to re-run; it skips files already on disk. Pass `--force` to
234+
re-fetch everything, or set `$FLEISCHWOLF_MODELS_URL` to fetch from a
235+
different host (your own export, an internal mirror, …). pdfium is Linux x64
236+
only for now — other platforms, or building the models from source, need
237+
[`scripts/pdf_setup.sh`](#testing) instead.
238+
239+
Then either:
240+
241+
```bash
242+
cargo run -p fleischwolf-cli -- document.pdf
243+
```
244+
245+
or, in a Node.js/Bun app:
246+
247+
```bash
248+
npm i fleischwolf
249+
```
250+
251+
```js
252+
import { convertFileAsync } from 'fleischwolf'
253+
const { content } = await convertFileAsync('document.pdf', { to: 'markdown' })
254+
console.log(content)
255+
```
256+
257+
The layout model and TableFormer are PyTorch→ONNX exports of docling-project's
258+
own models (Apache-2.0 / CDLA-Permissive-2.0 — see
259+
[`MODELS_NOTICE.md`](./MODELS_NOTICE.md) for full attribution); pdfium and the
260+
OCR model are re-hosted, unmodified, from their own public releases — all on
261+
one host for convenience.
262+
263+
To point at files you exported or placed elsewhere instead, set the env vars
264+
directly: `DOCLING_LAYOUT_ONNX`, `DOCLING_OCR_REC_ONNX`, `DOCLING_OCR_DICT`,
265+
`DOCLING_TABLEFORMER_{ENCODER,DECODER,BBOX}`, `PDFIUM_DYNAMIC_LIB_PATH` — an
266+
env var always wins over the `./models` / `./.pdfium` default.
267+
214268
## Testing
215269

216270
All commands run from the `fleischwolf/` workspace root.
@@ -268,8 +322,7 @@ cargo run -p fleischwolf-cli -- --strict crates/fleischwolf/sample.html
268322
cargo run -p fleischwolf-cli -- --to json crates/fleischwolf/sample.html
269323
cargo run -p fleischwolf-cli -- --to json crates/fleischwolf/sample.html > out.json
270324

271-
# PDF/image conversion needs the ML models: scripts/download_dependencies.sh once,
272-
# then it just works — models/ and .pdfium/lib are picked up automatically.
325+
# PDF/image conversion needs the ML models — see "Getting the ML models" above.
273326
scripts/download_dependencies.sh
274327
cargo run -p fleischwolf-cli -- document.pdf
275328

scripts/download_dependencies.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
# models/layout_heron.onnx
2424
# models/ocr_rec.onnx
2525
# models/ppocr_keys_v1.txt
26-
# models/tableformer/encoder.onnx
27-
# models/tableformer/decoder.onnx (+ decoder.onnx.data, if the export needs it)
28-
# models/tableformer/bbox.onnx
26+
# models/tableformer/encoder.onnx (+ .data, if the export needs it)
27+
# models/tableformer/decoder.onnx (+ .data, if the export needs it)
28+
# models/tableformer/bbox.onnx (+ .data, if the export needs it)
2929
#
3030
# pdfium is Linux x64 only for now, matching what's hosted in the release; for
3131
# other platforms (or to build the models from source) see scripts/pdf_setup.sh.
@@ -81,8 +81,10 @@ fetch "$BASE_URL/layout_heron.onnx" models/layout_heron.onnx
8181
fetch "$BASE_URL/ocr_rec.onnx" models/ocr_rec.onnx
8282
fetch "$BASE_URL/ppocr_keys_v1.txt" models/ppocr_keys_v1.txt
8383
fetch "$BASE_URL/encoder.onnx" models/tableformer/encoder.onnx
84+
fetch_optional "$BASE_URL/encoder.onnx.data" models/tableformer/encoder.onnx.data
8485
fetch "$BASE_URL/decoder.onnx" models/tableformer/decoder.onnx
8586
fetch_optional "$BASE_URL/decoder.onnx.data" models/tableformer/decoder.onnx.data
8687
fetch "$BASE_URL/bbox.onnx" models/tableformer/bbox.onnx
88+
fetch_optional "$BASE_URL/bbox.onnx.data" models/tableformer/bbox.onnx.data
8789

8890
echo "done — models/ and .pdfium/lib populated in $(pwd)"

scripts/export_layout.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
python scripts/export_layout.py models/layout_heron.onnx
99
"""
1010

11+
import os
1112
import sys
1213

1314
import torch
@@ -30,6 +31,9 @@ def forward(self, pixel_values):
3031

3132
def main() -> None:
3233
out = sys.argv[1] if len(sys.argv) > 1 else "models/layout_heron.onnx"
34+
out_dir = os.path.dirname(out)
35+
if out_dir:
36+
os.makedirs(out_dir, exist_ok=True)
3337
print(f"loading {REPO} ...", flush=True)
3438
model = RTDetrV2ForObjectDetection.from_pretrained(
3539
REPO, torch_dtype=torch.float32

0 commit comments

Comments
 (0)