NVIDIA / NVIDIA/NeMo-Retriever

[BUG] Propagate advertised ExtractParams fields to graph operators

Open
#2,324 1 comment 0 reactions 1 assignee View on GitHub

@jioffe502 is already working on this.

Since Jul 14, 2026.

bug python
Dominant language
Python
Stars
3k
Forks
349
Avg merge
1d 23h
Merged PRs (30d)
116

Description

Problem

ExtractParams publicly accepts several non-default settings that are not propagated to the PDF/image graph operators. Construction succeeds, but the values are silently replaced by operator defaults.

The fields are declared here:

Confirmed gaps on current upstream/main include:

  1. PDF rendering options

    render_mode, image_format, and jpeg_quality are accepted by ExtractParams and by the PDF extraction implementation, but build_graph() does not include them in extract_kwargs:

  2. Component-specific credentials and timeouts

    page_elements_api_key, page_elements_request_timeout_s, ocr_api_key, and ocr_request_timeout_s are declared, but the PDF/image detection graph uses the generic api_key and global retry/timeout mapping instead:

    The video branch already implements the intended OCR precedence (component-specific value, then global fallback), so PDF/image behavior is inconsistent with video:

  3. Page-element output columns

    output_column, num_detections_column, and counts_by_label_column are accepted by ExtractParams and supported by the page-elements function, but are not forwarded in detect_kwargs.

  4. Batch vs in-process parity

    MultiTypeExtractOperator reconstructs similar kwargs independently and drops the same rendering/output settings and component-specific PDF/image credentials/timeouts:

  5. Remote OCR batch-size wiring

    ocr_page_elements() accepts inference_batch_size as a formal argument, but its remote branch reads kwargs.get("inference_batch_size", 8). A normal bound argument is therefore ignored remotely and the request batch size remains 8:

These are dangerous silent no-ops: the object validates, the graph runs, and users cannot tell that their chosen rendering, routing, timeout, output schema, or remote batch-size setting was not honored.

Proposed behavior

Create one stage-specific mapping path from ExtractParams to operator kwargs and reuse it in both build_graph() and MultiTypeExtractOperator. Each public field should have one explicit owner and one documented precedence rule.

Suggested precedence for component settings:

  1. component-specific value, such as ocr_api_key or ocr_request_timeout_s
  2. generic api_key or request_timeout_s fallback
  3. operator default

Do not log credential values. Graph/debug representations must redact secrets.

Acceptance criteria

  • Every ExtractParams field is classified as either:
    • forwarded to a named operator/stage,
    • consumed by graph planning, or
    • removed/deprecated with an explicit validation or migration path.
  • No accepted ExtractParams field is a silent no-op.
  • render_mode, image_format, and jpeg_quality reach PDFExtractionActor in both batch-graph and MultiType/in-process paths.
  • Page-element component credentials, timeout, and custom output-column names reach PageElementDetectionActor.
  • OCR component credentials and timeout reach OCR, table-structure OCR, graphic-elements OCR, and video OCR with the same documented fallback rules.
  • Remote OCR uses the formal inference_batch_size value.
  • Batch graph and MultiType/in-process construction produce equivalent relevant stage kwargs for identical ExtractParams.
  • Tests construct ExtractParams with unique non-default sentinel values and assert the resolved node/actor kwargs, including secret redaction.
  • Runtime smoke tests verify custom page-element column names and observable remote request timeout/batch-size behavior.
  • Existing defaults remain behaviorally unchanged.

Validation and benchmark plan

1. Contract tests (primary gate)

This is primarily a configuration-correctness bug. Add a table-driven test that enumerates every ExtractParams model field and requires a declared consumer/disposition. Build both graph forms with non-default sentinels and inspect the resolved node kwargs.

Include at least:

  • fit_to_model vs full_dpi
  • jpeg vs png and non-default JPEG quality
  • different global, page-elements, and OCR API keys/timeouts to prove precedence
  • custom page-element output columns
  • remote OCR inference batch sizes 1, 4, 8, and 16
  • PDF, image, and video paths
  • batch graph and MultiType/in-process graph
2. PDF extraction performance matrix

Extend the existing extraction benchmark so the advertised render settings can be supplied and recorded:

uv run retriever benchmark extract run       --pdf-path /path/to/representative.pdf       --rows 128       --workers 1,2       --batch-sizes 1,4,8,16       --dpi 200       --output-json /tmp/extract-params-wiring.json

Run these cases on a native-text PDF, a dense scanned PDF, and an oversized page:

  • fit_to_model + jpeg + quality 100 (current default)
  • full_dpi + jpeg + quality 100
  • fit_to_model + jpeg + quality 80
  • fit_to_model + png

Record rows/sec, wall time, encoded page bytes, raster dimensions, peak RSS, and downstream page-element/OCR success counts. The default case must not regress; non-default cases must visibly change the expected raster/encoding properties.

3. Remote OCR request probe

Use a recording test endpoint or client double and sweep inference batch sizes 1, 4, 8, and 16. Record actual request chunk sizes and timeout values, not only throughput. This can share the focused benchmark added for the cross-page OCR batching issue.

4. End-to-end regression gate

Run the registered JP20 BEIR benchmark with the default configuration before and after:

uv run retriever harness run       --dataset jp20_beir       --run-name extract-params-wiring-default

Preserve and compare ingest timing, output artifacts, and standard retrieval metrics. Default output and quality should remain unchanged; focused contract tests are what prove the non-default settings are now honored.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.