Skip to content

feat: implement OCR handling for embedded images and add warnings#2059

Open
ricofurtado wants to merge 5 commits into
mainfrom
fix--ocr-disable-errors-handling
Open

feat: implement OCR handling for embedded images and add warnings#2059
ricofurtado wants to merge 5 commits into
mainfrom
fix--ocr-disable-errors-handling

Conversation

@ricofurtado

@ricofurtado ricofurtado commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

This pull request introduces comprehensive support for handling documents with embedded images when OCR is disabled. It ensures that users are notified with clear warnings if embedded images are present but OCR is turned off, preventing silent data loss. The changes add detection for embedded images, propagate warnings through the document processing pipeline, and include tests to verify this behavior.

Embedded image detection and warning propagation:

  • Added the has_embedded_images field to the output of extract_relevant in document_processing.py, using a new has_embedded_images function to detect embedded images in Docling JSON exports. [1] [2]
  • Introduced EMBEDDED_IMAGES_OCR_DISABLED_WARNING and logic to attach a warning to processing results if embedded images are found and OCR is disabled, in both process_document_standard and upload_and_ingest_file. [1] [2]

Image file handling and error reporting:

  • Added is_image_file and get_ocr_disabled_image_error helpers to identify image files and return user-friendly errors if OCR is disabled, preventing ingestion of image files without OCR. [1] [2] [3] [4] [5]
  • Updated supported image extensions and ensured consistent checking for images throughout the processing pipeline. [1] [2]

Docling polling and result propagation:

  • Modified DoclingPollResult and DoclingPollingService to carry the full document JSON content, enabling downstream checks for embedded images. [1] [2] [3] [4]

Testing and validation:

  • Added unit tests to verify that the has_embedded_images field is set correctly and that warnings are issued when appropriate, including a new test for the two-phase Langflow ingestion flow. [1] [2]

Minor improvements:

  • Ensured that file ingestion fails early with a clear error if an image file is uploaded while OCR is disabled, improving user feedback and robustness. [1] [2] [3] [4]

Summary by CodeRabbit

  • New Features

    • Added OCR-disabled guard to block image ingestion early, returning a clear user-facing error.
    • Detects embedded images and surfaces an “embedded images were skipped” warning when OCR is disabled.
  • Bug Fixes

    • Keeps successful indexing results while attaching warnings when embedded images are present.
    • Updated task/file visibility so completed items with warnings remain shown.
  • Tests

    • Expanded unit and async coverage for embedded-image detection, OCR-disabled blocking, and warning behavior across ingestion and task listing/UI.

@github-actions github-actions Bot added backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) tests labels Jul 8, 2026
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0e347497-c53d-4e1b-9b7b-33da3bf2f874

📥 Commits

Reviewing files that changed from the base of the PR and between ec6783a and c990769.

📒 Files selected for processing (2)
  • src/services/langflow_file_service.py
  • tests/unit/test_langflow_file_service_two_phase.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/unit/test_langflow_file_service_two_phase.py
  • src/services/langflow_file_service.py

Walkthrough

Adds OCR-disabled image ingestion blocking across document processors, detects embedded images in Docling output, propagates warnings through standard and Langflow ingestion paths, and includes warning-bearing completed files in task listings.

Changes

OCR-disabled image handling and embedded-image warnings

Layer / File(s) Summary
Image detection and OCR-disabled error helpers
src/models/processors.py
Adds IMAGE_EXTENSIONS, is_image_file(), and get_ocr_disabled_image_error() helpers, plus imports the embedded-images warning constant.
Embedded-image detection in document processing
src/utils/document_processing.py, tests/unit/test_document_processing_resplit.py
Adds has_embedded_images() and reference-scanning helpers, extends extract_relevant() with a has_embedded_images flag, and adds unit tests.
Standard processing OCR override and embedded-image warning
src/models/processors.py, tests/unit/test_processors_embedded_image_warning.py
Computes effective_ocr from request override, passes it to Docling conversion, sets a warning when OCR is disabled and embedded images are found, and includes the warning in the returned payload; adds tests for both OCR states.
Early rejection for OCR-disabled images across processors
src/models/processors.py, tests/unit/test_processors_ocr_image_block.py
Adds early-fail checks in DocumentFileProcessor, ConnectorFileProcessor (including tif extension support and re-check after loading connector content), and LangflowFileProcessor, marking tasks failed with dedicated tests.
Docling polling result carries document JSON
src/services/docling_polling_service.py
Extends DoclingPollResult with document_json_content, populated during SUCCESS polling and returned.
Langflow ingestion embedded-image warning
src/services/langflow_file_service.py, tests/unit/test_langflow_file_service_two_phase.py
Imports has_embedded_images, handles absent polling service, and conditionally adds a warning to success responses when OCR is disabled and embedded images are detected; test updates and new test added.
Task warning visibility
src/services/task_service.py, frontend/lib/task-utils.ts, src/api/v1/documents.py, tests/unit/test_task_service_get_task_status2.py
Treats warning-bearing completed files as visible in task payloads, updates frontend warning classification, and adjusts API doc text and tests accordingly.
Metadata assertion tightening
tests/unit/test_processors_clear_stale_chunks.py
Changes an existing test assertion to check for absence of connector_file_id key instead of exact metadata equality.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TaskProcessor
  participant DoclingService
  participant DocumentProcessing

  TaskProcessor->>DoclingService: convert_file(ocr=effective_ocr)
  DoclingService-->>TaskProcessor: document data
  TaskProcessor->>DocumentProcessing: has_embedded_images(doc_dict)
  DocumentProcessing-->>TaskProcessor: true/false
  TaskProcessor-->>TaskProcessor: attach warning when OCR is disabled
Loading
sequenceDiagram
  participant Client
  participant LangflowFileService
  participant DoclingPollingService
  participant TaskService

  Client->>LangflowFileService: upload_and_ingest_file(ocr_override=false)
  LangflowFileService->>DoclingPollingService: poll_until_ready()
  DoclingPollingService-->>LangflowFileService: document_json_content
  LangflowFileService-->>Client: success result with warning
  TaskService-->>Client: tasks/files include warning-bearing completed files
Loading

Possibly related PRs

  • langflow-ai/openrag#1671: Both PRs modify task-status payload construction in src/services/task_service.py.
  • langflow-ai/openrag#1695: Both PRs modify src/models/processors.py, including ConnectorFileProcessor and document processing flow.
  • langflow-ai/openrag#1706: Both PRs modify ConnectorFileProcessor.process_item to perform early filename/extension checks.

Suggested reviewers: lucaseduoli, phact

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: OCR handling for embedded images and warning propagation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix--ocr-disable-errors-handling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jul 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
tests/unit/test_document_processing_resplit.py (1)

122-158: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding tests for the reference-based detection path.

The two new tests only exercise the top-level pictures collection key. The _references_image_collection helper has non-trivial recursive logic (string marker matching, dict label/type inspection, list traversal) that is currently untested. Adding a test that provides a body with #/pictures/ references or a dict item with label: "picture" would increase confidence in that code path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/test_document_processing_resplit.py` around lines 122 - 158, Add
coverage for the reference-based image detection path in extract_relevant and
its _references_image_collection helper. The current tests only verify the
top-level pictures key, so add a test that drives the recursive logic through a
body containing `#/pictures/` references and another case with a dict item using
label or type set to picture. Keep the assertions focused on has_embedded_images
so the helper’s string, dict, and list traversal branches are exercised.
tests/unit/test_processors_embedded_image_warning.py (1)

11-176: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract shared test setup to reduce duplication.

The two tests share nearly identical mock setup (~70 lines each) differing only in the ocr value and final assertions. A shared fixture or helper function for the common mocks (docling_service, config, embedding client, session_manager, etc.) parameterized by ocr would reduce duplication and prevent the two tests from drifting apart over time.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/test_processors_embedded_image_warning.py` around lines 11 - 176,
The two tests for TaskProcessor.process_document_standard duplicate the same
mock and fixture setup, so extract the shared preparation into a reusable helper
or fixture and parameterize it by the OCR setting. Keep the common setup for
document_service, session_manager, docling_service, models_service,
get_openrag_config, get_index_name, chunk_texts_for_embeddings, and the fake
embedding client in one place, then have both tests only pass the differing ocr
value and assert the expected warning behavior. This will reduce repetition and
keep the embedded-image warning coverage in sync.
src/models/processors.py (1)

719-724: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: extract the repeated OCR-disabled early-fail block.

This exact 5-line fail-and-return block is duplicated across DocumentFileProcessor (Line 719), ConnectorFileProcessor (Lines 937 and 999), and LangflowFileProcessor (Line 1410). A small helper would keep the FAILED/error/updated_at/failed_files side effects consistent if this shape ever changes.

♻️ Example helper
def _fail_task_with_ocr_image_error(
    upload_task: "UploadTask", file_task: "FileTask", error: str
) -> None:
    file_task.status = TaskStatus.FAILED
    file_task.error = error
    file_task.updated_at = time.time()
    upload_task.failed_files += 1
-            if image_error := get_ocr_disabled_image_error(original_filename):
-                file_task.status = TaskStatus.FAILED
-                file_task.error = image_error
-                file_task.updated_at = time.time()
-                upload_task.failed_files += 1
-                return
+            if image_error := get_ocr_disabled_image_error(original_filename):
+                _fail_task_with_ocr_image_error(upload_task, file_task, image_error)
+                return
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/models/processors.py` around lines 719 - 724, The OCR-disabled early-fail
block is duplicated in multiple processors, so extract the shared
FAILED/error/updated_at/failed_files logic into a small helper and reuse it from
DocumentFileProcessor, ConnectorFileProcessor, and LangflowFileProcessor. Add a
helper such as _fail_task_with_ocr_image_error and call it wherever
get_ocr_disabled_image_error() returns a value, keeping the status update, error
assignment, timestamp refresh, and failed_files increment in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/services/langflow_file_service.py`:
- Around line 1068-1073: Use the effective OCR state when deciding whether to
attach EMBEDDED_IMAGES_OCR_DISABLED_WARNING, because ocr_override only reflects
an explicit false override and misses config/default-disabled OCR. Update the
warning guard in the relevant block in langflow_file_service to mirror the
effective_ocr logic used in processors.py, and base the check on that computed
state before setting result["warning"].

---

Nitpick comments:
In `@src/models/processors.py`:
- Around line 719-724: The OCR-disabled early-fail block is duplicated in
multiple processors, so extract the shared FAILED/error/updated_at/failed_files
logic into a small helper and reuse it from DocumentFileProcessor,
ConnectorFileProcessor, and LangflowFileProcessor. Add a helper such as
_fail_task_with_ocr_image_error and call it wherever
get_ocr_disabled_image_error() returns a value, keeping the status update, error
assignment, timestamp refresh, and failed_files increment in one place.

In `@tests/unit/test_document_processing_resplit.py`:
- Around line 122-158: Add coverage for the reference-based image detection path
in extract_relevant and its _references_image_collection helper. The current
tests only verify the top-level pictures key, so add a test that drives the
recursive logic through a body containing `#/pictures/` references and another
case with a dict item using label or type set to picture. Keep the assertions
focused on has_embedded_images so the helper’s string, dict, and list traversal
branches are exercised.

In `@tests/unit/test_processors_embedded_image_warning.py`:
- Around line 11-176: The two tests for TaskProcessor.process_document_standard
duplicate the same mock and fixture setup, so extract the shared preparation
into a reusable helper or fixture and parameterize it by the OCR setting. Keep
the common setup for document_service, session_manager, docling_service,
models_service, get_openrag_config, get_index_name, chunk_texts_for_embeddings,
and the fake embedding client in one place, then have both tests only pass the
differing ocr value and assert the expected warning behavior. This will reduce
repetition and keep the embedded-image warning coverage in sync.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dce63426-c54a-4188-9209-fee25ed6c7f6

📥 Commits

Reviewing files that changed from the base of the PR and between 8e0f30b and 33e8194.

📒 Files selected for processing (9)
  • src/models/processors.py
  • src/services/docling_polling_service.py
  • src/services/langflow_file_service.py
  • src/utils/document_processing.py
  • tests/unit/test_document_processing_resplit.py
  • tests/unit/test_langflow_file_service_two_phase.py
  • tests/unit/test_processors_clear_stale_chunks.py
  • tests/unit/test_processors_embedded_image_warning.py
  • tests/unit/test_processors_ocr_image_block.py

Comment thread src/services/langflow_file_service.py
@github-actions github-actions Bot added the frontend 🟨 Issues related to the UI/UX label Jul 9, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jul 9, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) enhancement 🔵 New feature or request frontend 🟨 Issues related to the UI/UX tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant