Skip to content

Files: Index the text in scanned documents with OCR #938

Description

@pchopinet

Context

Search can look inside documents since #923, but only where the words are already text. A scan carries pictures of words, so an invoice photographed by a phone or a contract returned by a flatbed indexes its filename and nothing else. #906 put OCR out of scope on purpose: "different dependency, different cost profile, its own issue if the need shows up". This is that issue.

Most of the work turns out to be already done, and the measurements below were taken against the branch that closed #906 so they do not need repeating.

The parser is already compiled in. iscc-tika ships Tika's TesseractOCRParser inside its native library. Grepping the shared object finds the class along with its runtime strings (hasTesseract, getTesseractPath, Tesseract command:, TesseractOCRParser timeout). It shells out to the tesseract binary at run time rather than embedding it.

The Python surface is a configuration change. workspace/common/documents/extraction.py already builds a PdfParserConfig and pins it to PdfOcrStrategy.NO_OCR. TesseractOcrConfig exposes set_language, set_timeout_seconds, set_density, set_depth, set_enable_image_preprocessing and set_apply_rotation.

Enabling it is free where the binary is absent. Without tesseract on PATH, Tika falls back to ImageParser, returns empty text and raises nothing. Measured over 25 runs each, AUTO and NO_OCR are indistinguishable: ~11 ms on a scan and on a text PDF alike. So the strategy can be switched on without waiting for the image to carry the binary.

AUTO only fires where it is needed. It runs OCR on pages with no text layer and leaves everything else alone, so ordinary documents cost nothing extra.

Scope

  • A setting, off or auto by default, that selects the OCR strategy and carries the language and a per-document timeout. Read through workspace/settings/ like every other setting, not hard-coded.
  • tesseract-ocr and its language data in the Docker image. Installed sizes on bookworm: tesseract-ocr 2.1 MB amd64 / 2.6 MB arm64, libtesseract5 3.5 / 3.2 MB, tesseract-ocr-eng 4.0 MB. The core is around 15 MB; the transitive image and text chain was not measured and needs a real build to confirm. Each further language adds roughly 1 to 5 MB. Whether this goes in the default image or an -ocr variant is part of the decision.
  • A separate Celery queue, or at least a separate rate, so a hundred-page scan cannot starve ordinary indexing. OCR costs seconds per page, and this project targets hardware as small as a Raspberry Pi, so the existing "extraction is fast and bounded" assumption stops holding.
  • A bound per document: set_timeout_seconds plus a page ceiling, so one pathological upload cannot occupy a worker indefinitely.

Notes

  • Enabling OCR on an existing instance only takes effect for documents indexed afterwards. reindex_files_search already exists for the backfill and should be named in whatever documentation this ships with.
  • Language is a per-instance choice. A French deployment needs tesseract-ocr-fra, and the setting has to allow more than one.
  • This widens the attack surface deliberately: untrusted PDFs get rendered to images and a external binary is invoked on the result. Worth a look at what the rendering path pulls in before shipping.
  • Out of scope here, as before: describing images with a vision model. That is a different dependency again and belongs to ai rather than to extraction.

Acceptance criteria

  • A word that appears only as pixels inside a scanned PDF finds the file, once OCR is enabled.
  • With OCR disabled, or with the binary absent, extraction behaves exactly as it does today and costs the same.
  • A scan that cannot be read within the timeout indexes its name and does not fail the task or hold the worker.
  • OCR work does not delay the indexing of ordinary documents.
  • The image size cost is measured on a real build and recorded, per architecture.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions