Skip to content

OCR fallback via kind='ocr_text' artifact (concrete path for #13 OCR item) #18

Description

@deOliveira-R

Refines the OCR line-item in the v2 umbrella (#13) with a concrete path now that the artifact infrastructure (commit e2b7342) is in place.

The gap

Scanned PDFs have no extractable text. PyMuPDF returns empty pages → zero chunks → invisible to both keyword and chunk-level semantic search. Only the item-level SPECTER2 embedding (title + abstract) surfaces them at all, and that relies on Crossref/GROBID having given us an abstract — which usually fails for scans.

Plan

  1. New CLI: `grimoire artifacts build --kind ocr_text [--since YYYY-MM-DD] [-j N]`.
  2. Walks items where:
    • `primary` artifact exists, and
    • `extract.pdf.has_extractable_text()` returns False (body is empty/degenerate), and
    • no `ocr_text` artifact yet.
  3. Each worker thread:
    • Pulls the primary CAS blob.
    • Runs ocrmypdf or pure Tesseract over it — the plan chose `ocrmypdf` (plan §4 tech-stack row).
    • Stores the plain-text result as the `ocr_text` artifact (source: `tesseract-` or `ocrmypdf-`).
  4. Extend `index.py` so when chunking a PDF item:
    • Prefer `ocr_text` artifact over raw PyMuPDF extraction when the latter is empty.
    • Reuse the existing chunker; no schema change (page numbers become approximate/synthetic for scans).
  5. Bonus: add a soft `metadata_confidence` reduction when the source is OCR so the dedup tier-4 is more cautious.

Acceptance

  • `grimoire artifacts build --kind ocr_text` walks scanned PDFs, writes `ocr_text` artifacts.
  • Indexer consumes OCR text when PyMuPDF gives nothing; scanned papers become searchable.
  • Throughput is bounded: 30 s – 2 min per page as the plan warns; `-j N` parallelism respected.
  • Non-scanned PDFs are untouched.
  • Test with a synthetic image-only PDF (built via pymupdf with `insert_image` + a pre-rendered PNG of text) + a stubbed OCR callable; assert end-to-end behavior.

Notes

  • The `ocrmypdf` dependency is heavy (pulls in Tesseract, poppler). Keep it in an optional extra (`[ocr]`) so it's not mandatory for users who don't need it.
  • Processing cost is bounded per-scan and embarrassingly parallel — user has explicitly said processing isn't a concern.
  • This closes the "invariant 7 (paper + DOI ⇒ venue)" soft-failure path for a lot of items where OCR could have provided a first-page abstract for Crossref backfill — worth measuring on the real library once landed.

Once this ships, update the corresponding checkbox in #13.

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

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions