nv-ingest-api 2025.9.22.dev20250922__py3-none-any.whl → 2025.9.23.dev20250923__py3-none-any.whl

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.

@@ -2,10 +2,14 @@
2
2
  # All rights reserved.
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
+ import hashlib
6
+ import json
5
7
  import logging
6
8
  import threading
7
9
  import time
8
- from concurrent.futures import ThreadPoolExecutor, as_completed
10
+ import queue
11
+ from collections import namedtuple
12
+ from concurrent.futures import Future, ThreadPoolExecutor, as_completed
9
13
  from typing import Any
10
14
  from typing import Optional
11
15
  from typing import Tuple, Union
@@ -17,8 +21,12 @@ import tritonclient.grpc as grpcclient
17
21
  from nv_ingest_api.internal.primitives.tracing.tagging import traceable_func
18
22
  from nv_ingest_api.util.string_processing import generate_url
19
23
 
24
+
20
25
  logger = logging.getLogger(__name__)
21
26
 
27
+ # A simple structure to hold a request's data and its Future for the result
28
+ InferenceRequest = namedtuple("InferenceRequest", ["data", "future", "model_name", "dims", "kwargs"])
29
+
22
30
 
23
31
  class NimClient:
24
32
  """
@@ -34,6 +42,9 @@ class NimClient:
34
42
  timeout: float = 120.0,
35
43
  max_retries: int = 5,
36
44
  max_429_retries: int = 5,
45
+ enable_dynamic_batching: bool = False,
46
+ dynamic_batch_timeout: float = 0.1, # 100 milliseconds
47
+ dynamic_batch_memory_budget_mb: Optional[float] = None,
37
48
  ):
38
49
  """
39
50
  Initialize the NimClient with the specified model interface, protocol, and server endpoints.
@@ -60,7 +71,6 @@ class NimClient:
60
71
  ValueError
61
72
  If an invalid protocol is specified or if required endpoints are missing.
62
73
  """
63
-
64
74
  self.client = None
65
75
  self.model_interface = model_interface
66
76
  self.protocol = protocol.lower()
@@ -88,12 +98,32 @@ class NimClient:
88
98
  else:
89
99
  raise ValueError("Invalid protocol specified. Must be 'grpc' or 'http'.")
90
100
 
101
+ self.dynamic_batching_enabled = enable_dynamic_batching
102
+ if self.dynamic_batching_enabled:
103
+ self._batch_timeout = dynamic_batch_timeout
104
+ if dynamic_batch_memory_budget_mb is not None:
105
+ self._batch_memory_budget_bytes = dynamic_batch_memory_budget_mb * 1024 * 1024
106
+ else:
107
+ self._batch_memory_budget_bytes = None
108
+
109
+ self._request_queue = queue.Queue()
110
+ self._stop_event = threading.Event()
111
+ self._batcher_thread = threading.Thread(target=self._batcher_loop, daemon=True)
112
+
113
+ def start(self):
114
+ """Starts the dynamic batching worker thread if enabled."""
115
+ if self.dynamic_batching_enabled and not self._batcher_thread.is_alive():
116
+ self._batcher_thread.start()
117
+
91
118
  def _fetch_max_batch_size(self, model_name, model_version: str = "") -> int:
92
119
  """Fetch the maximum batch size from the Triton model configuration in a thread-safe manner."""
93
120
 
94
121
  if model_name == "yolox_ensemble":
95
122
  model_name = "yolox"
96
123
 
124
+ if model_name == "scene_text_ensemble":
125
+ model_name = "scene_text_pre"
126
+
97
127
  if model_name in self._max_batch_sizes:
98
128
  return self._max_batch_sizes[model_name]
99
129
 
@@ -102,13 +132,12 @@ class NimClient:
102
132
  if model_name in self._max_batch_sizes:
103
133
  return self._max_batch_sizes[model_name]
104
134
 
105
- if not self._grpc_endpoint:
135
+ if not self._grpc_endpoint or not self.client:
106
136
  self._max_batch_sizes[model_name] = 1
107
137
  return 1
108
138
 
109
139
  try:
110
- client = self.client if self.client else grpcclient.InferenceServerClient(url=self._grpc_endpoint)
111
- model_config = client.get_model_config(model_name=model_name, model_version=model_version)
140
+ model_config = self.client.get_model_config(model_name=model_name, model_version=model_version)
112
141
  self._max_batch_sizes[model_name] = model_config.config.max_batch_size
113
142
  logger.debug(f"Max batch size for model '{model_name}': {self._max_batch_sizes[model_name]}")
114
143
  except Exception as e:
@@ -176,17 +205,40 @@ class NimClient:
176
205
  Any
177
206
  The processed inference results, coalesced in the same order as the input images.
178
207
  """
179
- try:
180
- # 1. Retrieve or default to the model's maximum batch size.
181
- batch_size = self._fetch_max_batch_size(model_name)
182
- max_requested_batch_size = kwargs.pop("max_batch_size", batch_size)
183
- force_requested_batch_size = kwargs.pop("force_max_batch_size", False)
184
- max_batch_size = (
185
- max(1, min(batch_size, max_requested_batch_size))
186
- if not force_requested_batch_size
187
- else max_requested_batch_size
188
- )
208
+ # 1. Retrieve or default to the model's maximum batch size.
209
+ batch_size = self._fetch_max_batch_size(model_name)
210
+ max_requested_batch_size = kwargs.pop("max_batch_size", batch_size)
211
+ force_requested_batch_size = kwargs.pop("force_max_batch_size", False)
212
+ max_batch_size = (
213
+ max(1, min(batch_size, max_requested_batch_size))
214
+ if not force_requested_batch_size
215
+ else max_requested_batch_size
216
+ )
217
+ self._batch_size = max_batch_size
218
+
219
+ if self.dynamic_batching_enabled:
220
+ # DYNAMIC BATCHING PATH
221
+ try:
222
+ data = self.model_interface.prepare_data_for_inference(data)
223
+
224
+ futures = []
225
+ for base64_image, image_array in zip(data["base64_images"], data["images"]):
226
+ dims = image_array.shape[:2]
227
+ futures.append(self.submit(base64_image, model_name, dims, **kwargs))
228
+
229
+ results = [future.result() for future in futures]
230
+
231
+ return results
232
+
233
+ except Exception as err:
234
+ error_str = (
235
+ f"Error during synchronous infer with dynamic batching [{self.model_interface.name()}]: {err}"
236
+ )
237
+ logger.error(error_str)
238
+ raise RuntimeError(error_str) from err
189
239
 
240
+ # OFFLINE BATCHING PATH
241
+ try:
190
242
  # 2. Prepare data for inference.
191
243
  data = self.model_interface.prepare_data_for_inference(data)
192
244
 
@@ -390,6 +442,209 @@ class NimClient:
390
442
  logger.error(f"Failed to get a successful response after {self.max_retries} retries.")
391
443
  raise Exception(f"Failed to get a successful response after {self.max_retries} retries.")
392
444
 
445
+ def _batcher_loop(self):
446
+ """The main loop for the background thread to form and process batches."""
447
+ while not self._stop_event.is_set():
448
+ requests_batch = []
449
+ try:
450
+ first_req = self._request_queue.get(timeout=self._batch_timeout)
451
+ if first_req is None:
452
+ continue
453
+ requests_batch.append(first_req)
454
+
455
+ start_time = time.monotonic()
456
+
457
+ while len(requests_batch) < self._batch_size:
458
+ if (time.monotonic() - start_time) >= self._batch_timeout:
459
+ break
460
+
461
+ if self._request_queue.empty():
462
+ break
463
+
464
+ next_req_peek = self._request_queue.queue[0]
465
+ if next_req_peek is None:
466
+ break
467
+
468
+ if self._batch_memory_budget_bytes:
469
+ if not self.model_interface.does_item_fit_in_batch(
470
+ requests_batch,
471
+ next_req_peek,
472
+ self._batch_memory_budget_bytes,
473
+ ):
474
+ break
475
+
476
+ try:
477
+ next_req = self._request_queue.get_nowait()
478
+ if next_req is None:
479
+ break
480
+ requests_batch.append(next_req)
481
+ except queue.Empty:
482
+ break
483
+
484
+ except queue.Empty:
485
+ continue
486
+
487
+ if requests_batch:
488
+ self._process_dynamic_batch(requests_batch)
489
+
490
+ def _process_dynamic_batch(self, requests: list[InferenceRequest]):
491
+ """Coalesces, infers, and distributes results for a dynamic batch."""
492
+ if not requests:
493
+ return
494
+
495
+ first_req = requests[0]
496
+ model_name = first_req.model_name
497
+ kwargs = first_req.kwargs
498
+
499
+ try:
500
+ # 1. Coalesce individual data items into a single batch input
501
+ batch_input, batch_data = self.model_interface.coalesce_requests_to_batch(
502
+ [req.data for req in requests],
503
+ [req.dims for req in requests],
504
+ protocol=self.protocol,
505
+ model_name=model_name,
506
+ **kwargs,
507
+ )
508
+
509
+ # 2. Perform inference using the existing _process_batch logic
510
+ parsed_output, _ = self._process_batch(batch_input, batch_data=batch_data, model_name=model_name, **kwargs)
511
+
512
+ # 3. Process the batched output to get final results
513
+ all_results = self.model_interface.process_inference_results(
514
+ parsed_output,
515
+ original_image_shapes=batch_data.get("original_image_shapes"),
516
+ protocol=self.protocol,
517
+ **kwargs,
518
+ )
519
+
520
+ # 4. Distribute the individual results back to the correct Future
521
+ if len(all_results) != len(requests):
522
+ raise ValueError("Mismatch between result count and request count.")
523
+
524
+ for i, req in enumerate(requests):
525
+ req.future.set_result(all_results[i])
526
+
527
+ except Exception as e:
528
+ # If anything fails, propagate the exception to all futures in the batch
529
+ logger.error(f"Error processing dynamic batch: {e}")
530
+ for req in requests:
531
+ req.future.set_exception(e)
532
+
533
+ def submit(self, data: Any, model_name: str, dims: Tuple[int, int], **kwargs) -> Future:
534
+ """
535
+ Submits a single inference request to the dynamic batcher.
536
+
537
+ This method is non-blocking and returns a Future object that will
538
+ eventually contain the inference result.
539
+
540
+ Parameters
541
+ ----------
542
+ data : Any
543
+ The single data item for inference (e.g., one image, one text prompt).
544
+
545
+ Returns
546
+ -------
547
+ concurrent.futures.Future
548
+ A future that will be fulfilled with the inference result.
549
+ """
550
+ if not self.dynamic_batching_enabled:
551
+ raise RuntimeError(
552
+ "Dynamic batching is not enabled. Please initialize NimClient with " "enable_dynamic_batching=True."
553
+ )
554
+
555
+ future = Future()
556
+ request = InferenceRequest(data=data, future=future, model_name=model_name, dims=dims, kwargs=kwargs)
557
+ self._request_queue.put(request)
558
+ return future
559
+
393
560
  def close(self):
394
- if self.protocol == "grpc" and hasattr(self.client, "close"):
561
+ """Stops the dynamic batching worker and closes client connections."""
562
+
563
+ if self.dynamic_batching_enabled:
564
+ self._stop_event.set()
565
+ # Unblock the queue in case the thread is waiting on get()
566
+ self._request_queue.put(None)
567
+ if self._batcher_thread.is_alive():
568
+ self._batcher_thread.join()
569
+
570
+ if self.client:
395
571
  self.client.close()
572
+
573
+
574
+ class NimClientManager:
575
+ """
576
+ A thread-safe, singleton manager for creating and sharing NimClient instances.
577
+
578
+ This manager ensures that only one NimClient is created per unique configuration.
579
+ """
580
+
581
+ _instance = None
582
+ _lock = threading.Lock()
583
+
584
+ def __new__(cls):
585
+ # Singleton pattern
586
+ if cls._instance is None:
587
+ with cls._lock:
588
+ if cls._instance is None:
589
+ cls._instance = super(NimClientManager, cls).__new__(cls)
590
+ return cls._instance
591
+
592
+ def __init__(self):
593
+ if not hasattr(self, "_initialized"):
594
+ with self._lock:
595
+ if not hasattr(self, "_initialized"):
596
+ self._clients = {} # Key: config_hash, Value: NimClient instance
597
+ self._client_lock = threading.Lock()
598
+ self._initialized = True
599
+
600
+ def _generate_config_key(self, **kwargs) -> str:
601
+ """Creates a stable, hashable key from client configuration."""
602
+ sorted_config = sorted(kwargs.items())
603
+ config_str = json.dumps(sorted_config)
604
+ return hashlib.md5(config_str.encode("utf-8")).hexdigest()
605
+
606
+ def get_client(self, model_interface, **kwargs) -> "NimClient":
607
+ """
608
+ Gets or creates a NimClient for the given configuration.
609
+ """
610
+ config_key = self._generate_config_key(model_interface_name=model_interface.name(), **kwargs)
611
+
612
+ if config_key in self._clients:
613
+ return self._clients[config_key]
614
+
615
+ with self._client_lock:
616
+ if config_key in self._clients:
617
+ return self._clients[config_key]
618
+
619
+ logger.debug(f"Creating new NimClient for config hash: {config_key}")
620
+
621
+ new_client = NimClient(model_interface=model_interface, **kwargs)
622
+
623
+ if new_client.dynamic_batching_enabled:
624
+ new_client.start()
625
+
626
+ self._clients[config_key] = new_client
627
+
628
+ return new_client
629
+
630
+ def shutdown(self):
631
+ """
632
+ Gracefully closes all managed NimClient instances.
633
+ This is called automatically on application exit by `atexit`.
634
+ """
635
+ logger.debug(f"Shutting down NimClientManager and {len(self._clients)} client(s)...")
636
+ with self._client_lock:
637
+ for config_key, client in self._clients.items():
638
+ logger.debug(f"Closing client for config: {config_key}")
639
+ try:
640
+ client.close()
641
+ except Exception as e:
642
+ logger.error(f"Error closing client for config {config_key}: {e}")
643
+ self._clients.clear()
644
+ logger.debug("NimClientManager shutdown complete.")
645
+
646
+
647
+ # A global helper function to make access even easier
648
+ def get_nim_client_manager(*args, **kwargs) -> NimClientManager:
649
+ """Returns the singleton instance of the NimClientManager."""
650
+ return NimClientManager(*args, **kwargs)
@@ -3,7 +3,10 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
5
  import logging
6
+ from typing import Any
7
+ from typing import Dict
6
8
  from typing import Optional
9
+ from typing import Tuple
7
10
 
8
11
 
9
12
  logger = logging.getLogger(__name__)
@@ -79,3 +82,45 @@ class ModelInterface:
79
82
  The name of the model interface.
