refactor: solidify startup UX and engine-aware preprocessing

- Slim core deps: move ML stack to optional extras (paddle/tables/figures/scientific/full)
- Lazy settings proxy with config search paths (env var, cwd, user dir)
- New commands: init, demo, setup [basic|full], first-run guard on run/watch
- Engine-aware preprocessing: Paddle gets original image (fixes dark mode 0.83->0.95)
- Results table shows Skipped count; lazy run-dir creation
- kg_ocr marked experimental with extra, Docker defaults with OCR_PIPELINE_CONFIG
- 25/25 tests, ruff clean
This commit is contained in:
2026-07-19 22:14:54 +02:00
parent deab02610b
commit a0211155fa
59 changed files with 2426 additions and 629 deletions

View File

@@ -11,61 +11,76 @@ Turns scientific screenshots into RAG-ready Markdown, with metadata attached.
## Quick start
The default install is small: Tesseract OCR only, no multi-GB ML downloads.
```bash
uv sync
pre-commit install
# Smoke test a small directory with the lightweight OCR path
uv run ocr-pipeline run \
--input-dir ~/Pictures/test_screenshots \
--output-dir /tmp/ocr-output \
--engine tesseract \
--workers 1 \
--exclude "*.photoslibrary/*"
uv run ocr-pipeline watch
uv run ocr-pipeline reprocess ocr_sc.ipynb
uv run ocr-pipeline status
uv sync # install the core pipeline
uv run ocr-pipeline setup # installs Tesseract if missing (asks first)
uv run ocr-pipeline init # write a config for this machine
uv run ocr-pipeline demo # verify everything works on a sample screenshot
uv run ocr-pipeline run # process your screenshots
```
Config is found in this order: `$OCR_PIPELINE_CONFIG`, `./config.yaml`, then the
per-user config directory (`~/Library/Application Support/ocr-pipeline` on macOS,
`~/.config/ocr-pipeline` on Linux). Running `run` with neither a config nor
`--input-dir` stops with guidance instead of scanning a default directory.
Use `--force` to reprocess files already recorded in the processing database. The
`--exclude` option is repeatable and prevents recursive scans from entering bundles
such as macOS `.photoslibrary` directories.
### Scientific NER environment
### Optional capabilities
`en_core_sci_lg` is distributed separately from scispaCy and is not installed by
`uv sync`. The compatible scispaCy 0.5.4 release requires spaCy 3.7.x, so install it
in a dedicated Python 3.11 environment rather than mixing it with the main Python
3.13 environment:
Heavy ML features are opt-in extras and degrade gracefully when absent (a warning
is logged and that step is skipped):
| Extra | Provides |
|-------|----------|
| `paddle` | PaddleOCR engine (`ocr.engine: paddleocr` or `auto`) |
| `scientific` | spaCy/scispaCy NER (`entities.enabled: true`) |
| `tables` | Table Transformer detection |
| `figures` | LayoutParser figure/caption detection (needs a Detectron2 build) |
| `full` | All of the above |
```bash
uv venv --python 3.11 .venv-scispacy
source .venv-scispacy/bin/activate
uv pip install "spacy>=3.7,<3.8" "scispacy==0.5.4" click
uv pip install https://s3-us-west-2.amazonaws.com/ai2-s2-scispacy/releases/v0.5.4/en_core_sci_lg-0.5.4.tar.gz
uv pip install -e .
uv pip install timm
# Confirm the model and command use this same environment
.venv-scispacy/bin/python -c "import spacy; spacy.load('en_core_sci_lg'); print('scispaCy OK')"
.venv-scispacy/bin/ocr-pipeline run --help
uv run ocr-pipeline setup full # runs: uv sync --extra full + downloads en_core_sci_lg
```
If the two environments are kept separate, invoke the pipeline with the explicit
`.venv-scispacy/bin/ocr-pipeline` path; `uv run` selects the project's default `.venv`.
`en_core_sci_lg` is distributed separately from scispaCy. The compatible scispaCy
0.5.4 release requires spaCy 3.7.x; if the model install conflicts with your spaCy
version, use a dedicated Python 3.11 environment as described in
`ocr-pipeline setup full --dry-run` output, and enable `entities` only there.
## kg_ocr (experimental)
The top-level `kg_ocr` package is a prototype txtai/litellm RAG interface over the
pipeline's output. It is not the supported interface (that is the `ocr-pipeline`
CLI) and its dependencies are not installed by default:
```bash
uv sync --extra kg
```
## Docker
The image ships the Tesseract-only core with a ready-made config that reads from
`/data/screenshots` and writes to `/data/output`:
```bash
docker build -t ocr-pipeline .
docker run -v ~/Pictures:/data/screenshots -v "$PWD/ocr-output:/data/output" ocr-pipeline run
docker run -v ~/Pictures:/data/screenshots -v "$PWD/ocr-output:/data/output" ocr-pipeline watch
docker run -v ~/Pictures:/data/screenshots -v ./data:/app/data ocr-pipeline run
docker run -v ~/Pictures:/data/screenshots -v ./data:/app/data ocr-pipeline watch
# ML extras baked in:
docker build --build-arg EXTRAS="--extra full" -t ocr-pipeline:full .
```
## Config
`ocr-pipeline init` writes a minimal working config; the example below shows every
knob for reference.
<details>
<summary><code>config.yaml</code></summary>
@@ -200,6 +215,7 @@ Gene/protein names go through scispaCy's `en_core_sci_lg`. Chemical formulas and
## Models
Model weights are only fetched when the matching extra is installed and enabled.
First run downloads what it needs, cached in `~/.cache/ocr_pipeline/`:
- PaddleOCR models (~200MB)