nv-ingest-api 2025.7.16.dev20250716__tar.gz → 2025.7.18.dev20250718__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nv-ingest-api might be problematic. Click here for more details.
- {nv_ingest_api-2025.7.16.dev20250716/src/nv_ingest_api.egg-info → nv_ingest_api-2025.7.18.dev20250718}/PKG-INFO +1 -1
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/interface/extract.py +18 -18
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/image/chart_extractor.py +80 -75
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/image/image_helpers/common.py +5 -6
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/image/infographic_extractor.py +59 -35
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/image/table_extractor.py +84 -64
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/engines/nemoretriever.py +10 -7
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/engines/pdfium.py +16 -29
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/helpers.py +59 -0
- nv_ingest_api-2025.7.16.dev20250716/src/nv_ingest_api/internal/primitives/nim/model_interface/paddle.py → nv_ingest_api-2025.7.18.dev20250718/src/nv_ingest_api/internal/primitives/nim/model_interface/ocr.py +132 -39
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/yolox.py +37 -224
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/nim_client.py +55 -14
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/extract_chart_schema.py +6 -6
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/extract_infographic_schema.py +6 -6
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/extract_table_schema.py +5 -5
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/transform/split_text.py +13 -8
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/image_processing/table_and_chart.py +97 -42
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/image_processing/transforms.py +16 -5
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/message_brokers/simple_message_broker/broker.py +1 -1
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/message_brokers/simple_message_broker/simple_client.py +51 -48
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718/src/nv_ingest_api.egg-info}/PKG-INFO +1 -1
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api.egg-info/SOURCES.txt +1 -1
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/LICENSE +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/MANIFEST.in +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/README.md +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/pyproject.toml +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/setup.cfg +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/interface/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/interface/mutate.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/interface/store.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/interface/transform.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/interface/utility.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/enums/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/enums/common.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/audio/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/audio/audio_extraction.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/docx/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/docx/docx_extractor.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/docx/engines/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/docx/engines/docxreader_helpers/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/docx/engines/docxreader_helpers/docx_helper.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/docx/engines/docxreader_helpers/docxreader.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/html/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/html/html_extractor.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/image/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/image/image_extractor.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/image/image_helpers/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/engines/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/engines/adobe.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/engines/llama.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/engines/pdf_helpers/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/engines/tika.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/engines/unstructured_io.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pdf/pdf_extractor.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pptx/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pptx/engines/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pptx/engines/pptx_helper.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/extract/pptx/pptx_extractor.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/mutate/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/mutate/deduplicate.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/mutate/filter.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/control_message_task.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/ingest_control_message.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/default_values.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/cached.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/decorators.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/deplot.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/nemoretriever_parse.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/parakeet.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/text_embedding.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/model_interface/vlm.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/nim/nim_model_interface.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/tracing/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/tracing/latency.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/tracing/logging.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/primitives/tracing/tagging.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/extract_audio_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/extract_docx_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/extract_html_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/extract_image_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/extract_pdf_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/extract/extract_pptx_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/message_brokers/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/message_brokers/message_broker_client_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/message_brokers/request_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/message_brokers/response_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/meta/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/meta/base_model_noext.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/meta/ingest_job_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/meta/metadata_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/mutate/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/mutate/mutate_image_dedup_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/store/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/store/store_embedding_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/store/store_image_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/transform/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/transform/transform_image_caption_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/transform/transform_image_filter_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/transform/transform_text_embedding_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/schemas/transform/transform_text_splitter_schema.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/store/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/store/embed_text_upload.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/store/image_upload.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/transform/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/transform/caption_image.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/internal/transform/embed_text.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/control_message/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/control_message/validators.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/converters/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/converters/bytetools.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/converters/containers.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/converters/datetools.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/converters/dftools.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/converters/formats.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/converters/type_mappings.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/detectors/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/detectors/language.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/exception_handlers/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/exception_handlers/converters.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/exception_handlers/decorators.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/exception_handlers/detectors.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/exception_handlers/pdf.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/exception_handlers/schemas.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/image_processing/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/image_processing/clustering.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/image_processing/processing.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/imports/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/imports/callable_signatures.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/imports/dynamic_resolvers.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/logging/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/logging/configuration.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/message_brokers/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/message_brokers/simple_message_broker/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/message_brokers/simple_message_broker/ordered_message_queue.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/metadata/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/metadata/aggregators.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/multi_processing/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/multi_processing/mp_pool_singleton.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/nim/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/pdf/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/pdf/pdfium.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/schema/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/schema/schema_validator.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/service_clients/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/service_clients/client_base.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/service_clients/kafka/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/service_clients/redis/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/service_clients/redis/redis_client.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/service_clients/rest/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/service_clients/rest/rest_client.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/string_processing/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/system/__init__.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api/util/system/hardware_info.py +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api.egg-info/dependency_links.txt +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api.egg-info/requires.txt +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/nv_ingest_api.egg-info/top_level.txt +0 -0
- {nv_ingest_api-2025.7.16.dev20250716 → nv_ingest_api-2025.7.18.dev20250718}/src/version.py +0 -0
|
@@ -781,9 +781,9 @@ def extract_chart_data_from_image(
|
|
|
781
781
|
*,
|
|
782
782
|
df_ledger: pd.DataFrame,
|
|
783
783
|
yolox_endpoints: Tuple[str, str],
|
|
784
|
-
|
|
784
|
+
ocr_endpoints: Tuple[str, str],
|
|
785
785
|
yolox_protocol: str = "grpc",
|
|
786
|
-
|
|
786
|
+
ocr_protocol: str = "grpc",
|
|
787
787
|
auth_token: str = "",
|
|
788
788
|
) -> DataFrame:
|
|
789
789
|
"""
|
|
@@ -795,11 +795,11 @@ def extract_chart_data_from_image(
|
|
|
795
795
|
DataFrame containing metadata required for chart extraction.
|
|
796
796
|
yolox_endpoints : Tuple[str, str]
|
|
797
797
|
YOLOX inference server endpoints.
|
|
798
|
-
|
|
798
|
+
ocr_endpoints : Tuple[str, str]
|
|
799
799
|
PaddleOCR inference server endpoints.
|
|
800
800
|
yolox_protocol : str, optional
|
|
801
801
|
Protocol for YOLOX inference (default "grpc").
|
|
802
|
-
|
|
802
|
+
ocr_protocol : str, optional
|
|
803
803
|
Protocol for PaddleOCR inference (default "grpc").
|
|
804
804
|
auth_token : str, optional
|
|
805
805
|
Authentication token for inference services.
|
|
@@ -821,9 +821,9 @@ def extract_chart_data_from_image(
|
|
|
821
821
|
**{
|
|
822
822
|
"endpoint_config": {
|
|
823
823
|
"yolox_endpoints": yolox_endpoints,
|
|
824
|
-
"
|
|
824
|
+
"ocr_endpoints": ocr_endpoints,
|
|
825
825
|
"yolox_infer_protocol": yolox_protocol,
|
|
826
|
-
"
|
|
826
|
+
"ocr_infer_protocol": ocr_protocol,
|
|
827
827
|
"auth_token": auth_token,
|
|
828
828
|
}
|
|
829
829
|
}
|
|
@@ -844,9 +844,9 @@ def extract_table_data_from_image(
|
|
|
844
844
|
*,
|
|
845
845
|
df_ledger: pd.DataFrame,
|
|
846
846
|
yolox_endpoints: Optional[Tuple[str, str]] = None,
|
|
847
|
-
|
|
847
|
+
ocr_endpoints: Optional[Tuple[str, str]] = None,
|
|
848
848
|
yolox_protocol: Optional[str] = None,
|
|
849
|
-
|
|
849
|
+
ocr_protocol: Optional[str] = None,
|
|
850
850
|
auth_token: Optional[str] = None,
|
|
851
851
|
) -> pd.DataFrame:
|
|
852
852
|
"""
|
|
@@ -858,11 +858,11 @@ def extract_table_data_from_image(
|
|
|
858
858
|
DataFrame containing metadata required for chart extraction.
|
|
859
859
|
yolox_endpoints : Optional[Tuple[str, str]], default=None
|
|
860
860
|
YOLOX inference server endpoints. If None, the default defined in ChartExtractorConfigSchema is used.
|
|
861
|
-
|
|
861
|
+
ocr_endpoints : Optional[Tuple[str, str]], default=None
|
|
862
862
|
PaddleOCR inference server endpoints. If None, the default defined in ChartExtractorConfigSchema is used.
|
|
863
863
|
yolox_protocol : Optional[str], default=None
|
|
864
864
|
Protocol for YOLOX inference. If None, the default defined in ChartExtractorConfigSchema is used.
|
|
865
|
-
|
|
865
|
+
ocr_protocol : Optional[str], default=None
|
|
866
866
|
Protocol for PaddleOCR inference. If None, the default defined in ChartExtractorConfigSchema is used.
|
|
867
867
|
auth_token : Optional[str], default=None
|
|
868
868
|
Authentication token for inference services. If None, the default defined in ChartExtractorConfigSchema is used.
|
|
@@ -882,9 +882,9 @@ def extract_table_data_from_image(
|
|
|
882
882
|
config_kwargs = {
|
|
883
883
|
"endpoint_config": {
|
|
884
884
|
"yolox_endpoints": yolox_endpoints,
|
|
885
|
-
"
|
|
885
|
+
"ocr_endpoints": ocr_endpoints,
|
|
886
886
|
"yolox_infer_protocol": yolox_protocol,
|
|
887
|
-
"
|
|
887
|
+
"ocr_infer_protocol": ocr_protocol,
|
|
888
888
|
"auth_token": auth_token,
|
|
889
889
|
}
|
|
890
890
|
}
|
|
@@ -907,8 +907,8 @@ def extract_table_data_from_image(
|
|
|
907
907
|
def extract_infographic_data_from_image(
|
|
908
908
|
*,
|
|
909
909
|
df_ledger: pd.DataFrame,
|
|
910
|
-
|
|
911
|
-
|
|
910
|
+
ocr_endpoints: Optional[Tuple[str, str]] = None,
|
|
911
|
+
ocr_protocol: Optional[str] = None,
|
|
912
912
|
auth_token: Optional[str] = None,
|
|
913
913
|
) -> pd.DataFrame:
|
|
914
914
|
"""
|
|
@@ -924,10 +924,10 @@ def extract_infographic_data_from_image(
|
|
|
924
924
|
----------
|
|
925
925
|
df_extraction_ledger : pd.DataFrame
|
|
926
926
|
DataFrame containing the images and associated metadata from which infographic data is to be extracted.
|
|
927
|
-
|
|
927
|
+
ocr_endpoints : Optional[Tuple[str, str]], default=None
|
|
928
928
|
A tuple of PaddleOCR endpoint addresses (e.g., (gRPC_endpoint, HTTP_endpoint)) used for inference.
|
|
929
929
|
If None, the default endpoints from InfographicExtractorConfigSchema are used.
|
|
930
|
-
|
|
930
|
+
ocr_protocol : Optional[str], default=None
|
|
931
931
|
The protocol (e.g., "grpc" or "http") for PaddleOCR inference.
|
|
932
932
|
If None, the default protocol from InfographicExtractorConfigSchema is used.
|
|
933
933
|
auth_token : Optional[str], default=None
|
|
@@ -951,8 +951,8 @@ def extract_infographic_data_from_image(
|
|
|
951
951
|
extractor_config_kwargs = {
|
|
952
952
|
"endpoint_config": InfographicExtractorConfigSchema(
|
|
953
953
|
**{
|
|
954
|
-
"
|
|
955
|
-
"
|
|
954
|
+
"ocr_endpoints": ocr_endpoints,
|
|
955
|
+
"ocr_infer_protocol": ocr_protocol,
|
|
956
956
|
"auth_token": auth_token,
|
|
957
957
|
}
|
|
958
958
|
)
|
|
@@ -13,12 +13,12 @@ from typing import Tuple
|
|
|
13
13
|
import numpy as np
|
|
14
14
|
import pandas as pd
|
|
15
15
|
|
|
16
|
-
from nv_ingest_api.internal.primitives.nim.model_interface.helpers import get_version
|
|
17
16
|
from nv_ingest_api.internal.schemas.extract.extract_chart_schema import ChartExtractorSchema
|
|
18
17
|
from nv_ingest_api.internal.schemas.meta.ingest_job_schema import IngestTaskChartExtraction
|
|
19
|
-
from nv_ingest_api.util.image_processing.table_and_chart import
|
|
18
|
+
from nv_ingest_api.util.image_processing.table_and_chart import join_yolox_graphic_elements_and_ocr_output
|
|
20
19
|
from nv_ingest_api.util.image_processing.table_and_chart import process_yolox_graphic_elements
|
|
21
|
-
from nv_ingest_api.internal.primitives.nim.model_interface.
|
|
20
|
+
from nv_ingest_api.internal.primitives.nim.model_interface.ocr import OCRModelInterface
|
|
21
|
+
from nv_ingest_api.internal.primitives.nim.model_interface.ocr import get_ocr_model_name
|
|
22
22
|
from nv_ingest_api.internal.primitives.nim import NimClient
|
|
23
23
|
from nv_ingest_api.internal.primitives.nim.model_interface.yolox import YoloxGraphicElementsModelInterface
|
|
24
24
|
from nv_ingest_api.util.image_processing.transforms import base64_to_numpy
|
|
@@ -62,7 +62,8 @@ def _filter_valid_chart_images(
|
|
|
62
62
|
|
|
63
63
|
def _run_chart_inference(
|
|
64
64
|
yolox_client: Any,
|
|
65
|
-
|
|
65
|
+
ocr_client: Any,
|
|
66
|
+
ocr_model_name: str,
|
|
66
67
|
valid_arrays: List[np.ndarray],
|
|
67
68
|
valid_images: List[str],
|
|
68
69
|
trace_info: Dict,
|
|
@@ -70,29 +71,43 @@ def _run_chart_inference(
|
|
|
70
71
|
"""
|
|
71
72
|
Run concurrent inference for chart extraction using YOLOX and Paddle.
|
|
72
73
|
|
|
73
|
-
Returns a tuple of (yolox_results,
|
|
74
|
+
Returns a tuple of (yolox_results, ocr_results).
|
|
74
75
|
"""
|
|
75
76
|
data_yolox = {"images": valid_arrays}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
77
|
+
data_ocr = {"base64_images": valid_images}
|
|
78
|
+
|
|
79
|
+
future_yolox_kwargs = dict(
|
|
80
|
+
data=data_yolox,
|
|
81
|
+
model_name="yolox_ensemble",
|
|
82
|
+
stage_name="chart_extraction",
|
|
83
|
+
input_names=["INPUT_IMAGES", "THRESHOLDS"],
|
|
84
|
+
dtypes=["BYTES", "FP32"],
|
|
85
|
+
output_names=["OUTPUT"],
|
|
86
|
+
trace_info=trace_info,
|
|
87
|
+
max_batch_size=8,
|
|
88
|
+
)
|
|
89
|
+
future_ocr_kwargs = dict(
|
|
90
|
+
data=data_ocr,
|
|
91
|
+
stage_name="chart_extraction",
|
|
92
|
+
max_batch_size=1 if ocr_client.protocol == "grpc" else 2,
|
|
93
|
+
trace_info=trace_info,
|
|
94
|
+
)
|
|
95
|
+
if ocr_model_name == "paddle":
|
|
96
|
+
future_ocr_kwargs.update(
|
|
90
97
|
model_name="paddle",
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
)
|
|
99
|
+
else:
|
|
100
|
+
future_ocr_kwargs.update(
|
|
101
|
+
model_name="scene_text",
|
|
102
|
+
input_names=["input", "merge_levels"],
|
|
103
|
+
dtypes=["FP32", "BYTES"],
|
|
104
|
+
merge_level="paragraph",
|
|
94
105
|
)
|
|
95
106
|
|
|
107
|
+
with ThreadPoolExecutor(max_workers=2) as executor:
|
|
108
|
+
future_yolox = executor.submit(yolox_client.infer, **future_yolox_kwargs)
|
|
109
|
+
future_ocr = executor.submit(ocr_client.infer, **future_ocr_kwargs)
|
|
110
|
+
|
|
96
111
|
try:
|
|
97
112
|
yolox_results = future_yolox.result()
|
|
98
113
|
except Exception as e:
|
|
@@ -100,16 +115,16 @@ def _run_chart_inference(
|
|
|
100
115
|
raise
|
|
101
116
|
|
|
102
117
|
try:
|
|
103
|
-
|
|
118
|
+
ocr_results = future_ocr.result()
|
|
104
119
|
except Exception as e:
|
|
105
|
-
logger.error(f"Error calling
|
|
120
|
+
logger.error(f"Error calling ocr_client.infer: {e}", exc_info=True)
|
|
106
121
|
raise
|
|
107
122
|
|
|
108
|
-
return yolox_results,
|
|
123
|
+
return yolox_results, ocr_results
|
|
109
124
|
|
|
110
125
|
|
|
111
126
|
def _validate_chart_inference_results(
|
|
112
|
-
yolox_results: Any,
|
|
127
|
+
yolox_results: Any, ocr_results: Any, valid_arrays: List[Any], valid_images: List[str]
|
|
113
128
|
) -> Tuple[List[Any], List[Any]]:
|
|
114
129
|
"""
|
|
115
130
|
Ensure inference results are lists and have expected lengths.
|
|
@@ -117,21 +132,21 @@ def _validate_chart_inference_results(
|
|
|
117
132
|
Raises:
|
|
118
133
|
ValueError if results do not match expected types or lengths.
|
|
119
134
|
"""
|
|
120
|
-
if not (isinstance(yolox_results, list) and isinstance(
|
|
121
|
-
raise ValueError("Expected list results from both yolox_client and
|
|
135
|
+
if not (isinstance(yolox_results, list) and isinstance(ocr_results, list)):
|
|
136
|
+
raise ValueError("Expected list results from both yolox_client and ocr_client infer calls.")
|
|
122
137
|
|
|
123
138
|
if len(yolox_results) != len(valid_arrays):
|
|
124
139
|
raise ValueError(f"Expected {len(valid_arrays)} yolox results, got {len(yolox_results)}")
|
|
125
|
-
if len(
|
|
126
|
-
raise ValueError(f"Expected {len(valid_images)}
|
|
127
|
-
return yolox_results,
|
|
140
|
+
if len(ocr_results) != len(valid_images):
|
|
141
|
+
raise ValueError(f"Expected {len(valid_images)} ocr results, got {len(ocr_results)}")
|
|
142
|
+
return yolox_results, ocr_results
|
|
128
143
|
|
|
129
144
|
|
|
130
145
|
def _merge_chart_results(
|
|
131
146
|
base64_images: List[str],
|
|
132
147
|
valid_indices: List[int],
|
|
133
148
|
yolox_results: List[Any],
|
|
134
|
-
|
|
149
|
+
ocr_results: List[Any],
|
|
135
150
|
initial_results: List[Tuple[str, Optional[Dict]]],
|
|
136
151
|
) -> List[Tuple[str, Optional[Dict]]]:
|
|
137
152
|
"""
|
|
@@ -140,10 +155,10 @@ def _merge_chart_results(
|
|
|
140
155
|
For each valid image, processes the results from both inference calls and updates the
|
|
141
156
|
corresponding entry in the results list.
|
|
142
157
|
"""
|
|
143
|
-
for idx, (yolox_res,
|
|
144
|
-
# Unpack
|
|
145
|
-
bounding_boxes, text_predictions =
|
|
146
|
-
yolox_elements =
|
|
158
|
+
for idx, (yolox_res, ocr_res) in enumerate(zip(yolox_results, ocr_results)):
|
|
159
|
+
# Unpack ocr result into bounding boxes and text predictions.
|
|
160
|
+
bounding_boxes, text_predictions, _ = ocr_res
|
|
161
|
+
yolox_elements = join_yolox_graphic_elements_and_ocr_output(yolox_res, bounding_boxes, text_predictions)
|
|
147
162
|
chart_content = process_yolox_graphic_elements(yolox_elements)
|
|
148
163
|
original_index = valid_indices[idx]
|
|
149
164
|
initial_results[original_index] = (base64_images[original_index], chart_content)
|
|
@@ -153,7 +168,8 @@ def _merge_chart_results(
|
|
|
153
168
|
def _update_chart_metadata(
|
|
154
169
|
base64_images: List[str],
|
|
155
170
|
yolox_client: Any,
|
|
156
|
-
|
|
171
|
+
ocr_client: Any,
|
|
172
|
+
ocr_model_name: str,
|
|
157
173
|
trace_info: Dict,
|
|
158
174
|
worker_pool_size: int = 8, # Not currently used.
|
|
159
175
|
) -> List[Tuple[str, Optional[Dict]]]:
|
|
@@ -172,51 +188,35 @@ def _update_chart_metadata(
|
|
|
172
188
|
valid_images, valid_arrays, valid_indices, results = _filter_valid_chart_images(base64_images)
|
|
173
189
|
|
|
174
190
|
# Run concurrent inference only for valid images.
|
|
175
|
-
yolox_results,
|
|
191
|
+
yolox_results, ocr_results = _run_chart_inference(
|
|
176
192
|
yolox_client=yolox_client,
|
|
177
|
-
|
|
193
|
+
ocr_client=ocr_client,
|
|
194
|
+
ocr_model_name=ocr_model_name,
|
|
178
195
|
valid_arrays=valid_arrays,
|
|
179
196
|
valid_images=valid_images,
|
|
180
197
|
trace_info=trace_info,
|
|
181
198
|
)
|
|
182
199
|
|
|
183
200
|
# Validate that the returned inference results are lists of the expected length.
|
|
184
|
-
yolox_results,
|
|
185
|
-
yolox_results,
|
|
201
|
+
yolox_results, ocr_results = _validate_chart_inference_results(
|
|
202
|
+
yolox_results, ocr_results, valid_arrays, valid_images
|
|
186
203
|
)
|
|
187
204
|
|
|
188
205
|
# Merge the inference results into the results list.
|
|
189
|
-
return _merge_chart_results(base64_images, valid_indices, yolox_results,
|
|
206
|
+
return _merge_chart_results(base64_images, valid_indices, yolox_results, ocr_results, results)
|
|
190
207
|
|
|
191
208
|
|
|
192
209
|
def _create_clients(
|
|
193
210
|
yolox_endpoints: Tuple[str, str],
|
|
194
211
|
yolox_protocol: str,
|
|
195
|
-
|
|
196
|
-
|
|
212
|
+
ocr_endpoints: Tuple[str, str],
|
|
213
|
+
ocr_protocol: str,
|
|
197
214
|
auth_token: str,
|
|
198
215
|
) -> Tuple[NimClient, NimClient]:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
yolox_http_endpoint = yolox_endpoints[1]
|
|
202
|
-
|
|
203
|
-
try:
|
|
204
|
-
yolox_version = get_version(yolox_http_endpoint)
|
|
205
|
-
if not yolox_version:
|
|
206
|
-
logger.warning(
|
|
207
|
-
"Failed to obtain yolox-page-elements version from the endpoint. Falling back to the latest version."
|
|
208
|
-
)
|
|
209
|
-
yolox_version = None # Default to the latest version
|
|
210
|
-
except Exception:
|
|
211
|
-
logger.warning(
|
|
212
|
-
"Failed to get yolox-page-elements version after 30 seconds. Falling back to the latest version."
|
|
213
|
-
)
|
|
214
|
-
yolox_version = None # Default to the latest version
|
|
216
|
+
yolox_model_interface = YoloxGraphicElementsModelInterface()
|
|
217
|
+
ocr_model_interface = OCRModelInterface()
|
|
215
218
|
|
|
216
|
-
|
|
217
|
-
paddle_model_interface = PaddleOCRModelInterface()
|
|
218
|
-
|
|
219
|
-
logger.debug(f"Inference protocols: yolox={yolox_protocol}, paddle={paddle_protocol}")
|
|
219
|
+
logger.debug(f"Inference protocols: yolox={yolox_protocol}, ocr={ocr_protocol}")
|
|
220
220
|
|
|
221
221
|
yolox_client = create_inference_client(
|
|
222
222
|
endpoints=yolox_endpoints,
|
|
@@ -225,14 +225,14 @@ def _create_clients(
|
|
|
225
225
|
infer_protocol=yolox_protocol,
|
|
226
226
|
)
|
|
227
227
|
|
|
228
|
-
|
|
229
|
-
endpoints=
|
|
230
|
-
model_interface=
|
|
228
|
+
ocr_client = create_inference_client(
|
|
229
|
+
endpoints=ocr_endpoints,
|
|
230
|
+
model_interface=ocr_model_interface,
|
|
231
231
|
auth_token=auth_token,
|
|
232
|
-
infer_protocol=
|
|
232
|
+
infer_protocol=ocr_protocol,
|
|
233
233
|
)
|
|
234
234
|
|
|
235
|
-
return yolox_client,
|
|
235
|
+
return yolox_client, ocr_client
|
|
236
236
|
|
|
237
237
|
|
|
238
238
|
def extract_chart_data_from_image_internal(
|
|
@@ -275,14 +275,18 @@ def extract_chart_data_from_image_internal(
|
|
|
275
275
|
return df_extraction_ledger, execution_trace_log
|
|
276
276
|
|
|
277
277
|
endpoint_config = extraction_config.endpoint_config
|
|
278
|
-
yolox_client,
|
|
278
|
+
yolox_client, ocr_client = _create_clients(
|
|
279
279
|
endpoint_config.yolox_endpoints,
|
|
280
280
|
endpoint_config.yolox_infer_protocol,
|
|
281
|
-
endpoint_config.
|
|
282
|
-
endpoint_config.
|
|
281
|
+
endpoint_config.ocr_endpoints,
|
|
282
|
+
endpoint_config.ocr_infer_protocol,
|
|
283
283
|
endpoint_config.auth_token,
|
|
284
284
|
)
|
|
285
285
|
|
|
286
|
+
# Get the grpc endpoint to determine the model if needed
|
|
287
|
+
ocr_grpc_endpoint = endpoint_config.ocr_endpoints[0]
|
|
288
|
+
ocr_model_name = get_ocr_model_name(ocr_grpc_endpoint)
|
|
289
|
+
|
|
286
290
|
try:
|
|
287
291
|
# 1) Identify rows that meet criteria in a single pass
|
|
288
292
|
# - metadata exists
|
|
@@ -323,7 +327,8 @@ def extract_chart_data_from_image_internal(
|
|
|
323
327
|
bulk_results = _update_chart_metadata(
|
|
324
328
|
base64_images=base64_images,
|
|
325
329
|
yolox_client=yolox_client,
|
|
326
|
-
|
|
330
|
+
ocr_client=ocr_client,
|
|
331
|
+
ocr_model_name=ocr_model_name,
|
|
327
332
|
worker_pool_size=endpoint_config.workers_per_progress_engine,
|
|
328
333
|
trace_info=execution_trace_log,
|
|
329
334
|
)
|
|
@@ -344,8 +349,8 @@ def extract_chart_data_from_image_internal(
|
|
|
344
349
|
|
|
345
350
|
finally:
|
|
346
351
|
try:
|
|
347
|
-
if
|
|
348
|
-
|
|
352
|
+
if ocr_client is not None:
|
|
353
|
+
ocr_client.close()
|
|
349
354
|
if yolox_client is not None:
|
|
350
355
|
yolox_client.close()
|
|
351
356
|
|
|
@@ -33,7 +33,6 @@ from PIL import Image
|
|
|
33
33
|
from nv_ingest_api.internal.enums.common import AccessLevelEnum
|
|
34
34
|
from nv_ingest_api.internal.primitives.nim.model_interface.yolox import (
|
|
35
35
|
YoloxPageElementsModelInterface,
|
|
36
|
-
get_yolox_model_name,
|
|
37
36
|
)
|
|
38
37
|
from nv_ingest_api.internal.schemas.extract.extract_image_schema import ImageConfigSchema
|
|
39
38
|
from nv_ingest_api.util.image_processing.transforms import crop_image, numpy_to_base64
|
|
@@ -202,11 +201,8 @@ def extract_page_elements_from_images(
|
|
|
202
201
|
|
|
203
202
|
# Obtain yolox_version
|
|
204
203
|
# Assuming that the http endpoint is at index 1
|
|
205
|
-
yolox_http_endpoint = config.yolox_endpoints[1]
|
|
206
|
-
yolox_model_name = get_yolox_model_name(yolox_http_endpoint)
|
|
207
|
-
|
|
208
204
|
try:
|
|
209
|
-
model_interface = YoloxPageElementsModelInterface(
|
|
205
|
+
model_interface = YoloxPageElementsModelInterface()
|
|
210
206
|
yolox_client = create_inference_client(
|
|
211
207
|
config.yolox_endpoints,
|
|
212
208
|
model_interface,
|
|
@@ -220,8 +216,11 @@ def extract_page_elements_from_images(
|
|
|
220
216
|
# Perform inference in a single call. The NimClient handles batching internally.
|
|
221
217
|
inference_results = yolox_client.infer(
|
|
222
218
|
data,
|
|
223
|
-
model_name="
|
|
219
|
+
model_name="yolox_ensemble",
|
|
224
220
|
max_batch_size=YOLOX_MAX_BATCH_SIZE,
|
|
221
|
+
input_names=["INPUT_IMAGES", "THRESHOLDS"],
|
|
222
|
+
dtypes=["BYTES", "FP32"],
|
|
223
|
+
output_names=["OUTPUT"],
|
|
225
224
|
trace_info=trace_info,
|
|
226
225
|
stage_name="pdf_extraction",
|
|
227
226
|
)
|
|
@@ -12,12 +12,14 @@ from typing import Tuple
|
|
|
12
12
|
import pandas as pd
|
|
13
13
|
|
|
14
14
|
from nv_ingest_api.internal.primitives.nim import NimClient
|
|
15
|
-
from nv_ingest_api.internal.primitives.nim.model_interface.
|
|
15
|
+
from nv_ingest_api.internal.primitives.nim.model_interface.ocr import OCRModelInterface
|
|
16
|
+
from nv_ingest_api.internal.primitives.nim.model_interface.ocr import get_ocr_model_name
|
|
16
17
|
from nv_ingest_api.internal.schemas.extract.extract_infographic_schema import (
|
|
17
18
|
InfographicExtractorSchema,
|
|
18
19
|
)
|
|
19
20
|
from nv_ingest_api.util.image_processing.transforms import base64_to_numpy
|
|
20
21
|
from nv_ingest_api.util.nim import create_inference_client
|
|
22
|
+
from nv_ingest_api.util.image_processing.table_and_chart import reorder_boxes
|
|
21
23
|
|
|
22
24
|
logger = logging.getLogger(__name__)
|
|
23
25
|
|
|
@@ -61,22 +63,23 @@ def _filter_infographic_images(
|
|
|
61
63
|
|
|
62
64
|
def _update_infographic_metadata(
|
|
63
65
|
base64_images: List[str],
|
|
64
|
-
|
|
66
|
+
ocr_client: NimClient,
|
|
67
|
+
ocr_model_name: str,
|
|
65
68
|
worker_pool_size: int = 8, # Not currently used
|
|
66
69
|
trace_info: Optional[Dict] = None,
|
|
67
70
|
) -> List[Tuple[str, Optional[Any], Optional[Any]]]:
|
|
68
71
|
"""
|
|
69
|
-
Filters base64-encoded images and uses
|
|
72
|
+
Filters base64-encoded images and uses OCR to extract infographic data.
|
|
70
73
|
|
|
71
|
-
For each image that meets the minimum size, calls
|
|
74
|
+
For each image that meets the minimum size, calls ocr_client.infer to obtain
|
|
72
75
|
(text_predictions, bounding_boxes). Invalid images are marked as skipped.
|
|
73
76
|
|
|
74
77
|
Parameters
|
|
75
78
|
----------
|
|
76
79
|
base64_images : List[str]
|
|
77
80
|
List of base64-encoded images.
|
|
78
|
-
|
|
79
|
-
Client instance for
|
|
81
|
+
ocr_client : NimClient
|
|
82
|
+
Client instance for OCR inference.
|
|
80
83
|
worker_pool_size : int, optional
|
|
81
84
|
Worker pool size (currently not used), by default 8.
|
|
82
85
|
trace_info : Optional[Dict], optional
|
|
@@ -88,54 +91,70 @@ def _update_infographic_metadata(
|
|
|
88
91
|
List of tuples in the same order as base64_images, where each tuple contains:
|
|
89
92
|
(base64_image, text_predictions, bounding_boxes).
|
|
90
93
|
"""
|
|
91
|
-
logger.debug(f"Running infographic extraction using protocol {
|
|
94
|
+
logger.debug(f"Running infographic extraction using protocol {ocr_client.protocol}")
|
|
92
95
|
|
|
93
96
|
valid_images, valid_indices, results = _filter_infographic_images(base64_images)
|
|
94
|
-
|
|
97
|
+
data_ocr = {"base64_images": valid_images}
|
|
95
98
|
|
|
96
99
|
# worker_pool_size is not used in current implementation.
|
|
97
100
|
_ = worker_pool_size
|
|
98
101
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
infer_kwargs = dict(
|
|
103
|
+
stage_name="infographic_extraction",
|
|
104
|
+
max_batch_size=1 if ocr_client.protocol == "grpc" else 2,
|
|
105
|
+
trace_info=trace_info,
|
|
106
|
+
)
|
|
107
|
+
if ocr_model_name == "paddle":
|
|
108
|
+
infer_kwargs.update(
|
|
102
109
|
model_name="paddle",
|
|
103
|
-
stage_name="infographic_extraction",
|
|
104
|
-
max_batch_size=1 if paddle_client.protocol == "grpc" else 2,
|
|
105
|
-
trace_info=trace_info,
|
|
106
110
|
)
|
|
111
|
+
else:
|
|
112
|
+
infer_kwargs.update(
|
|
113
|
+
model_name="scene_text",
|
|
114
|
+
input_names=["input", "merge_levels"],
|
|
115
|
+
dtypes=["FP32", "BYTES"],
|
|
116
|
+
merge_level="paragraph",
|
|
117
|
+
)
|
|
118
|
+
try:
|
|
119
|
+
ocr_results = ocr_client.infer(data_ocr, **infer_kwargs)
|
|
107
120
|
except Exception as e:
|
|
108
|
-
logger.error(f"Error calling
|
|
121
|
+
logger.error(f"Error calling ocr_client.infer: {e}", exc_info=True)
|
|
109
122
|
raise
|
|
110
123
|
|
|
111
|
-
if len(
|
|
112
|
-
raise ValueError(f"Expected {len(valid_images)}
|
|
124
|
+
if len(ocr_results) != len(valid_images):
|
|
125
|
+
raise ValueError(f"Expected {len(valid_images)} ocr results, got {len(ocr_results)}")
|
|
113
126
|
|
|
114
|
-
for idx,
|
|
127
|
+
for idx, ocr_res in enumerate(ocr_results):
|
|
115
128
|
original_index = valid_indices[idx]
|
|
116
|
-
|
|
117
|
-
|
|
129
|
+
|
|
130
|
+
if ocr_model_name == "paddle":
|
|
131
|
+
logger.debug(f"OCR results for image {base64_images[original_index]}: {ocr_res}")
|
|
132
|
+
else:
|
|
133
|
+
# Each ocr_res is expected to be a tuple (text_predictions, bounding_boxes, conf_scores).
|
|
134
|
+
ocr_res = reorder_boxes(*ocr_res)
|
|
135
|
+
|
|
136
|
+
results[original_index] = (base64_images[original_index], ocr_res[0], ocr_res[1])
|
|
118
137
|
|
|
119
138
|
return results
|
|
120
139
|
|
|
121
140
|
|
|
122
141
|
def _create_clients(
|
|
123
|
-
|
|
124
|
-
|
|
142
|
+
ocr_endpoints: Tuple[str, str],
|
|
143
|
+
ocr_protocol: str,
|
|
125
144
|
auth_token: str,
|
|
126
145
|
) -> NimClient:
|
|
127
|
-
|
|
146
|
+
ocr_model_interface = OCRModelInterface()
|
|
128
147
|
|
|
129
|
-
logger.debug(f"Inference protocols:
|
|
148
|
+
logger.debug(f"Inference protocols: ocr={ocr_protocol}")
|
|
130
149
|
|
|
131
|
-
|
|
132
|
-
endpoints=
|
|
133
|
-
model_interface=
|
|
150
|
+
ocr_client = create_inference_client(
|
|
151
|
+
endpoints=ocr_endpoints,
|
|
152
|
+
model_interface=ocr_model_interface,
|
|
134
153
|
auth_token=auth_token,
|
|
135
|
-
infer_protocol=
|
|
154
|
+
infer_protocol=ocr_protocol,
|
|
136
155
|
)
|
|
137
156
|
|
|
138
|
-
return
|
|
157
|
+
return ocr_client
|
|
139
158
|
|
|
140
159
|
|
|
141
160
|
def _meets_infographic_criteria(row: pd.Series) -> bool:
|
|
@@ -209,12 +228,16 @@ def extract_infographic_data_from_image_internal(
|
|
|
209
228
|
return df_extraction_ledger, execution_trace_log
|
|
210
229
|
|
|
211
230
|
endpoint_config = extraction_config.endpoint_config
|
|
212
|
-
|
|
213
|
-
endpoint_config.
|
|
214
|
-
endpoint_config.
|
|
231
|
+
ocr_client = _create_clients(
|
|
232
|
+
endpoint_config.ocr_endpoints,
|
|
233
|
+
endpoint_config.ocr_infer_protocol,
|
|
215
234
|
endpoint_config.auth_token,
|
|
216
235
|
)
|
|
217
236
|
|
|
237
|
+
# Get the grpc endpoint to determine the model if needed
|
|
238
|
+
ocr_grpc_endpoint = endpoint_config.ocr_endpoints[0]
|
|
239
|
+
ocr_model_name = get_ocr_model_name(ocr_grpc_endpoint)
|
|
240
|
+
|
|
218
241
|
try:
|
|
219
242
|
# Identify rows that meet the infographic criteria.
|
|
220
243
|
mask = df_extraction_ledger.apply(_meets_infographic_criteria, axis=1)
|
|
@@ -230,14 +253,15 @@ def extract_infographic_data_from_image_internal(
|
|
|
230
253
|
# Call bulk update to extract infographic data.
|
|
231
254
|
bulk_results = _update_infographic_metadata(
|
|
232
255
|
base64_images=base64_images,
|
|
233
|
-
|
|
256
|
+
ocr_client=ocr_client,
|
|
257
|
+
ocr_model_name=ocr_model_name,
|
|
234
258
|
worker_pool_size=endpoint_config.workers_per_progress_engine,
|
|
235
259
|
trace_info=execution_trace_log,
|
|
236
260
|
)
|
|
237
261
|
|
|
238
262
|
# Write the extracted results back into the DataFrame.
|
|
239
263
|
for result_idx, df_idx in enumerate(valid_indices):
|
|
240
|
-
# Unpack result: (base64_image,
|
|
264
|
+
# Unpack result: (base64_image, ocr_bounding_boxes, ocr_text_predictions)
|
|
241
265
|
_, _, text_predictions = bulk_results[result_idx]
|
|
242
266
|
table_content = " ".join(text_predictions) if text_predictions else None
|
|
243
267
|
df_extraction_ledger.at[df_idx, "metadata"]["table_metadata"]["table_content"] = table_content
|
|
@@ -250,4 +274,4 @@ def extract_infographic_data_from_image_internal(
|
|
|
250
274
|
raise
|
|
251
275
|
|
|
252
276
|
finally:
|
|
253
|
-
|
|
277
|
+
ocr_client.close()
|