80
83
  """
81
84
  raise NotImplementedError("Subclasses should implement this method")
85
+
86
+ def coalesce_requests_to_batch(self, requests, protocol: str, **kwargs) -> Tuple[Any, Dict[str, Any]]:
87
+ """
88
+ Takes a list of InferenceRequest objects and combines them into a single
89
+ formatted batch ready for inference.
90
+
91
+ THIS METHOD IS REQUIRED FOR DYNAMIC BATCHING SUPPORT.
92
+
93
+ Parameters
94
+ ----------
95
+ requests : List[InferenceRequest]
96
+ A list of InferenceRequest namedtuples collected for the batch.
97
+ Each tuple contains the data, dimensions, and other context for a single item.
98
+ protocol : str
99
+ The inference protocol, either "grpc" or "http".
100
+ **kwargs : Any
101
+ Additional keyword arguments passed from the original request.
102
+
103
+ Returns
104
+ -------
105
+ Tuple[Any, Dict[str, Any]]
106
+ A tuple containing the single formatted batch and its scratch-pad data.
107
+ """
108
+ raise NotImplementedError(
109
+ f"{self.__class__.__name__} does not support dynamic batching "
110
+ "because `coalesce_requests_to_batch` is not implemented."
111
+ )
112
+
113
+ def does_item_fit_in_batch(self, current_batch, next_request, memory_budget_bytes: int) -> bool:
114
+ """
115
+ Checks if adding another request to the current batch would exceed the memory budget.
116
+
117
+ This is a model-specific calculation. The default implementation always
118
+ returns True, effectively ignoring the memory budget. Interfaces for models
119
+ that require memory management (like padded image models) must override this.
120
+
121
+ Returns
122
+ -------
123
+ bool
124
+ True if the item fits within the budget, False otherwise.
125
+ """
126
+ return True
@@ -4,7 +4,8 @@
4
4
 
5
5
  from typing import Tuple, Optional
6
6
 
7
- from nv_ingest_api.internal.primitives.nim.nim_client import NimClient
7
+ from nv_ingest_api.internal.primitives.nim.nim_client import NimClientManager
8
+ from nv_ingest_api.internal.primitives.nim.nim_client import get_nim_client_manager
8
9
  from nv_ingest_api.internal.primitives.nim.nim_model_interface import ModelInterface
9
10
 
10
11
  __all__ = ["create_inference_client"]
@@ -17,9 +18,10 @@ def create_inference_client(
17
18
  infer_protocol: Optional[str] = None,
18
19
  timeout: float = 120.0,
19
20
  max_retries: int = 5,
20
- ) -> NimClient:
21
+ **kwargs,
22
+ ) -> NimClientManager:
21
23
  """
22
- Create a NimClient for interfacing with a model inference server.
24
+ Create a NimClientManager for interfacing with a model inference server.
23
25
 
24
26
  Parameters
25
27
  ----------
