Skip to content

Add text extraction (OCR / document parsing) capability - #269

Open
saarnilauri wants to merge 2 commits into
WordPress:trunkfrom
saarnilauri:feature/text-extraction-poc
Open

Add text extraction (OCR / document parsing) capability#269
saarnilauri wants to merge 2 commits into
WordPress:trunkfrom
saarnilauri:feature/text-extraction-poc

Conversation

@saarnilauri

@saarnilauri saarnilauri commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Adds a provider-agnostic text extraction capability, following the structural pattern established by embedding generation in 1.4.0 (dedicated builder, result type, and requirements factory):

  • CapabilityEnum::TEXT_EXTRACTION with magic accessors.
  • TextExtractionModelInterface::extractTextResult(File): TextExtractionResult.
  • Result DTOs: TextExtractionResult (ResultInterface, non-candidate-based), ExtractedPage (1-based page numbers, markdown content), ExtractedImage, BoundingBox (normalized 0-1 coordinates), PageDimensions.
  • ModelRequirements::fromExtractionData() mapping the document's MIME type to a document or image input-modality requirement.
  • TextExtractionBuilder with withDocument($document, $mimeType) plus AiClient::document() / extractTextResult() / extractText() entry points.

Validated end to end by two downstream provider PoCs with intentionally different API shapes: ai-provider-for-mistral (synchronous dedicated OCR endpoint) and ai-provider-for-llamaparse (async job-based parsing with internal polling).

For more details see the issue that this PR closes #268

Use of AI Tools

This implementations was drafted with the assistance of Claude Code (Anthropic), used for researching the provider APIs, analyzing the SDK architecture, and writing code. All work was done with a human in the loop: the design direction, scope decisions, and API trade-offs were made or reviewed by the author, and the proof of concept was verified by the author against the live Mistral and LlamaParse APIs (including real integration test runs and inspection of the extracted output).

Adds a provider-agnostic text extraction capability, following the
structural pattern established by embedding generation in 1.4.0
(dedicated builder, result type, and requirements factory):

- CapabilityEnum::TEXT_EXTRACTION with magic accessors.
- TextExtractionModelInterface::extractTextResult(File): TextExtractionResult.
- Result DTOs: TextExtractionResult (ResultInterface, non-candidate-based),
  ExtractedPage (1-based page numbers, markdown content), ExtractedImage,
  BoundingBox (normalized 0-1 coordinates), PageDimensions.
- ModelRequirements::fromExtractionData() mapping the document's MIME type
  to a document or image input-modality requirement.
- TextExtractionBuilder with withDocument($document, $mimeType) plus
  AiClient::document() / extractTextResult() / extractText() entry points.

Validated end to end by two downstream provider PoCs with intentionally
different API shapes: ai-provider-for-mistral (synchronous dedicated OCR
endpoint) and ai-provider-for-llamaparse (async job-based parsing with
internal polling).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: saarnilauri <laurisaarni@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.67%. Comparing base (a31b0ec) to head (127caab).

Additional details and impacted files
@@             Coverage Diff              @@
##              trunk     #269      +/-   ##
============================================
+ Coverage     86.49%   87.67%   +1.17%     
- Complexity     1327     1418      +91     
============================================
  Files            68       74       +6     
  Lines          4295     4696     +401     
============================================
+ Hits           3715     4117     +402     
+ Misses          580      579       -1     
Flag Coverage Δ
unit 87.67% <100.00%> (+1.17%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add provider-agnostic text extraction (OCR / document parsing) capability

1 participant