@@ -34,8 +36,8 @@ def create_inference_client(
34
36
 
35
37
  Returns
36
38
  -------
37
- NimClient
38
- The initialized NimClient.
39
+ NimClientManager
40
+ The initialized NimClientManager.
39
41
 
40
42
  Raises
41
43
  ------
@@ -53,4 +55,15 @@ def create_inference_client(
53
55
  if infer_protocol not in ["grpc", "http"]:
54
56
  raise ValueError("Invalid infer_protocol specified. Must be 'grpc' or 'http'.")
55
57
 
56
- return NimClient(model_interface, infer_protocol, endpoints, auth_token, timeout, max_retries)
58
+ manager = get_nim_client_manager()
59
+ client = manager.get_client(
60
+ model_interface=model_interface,
61
+ protocol=infer_protocol,
62
+ endpoints=endpoints,
63
+ auth_token=auth_token,
64
+ timeout=timeout,
65
+ max_retries=max_retries,
66
+ **kwargs,
67
+ )
68
+
69
+ return client
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nv-ingest-api
3
- Version: 2025.9.22.dev20250922
3
+ Version: 2025.9.23.dev20250923
4
4
  Summary: Python module with core document ingestion functions.
5
5
  Author-email: Jeremy Dyer <jdyer@nvidia.com>
6
6
  License: Apache License
@@ -20,19 +20,19 @@ nv_ingest_api/internal/extract/docx/engines/docxreader_helpers/docxreader.py,sha
20
20
  nv_ingest_api/internal/extract/html/__init__.py,sha256=wQSlVx3T14ZgQAt-EPzEczQusXVW0W8yynnUaFFGE3s,143
21
21
  nv_ingest_api/internal/extract/html/html_extractor.py,sha256=I9oWfj6_As4898GDDh0zsSuKxO3lBsvyYzhvUotjzJI,3282
22
22
  nv_ingest_api/internal/extract/image/__init__.py,sha256=wQSlVx3T14ZgQAt-EPzEczQusXVW0W8yynnUaFFGE3s,143
23
- nv_ingest_api/internal/extract/image/chart_extractor.py,sha256=HTu0mOIYMpK5JAAiyvlIHgUtmjQV44Gv8dE5hYIqeQE,13633
23
+ nv_ingest_api/internal/extract/image/chart_extractor.py,sha256=Pojiu7R1BT8tUUzD5DsF-dDEwakz1ZfUrL_agalUsNc,13591
24
24
  nv_ingest_api/internal/extract/image/image_extractor.py,sha256=gBKjlx28hA_e-dupatu46YQgOHJ0DLpAWxREiLaZLyo,9039
25
- nv_ingest_api/internal/extract/image/infographic_extractor.py,sha256=G5sRnyJ-8ToBbD0_7W6Vemq4a5SBNLtzhZKpuR26mlU,10104
26
- nv_ingest_api/internal/extract/image/table_extractor.py,sha256=yjSehCTV43a35I_JrVNkgi7yV6RTAEvTeB3kGtM9ZTs,14196
25
+ nv_ingest_api/internal/extract/image/infographic_extractor.py,sha256=gP-WiBIHruDmNFchq4BbVAci3XStMtyeN99M8dLm1j4,10225
26
+ nv_ingest_api/internal/extract/image/table_extractor.py,sha256=T80-Smkf54Y5OkSaOquXpcoLbAf5uMnV-LOsBgD0L7E,14440
27
27
  nv_ingest_api/internal/extract/image/image_helpers/__init__.py,sha256=wQSlVx3T14ZgQAt-EPzEczQusXVW0W8yynnUaFFGE3s,143
28
- nv_ingest_api/internal/extract/image/image_helpers/common.py,sha256=80jRhGzisHvQ9Ky3MKUMM7soKUmvZ5LqRVzwNYjgdPY,14988
28
+ nv_ingest_api/internal/extract/image/image_helpers/common.py,sha256=VhqjsBqvUz-2y92t6iryVERTuRfcGUdTHOOScYr8GLo,14916
29
29
  nv_ingest_api/internal/extract/pdf/__init__.py,sha256=wQSlVx3T14ZgQAt-EPzEczQusXVW0W8yynnUaFFGE3s,143
30
30
  nv_ingest_api/internal/extract/pdf/pdf_extractor.py,sha256=CxtWaD6mql9MEqSdk2CfSQ9T-Bn87beBkCOuGGjxGt8,2934
31
31
  nv_ingest_api/internal/extract/pdf/engines/__init__.py,sha256=u4GnAZmDKRl0RwYGIRiozIRw70Kybw3A72-lcKFeoTI,582
32
32
  nv_ingest_api/internal/extract/pdf/engines/adobe.py,sha256=VT0dEqkU-y2uGkaCqxtKYov_Q8R1028UQVBchgMLca4,17466
33
33
  nv_ingest_api/internal/extract/pdf/engines/llama.py,sha256=MwzM-n2tu0FHM0wDe_0mONLlzHrPte7EOTuPtzCh7Zs,8384
34
34
  nv_ingest_api/internal/extract/pdf/engines/nemoretriever.py,sha256=IVbNcH_phMiRSxnkZ04pGfQrPJ-x1zVR3hXyhxv7juc,22977
35
- nv_ingest_api/internal/extract/pdf/engines/pdfium.py,sha256=SKmias2iZmAE6Q8WXxmFEjvLOZy-vXRoaRIPpi7Tuhs,22962
35
+ nv_ingest_api/internal/extract/pdf/engines/pdfium.py,sha256=CCfxcHAS3mED8zD6GKTGNUi02CzBMs7FsSopevhsiyk,22720
36
36
  nv_ingest_api/internal/extract/pdf/engines/tika.py,sha256=6GyR2l6EsgNZl9jnYDXLeKNK9Fj2Mw9y2UWDq-eSkOc,3169
37
37
  nv_ingest_api/internal/extract/pdf/engines/unstructured_io.py,sha256=jrv2B4VZAH4PevAQrFz965qz8UyXq3rViiOTbGLejec,14908
38
38
  nv_ingest_api/internal/extract/pdf/engines/pdf_helpers/__init__.py,sha256=uTPTUTWQsGM1oeTUo49_hzwC5Yy9iEokrnS3z3WvtIo,5988
@@ -48,17 +48,17 @@ nv_ingest_api/internal/mutate/filter.py,sha256=H-hOTBVP-zLpvQr-FoGIJKxkhtj4l_sZ9
48
48
  nv_ingest_api/internal/primitives/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  nv_ingest_api/internal/primitives/control_message_task.py,sha256=nWVB3QsP6p8BKwHThd-SNv_zwJAEA1mKCRharuju1mc,439
50
50
  nv_ingest_api/internal/primitives/ingest_control_message.py,sha256=8rA0UbPDSB3avReAKNxiUa_FCy7fIQpqk6tfmcYUibA,9879
51
- nv_ingest_api/internal/primitives/nim/__init__.py,sha256=i_i_fBR2EcRCh2Y19DF6GM3s_Q0VPgo_thPnhEIJUyg,266
51
+ nv_ingest_api/internal/primitives/nim/__init__.py,sha256=-dFBTHQnMKV0yc5tfSqIT-rkJXKtpcmyUfTPs8TJAi8,339
52
52
  nv_ingest_api/internal/primitives/nim/default_values.py,sha256=W92XjfyeC6uuVxut6J7p00x1kpNsnXIDb97gSVytZJk,380
53
- nv_ingest_api/internal/primitives/nim/nim_client.py,sha256=m8_whtmfXFGSw4-Efu938NKG97nzhygyuHB8Tq-a0Ec,16570
54
- nv_ingest_api/internal/primitives/nim/nim_model_interface.py,sha256=wMEgoi79YQn_4338MVemkeZgM1J-vnz0aZWpvqDhib4,2392
53
+ nv_ingest_api/internal/primitives/nim/nim_client.py,sha256=kQAHWwZ6kjTVYZSfa0qRyIOFcqrhMe8LUygGtgzAly0,26321
54
+ nv_ingest_api/internal/primitives/nim/nim_model_interface.py,sha256=gWhyR33mIgEOYirq53WOk1bRl1SL0C_SVrM4w1-JmKU,4166
55
55
  nv_ingest_api/internal/primitives/nim/model_interface/__init__.py,sha256=wQSlVx3T14ZgQAt-EPzEczQusXVW0W8yynnUaFFGE3s,143
56
56
  nv_ingest_api/internal/primitives/nim/model_interface/cached.py,sha256=b1HX-PY1ExW5V6pXC1ZiHdobeG_BmbPr3rBbVJef13s,11003
57
57
  nv_ingest_api/internal/primitives/nim/model_interface/decorators.py,sha256=qwubkHs4WjnexM6rI0wkjWCsrVNEbA4Wjk2oKL9OYCU,1499
58
58
  nv_ingest_api/internal/primitives/nim/model_interface/deplot.py,sha256=TvKdk6PTuI1WNhRmNNrvygaI_DIutkJkDL-XdtLZQac,10787
59
- nv_ingest_api/internal/primitives/nim/model_interface/helpers.py,sha256=iyGxAr4tG2UZ7LtXXoWO_kF-KsObhPrmZ46Nl0Mi-Ag,11592
59
+ nv_ingest_api/internal/primitives/nim/model_interface/helpers.py,sha256=jqbEbavvr9giODpzsGQSRDu5yZ4YfNfKAQfqUm9yUDI,11698
60
60
  nv_ingest_api/internal/primitives/nim/model_interface/nemoretriever_parse.py,sha256=WysjDZeegclO3mZgVcGOwzWbr8wSI4pWRiYD4iC2EXo,7098
61
- nv_ingest_api/internal/primitives/nim/model_interface/ocr.py,sha256=0Xfuf5_-7LoWnqzZlsJFI53ztneB7Rs-PHZQzDgR0mo,22679
61
+ nv_ingest_api/internal/primitives/nim/model_interface/ocr.py,sha256=QOjKEJaL7Z_aT-luyV4eJSNQX4o-a9-P0CB0ZwSxFk4,29282
62
62
  nv_ingest_api/internal/primitives/nim/model_interface/parakeet.py,sha256=5PqD2JuHY2rwd-6SSB4axr2Dd79vm95sAEkcmI3U7ME,12977
63
63
  nv_ingest_api/internal/primitives/nim/model_interface/text_embedding.py,sha256=lFhppNqrq5X_fzbCWKphvZQMzaJd3gHrkWsyJORzFrU,5010
64
64
  nv_ingest_api/internal/primitives/nim/model_interface/vlm.py,sha256=qJ382PU1ZrIM-SR3cqIhtY_W2rmHec2HIa2aUB2SvaU,6031
@@ -145,7 +145,7 @@ nv_ingest_api/util/metadata/__init__.py,sha256=HIHfzSig66GT0Uk8qsGBm_f13fKYcPtIt
145
145
  nv_ingest_api/util/metadata/aggregators.py,sha256=YYdvJ1E04eGFZKKHUxXoH6mzLg8nor9Smvnv0qzqK5w,15988
146
146
  nv_ingest_api/util/multi_processing/__init__.py,sha256=4fojP8Rp_5Hu1YAkqGylqTyEZ-HBVVEunn5Z9I99swA,242
147
147
  nv_ingest_api/util/multi_processing/mp_pool_singleton.py,sha256=dTfP82DgGPaXEJH3jywTO8rNlLZUniD4FFzwv84_giE,7372
148
- nv_ingest_api/util/nim/__init__.py,sha256=UqbiXFCqjWcjNvoduXd_0gOUOGBT8JvppiYHOmMyneA,1775
148
+ nv_ingest_api/util/nim/__init__.py,sha256=No45pMstom1Jo0EENT6VEFkZn3YmTha7lYaBZU7xtHk,2116
149
149
  nv_ingest_api/util/pdf/__init__.py,sha256=uLsBITo_XfgbwpzqXUm1IYX6XlZrTfx6T1cIhdILwG8,140
150
150
  nv_ingest_api/util/pdf/pdfium.py,sha256=1aPCnPKXHWnncYoMO8HllYjrhODSXIeRBIsSLDevpYs,15667
151
151
  nv_ingest_api/util/schema/__init__.py,sha256=wQSlVx3T14ZgQAt-EPzEczQusXVW0W8yynnUaFFGE3s,143
@@ -162,10 +162,10 @@ nv_ingest_api/util/string_processing/configuration.py,sha256=2HS08msccuPCT0fn_jf
162
162
  nv_ingest_api/util/string_processing/yaml.py,sha256=6SW2O6wbXRhGbhETMbtXjYCZn53HeCNOP6a96AaxlHs,1454
163
163
  nv_ingest_api/util/system/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
164
164
  nv_ingest_api/util/system/hardware_info.py,sha256=1UFM8XE6M3pgQcpbVsCsqDQ7Dj-zzptL-XRE-DEu9UA,27213
165
- nv_ingest_api-2025.9.22.dev20250922.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
165
+ nv_ingest_api-2025.9.23.dev20250923.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
166
166
  udfs/__init__.py,sha256=pXFqPgXIUqHDfj7SAR1Q19tt8KwGv_iMvhHyziz4AYM,205
167
167
  udfs/llm_summarizer_udf.py,sha256=sIMfcH4GRyciTKUtq4dmhd6fZmAp07X32irIC4k7nEI,7316
168
- nv_ingest_api-2025.9.22.dev20250922.dist-info/METADATA,sha256=F7mdGKd1x_YvpyTPjtM19SAaNiI87fLIxN8ebo4DM0s,13947
169
- nv_ingest_api-2025.9.22.dev20250922.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
170
- nv_ingest_api-2025.9.22.dev20250922.dist-info/top_level.txt,sha256=I1lseG9FF0CH93SPx4kFblsxFuv190cfzaas_CLNIiw,19
171
- nv_ingest_api-2025.9.22.dev20250922.dist-info/RECORD,,
168
+ nv_ingest_api-2025.9.23.dev20250923.dist-info/METADATA,sha256=GxHkBLbWifHcUO7FVUS2urfBqa9eo_2ClRT3o61Yc-U,13947
169
+ nv_ingest_api-2025.9.23.dev20250923.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
170
+ nv_ingest_api-2025.9.23.dev20250923.dist-info/top_level.txt,sha256=I1lseG9FF0CH93SPx4kFblsxFuv190cfzaas_CLNIiw,19
171
+ nv_ingest_api-2025.9.23.dev20250923.dist-info/RECORD,,