diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85024ed73b..8490f8a700 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,10 @@ jobs: with: fail-on-severity: low allow-licenses: MIT, Apache-2.0, BSD-3-Clause, 0BSD, 0BSD AND Apache-2.0 AND BSD-3-Clause AND MIT + # ml-dtypes (transitive via optimum-onnx -> onnx) is Apache-2.0 with + # MPL-2.0-licensed Eigen headers; exempt it rather than allowing + # MPL-2.0 globally. + allow-dependencies-licenses: pkg:pypi/ml-dtypes comment-summary-in-pr: on-failure test: diff --git a/docs/analyzer/huggingface_ner_inference.md b/docs/analyzer/huggingface_ner_inference.md new file mode 100644 index 0000000000..fffef66f18 --- /dev/null +++ b/docs/analyzer/huggingface_ner_inference.md @@ -0,0 +1,335 @@ +# HuggingFace NER inference backends + +The `HuggingFaceNerRecognizer` runs a HuggingFace token-classification model +to detect PII. It supports two inference backends, selected by the `backend` +constructor parameter — set it in the recognizer YAML or pass it directly +when constructing the recognizer in Python: + +- `torch` (default) — PyTorch via the `transformers` pipeline. Works on CPU + and NVIDIA GPU (CUDA). +- `ort` — ONNX Runtime via `optimum`. Works on CPU, NVIDIA GPU, AMD GPU, + Intel CPU/iGPU/NPU, and Apple Silicon, by selecting an ONNX Runtime + *execution provider*. + +Any extra keyword arguments (e.g. `file_name`, `subfolder`, `provider`, +`provider_options`, `revision`) — whether passed in Python or as extra +fields in the YAML — are captured into `**model_kwargs` and forwarded to +the underlying loader. You do not need to edit the recognizer to plumb +new knobs. + +The examples below use YAML (the +[recognizer registry configuration](recognizer_registry_provider.md)); +every field shown maps 1:1 to a constructor argument. The Python +equivalent of an ort configuration: + +```python +from presidio_analyzer import AnalyzerEngine +from presidio_analyzer.predefined_recognizers import HuggingFaceNerRecognizer + +recognizer = HuggingFaceNerRecognizer( + model_name="onnx-community/stanford-deidentifier-base-ONNX", + backend="ort", + subfolder="onnx", # forwarded via **model_kwargs + file_name="model_quantized.onnx", # forwarded via **model_kwargs + label_mapping={ + "PATIENT": "PERSON", + "HCW": "PERSON", + "PHONE": "PHONE_NUMBER", + }, + threshold=0.5, +) + +analyzer = AnalyzerEngine() +analyzer.registry.add_recognizer(recognizer) +results = analyzer.analyze(text="Dr. Sarah Chen, 555-123-4567", language="en") +``` + +## Choosing a backend + +| Hardware | Recommended backend | Why | +|----------|---------------------|-----| +| NVIDIA GPU, baseline | `torch` with `device: cuda` | Zero extra install, no model conversion | +| NVIDIA GPU + quantized ONNX | `ort` with `CUDAExecutionProvider` | Runs pre-quantized FP16/INT8 ONNX files that torch can't use directly | +| NVIDIA GPU + high throughput | `ort` with `TensorrtExecutionProvider` | Designed for sustained batch inference; slow first request (engine build) | +| Intel Xeon Scalable (Sapphire Rapids+) | `ort` with `OpenVINOExecutionProvider` | Uses native AVX-512 BF16 / AMX kernels not fully exploited by the default CPU EP | +| Intel iGPU / Arc / NPU | `ort` with `OpenVINOExecutionProvider` (`device_type=GPU` or `NPU`) | Only practical path for Intel accelerators | +| Apple Silicon | `ort` with `CoreMLExecutionProvider`, or CPU | The recognizer's device handling does not support MPS; CoreML EP is the only acceleration path | +| Generic cloud CPU | `torch` with `device: cpu`, or `ort` with default CPU EP | Comparable for FP32; ort additionally runs quantized variants | + +## torch backend + +The default. Uses `transformers.pipeline` directly. Best for "just works" +deployments. + +```yaml +- name: "HF NER (torch)" + type: predefined + class_name: HuggingFaceNerRecognizer + model_name: dslim/bert-base-NER + backend: torch + # device: cuda # omit to let Presidio's device detector decide + aggregation_strategy: simple + threshold: 0.3 + supported_languages: [en] + supported_entities: [PERSON, LOCATION, ORGANIZATION] +``` + +Device selection precedence: + +1. **Explicit `device`** (`cpu` | `cuda` | `cuda:N` | int index) — hard + override; bypasses the detector *and* `PRESIDIO_DEVICE`. +2. **`device` omitted** — Presidio's `DeviceDetector` singleton decides: + the `PRESIDIO_DEVICE` environment variable if set, otherwise + auto-detection (CUDA if available, else CPU). See + [GPU Acceleration](nlp_engines/gpu_usage.md). + +In most deployments, omit `device` and control hardware via +`PRESIDIO_DEVICE` — that keeps the YAML portable across CPU and GPU +environments. Set `device` explicitly only to pin a recognizer to +specific hardware regardless of environment (e.g. force a heavyweight +model onto `cuda:1`). + +If CUDA is requested but unavailable, the recognizer logs a warning and +falls back to CPU. + +!!! note "MPS (Apple Silicon) is not supported" + Presidio's device detector does not support MPS, and the recognizer + normalizes any non-CUDA device to CPU. On Apple Silicon the torch + backend runs on CPU; for acceleration use the ort backend with the + CoreML execution provider. + +## ort backend + +Uses optimum's `ORTModelForTokenClassification` plus ONNX Runtime. + +### Installation + +For CPU (also covers Apple Silicon via the CoreML EP), use the +`onnxruntime` extra: + +```bash +pip install 'presidio-analyzer[onnxruntime]' +``` + +The extra installs the **CPU** build of ONNX Runtime. For GPU or other +accelerators, skip the extra and install the optimum stack with the +ONNX Runtime build matching your hardware — e.g. in a CUDA Docker image: + +```bash +# NVIDIA GPU: onnxruntime-gpu instead of onnxruntime +pip install presidio-analyzer optimum 'optimum-onnx[onnxruntime-gpu]' 'transformers<5' +``` + +| Hardware | ONNX Runtime build | +|----------|--------------------| +| CPU (default) | `onnxruntime` — via `presidio-analyzer[onnxruntime]` | +| NVIDIA GPU | `optimum-onnx[onnxruntime-gpu]` (pulls `onnxruntime-gpu`) | +| Apple Silicon (CoreML) | `onnxruntime` — CoreML EP ships in the default package | +| Intel CPU/GPU/NPU | `onnxruntime-openvino` (install instead of `onnxruntime`) | +| AMD GPU (ROCm) | `onnxruntime-rocm` (install instead of `onnxruntime`) | + +!!! warning "Do not combine the extra with a GPU build" + `onnxruntime`, `onnxruntime-gpu`, `onnxruntime-openvino`, etc. all + ship the same Python module and shadow each other when several are + installed. If you use a non-CPU build, install it *instead of* the + `[onnxruntime]` extra, not on top of it. To recover from a mixed + install: + + ```bash + pip uninstall onnxruntime onnxruntime-gpu onnxruntime-openvino + pip install onnxruntime-gpu # the one you actually want + ``` + +### YAML — CPU (default ORT) + +```yaml +- name: "HF NER (ORT CPU)" + type: predefined + class_name: HuggingFaceNerRecognizer + model_name: optimum/bert-base-NER + backend: ort + aggregation_strategy: simple + threshold: 0.3 + supported_languages: [en] + supported_entities: [PERSON, LOCATION, ORGANIZATION] +``` + +For models published under the dual-runtime convention +(`onnx-community/*`, `Xenova/*`) where ONNX files +sit under `onnx/` while config/tokenizer live at the repo root, also +specify `subfolder` and `file_name`: + +```yaml +- name: "HF NER (ORT, FP16 ONNX)" + type: predefined + class_name: HuggingFaceNerRecognizer + model_name: onnx-community/stanford-deidentifier-base-ONNX + backend: ort + subfolder: onnx + file_name: model_fp16.onnx # or model.onnx, model_quantized.onnx, model_int8.onnx, ... + aggregation_strategy: simple + threshold: 0.3 +``` + +The recognizer pre-loads the ORT model with these kwargs scoped to the +model loader, so they don't leak into transformers' tokenizer/config +loading. + +### YAML — NVIDIA GPU + +Install `onnxruntime-gpu` and select the CUDA provider: + +```yaml +- name: "HF NER (ORT, CUDA)" + type: predefined + class_name: HuggingFaceNerRecognizer + model_name: optimum/bert-base-NER + backend: ort + provider: CUDAExecutionProvider + provider_options: + - device_id: 0 + aggregation_strategy: simple + threshold: 0.3 +``` + +For TensorRT (higher throughput, slow first request because of engine +build): + +```yaml +- name: "HF NER (ORT, TensorRT)" + type: predefined + class_name: HuggingFaceNerRecognizer + model_name: optimum/bert-base-NER + backend: ort + provider: TensorrtExecutionProvider + provider_options: + - trt_fp16_enable: true + trt_engine_cache_enable: true + trt_engine_cache_path: /var/cache/trt + aggregation_strategy: simple + threshold: 0.3 +``` + +### YAML — Intel CPU / iGPU / NPU via OpenVINO + +Install `onnxruntime-openvino`: + +```bash +pip uninstall onnxruntime onnxruntime-gpu +pip install onnxruntime-openvino +``` + +Then route through the OpenVINO execution provider: + +```yaml +- name: "HF NER (ORT, OpenVINO)" + type: predefined + class_name: HuggingFaceNerRecognizer + model_name: optimum/bert-base-NER + backend: ort + provider: OpenVINOExecutionProvider + provider_options: + - device_type: CPU # CPU | GPU | NPU | AUTO + aggregation_strategy: simple + threshold: 0.3 +``` + +OpenVINO is most worthwhile on: + +- Intel Xeon Scalable (Sapphire Rapids and newer) — its kernels use + AVX-512 BF16 / AMX instructions that the default CPU EP does not fully + exploit. Intel publishes substantial speedups for BERT-class models on + this hardware; actual gains depend heavily on model, sequence length, + and batch size. +- Intel Arc / iGPU / Data Center GPU Max — native GPU acceleration without + CUDA. +- Intel NPUs (Meteor Lake, Lunar Lake, Arrow Lake) — currently the only + practical runtime for on-device NPU inference. + +!!! note "Benchmark before adopting" + The throughput figures published for these providers come from vendor + benchmarks under favorable conditions (large batches, long + sequences). Typical Presidio traffic — short texts at low batch + sizes — usually sees smaller gains, and on generic cloud VMs (where + the CPU generation isn't guaranteed) the difference over the default + CPU EP can be negligible. Measure on your target hardware with your + own traffic shape before committing to a provider. + +### Apple Silicon (CoreML) + +The default `onnxruntime` package ships the CoreML execution provider on +macOS: + +```yaml +- name: "HF NER (ORT, CoreML)" + type: predefined + class_name: HuggingFaceNerRecognizer + model_name: optimum/bert-base-NER + backend: ort + provider: CoreMLExecutionProvider +``` + +On Apple Silicon the torch backend runs on CPU (the recognizer does not +support MPS), so the CoreML EP is the only acceleration path — at the +cost of needing an ONNX model (pre-built or exported). + +### AMD GPU (ROCm) + +```yaml +- name: "HF NER (ORT, ROCm)" + type: predefined + class_name: HuggingFaceNerRecognizer + model_name: optimum/bert-base-NER + backend: ort + provider: ROCMExecutionProvider +``` + +Requires `onnxruntime-rocm`. + +## Picking an ONNX variant + +When the repo ships multiple quantized ONNX files (common in +`onnx-community/*`), the precision/quantization knob is the `file_name`, +not a runtime flag: + +| File | Precision | Notes | +|------|-----------|-------| +| `model.onnx` | FP32 | Baseline; largest | +| `model_fp16.onnx` | FP16 | ~half the size; benefits from NVIDIA tensor cores, limited CPU support | +| `model_bf16.onnx` | BF16 | Needs BF16-capable hardware (Sapphire Rapids+, recent NVIDIA) | +| `model_int8.onnx` | INT8 (dynamic) | ~quarter the size; aimed at CPU inference | +| `model_quantized.onnx` | INT8 (static) | Pre-calibrated variant of INT8 | +| `model_uint8.onnx` | UINT8 | Similar to INT8 | +| `model_q4.onnx`, `model_q4f16.onnx` | 4-bit | Smallest; expect an accuracy trade-off | + +Smaller is not automatically faster — quantized kernels, hardware +support, and accuracy interact. Validate both latency *and* detection +quality (precision/recall on your own data) when switching variants. + +Pick by setting `file_name:` in the YAML. Inference precision otherwise +follows what's baked into the ONNX file — there is no separate `dtype` +parameter at the recognizer level. + +## Troubleshooting + +- **`FileNotFoundError: Could not find any ONNX files`** — the repo uses a + mixed layout. Set `subfolder: onnx` and a *bare* `file_name` + (e.g. `model.onnx`, not `onnx/model.onnx`). Path-in-`file_name` does not + match optimum's resolver even when the file is listed in the error. +- **`OSError: Could not locate onnx/config.json`** — `subfolder` is + leaking into tokenizer/config loading. Confirm you are on a recognizer + version that pre-loads `ORTModelForTokenClassification` explicitly; on + older versions the `subfolder` is passed at the pipeline level and + breaks mixed-layout repos. +- **`ImportError: cannot import name 'is_offline_mode' from + 'transformers.utils'`** — `optimum-onnx` is incompatible with + `transformers>=5`. Pin `transformers<5`. +- **Provider not available** at runtime — usually means another ORT + package (e.g. `onnxruntime` next to `onnxruntime-gpu`) is shadowing the + one with the provider you want. Uninstall all and reinstall a single + variant. +- **First TensorRT request is slow** — TRT builds an engine on first use. + Persist `trt_engine_cache_path` so subsequent processes reuse it. +- **`TypeError: got an unexpected keyword argument 'foo'`** — a key in + your YAML is being forwarded to the loader and isn't recognized. Stray + kwargs are no longer silently dropped; the loud failure is intentional. diff --git a/docs/analyzer/nlp_engines/gpu_usage.md b/docs/analyzer/nlp_engines/gpu_usage.md index 52f6021485..a7b2874453 100644 --- a/docs/analyzer/nlp_engines/gpu_usage.md +++ b/docs/analyzer/nlp_engines/gpu_usage.md @@ -145,3 +145,4 @@ Related Presidio documentation: - [Transformer Models](transformers.md) - [spaCy and Stanza Models](spacy_stanza.md) - [Customizing NLP Models](../customizing_nlp_models.md) +- [HuggingFace NER inference backends](../huggingface_ner_inference.md) — ORT execution providers (CUDA, TensorRT, OpenVINO, CoreML, ROCm) and Intel-specific acceleration via `HuggingFaceNerRecognizer` diff --git a/docs/analyzer/recognizer_registry_provider.md b/docs/analyzer/recognizer_registry_provider.md index 1e260b46ef..53627d384f 100644 --- a/docs/analyzer/recognizer_registry_provider.md +++ b/docs/analyzer/recognizer_registry_provider.md @@ -92,6 +92,7 @@ The recognizer list comprises of both the predefined and custom recognizers, for type: "predefined" class_name: "HuggingFaceNerRecognizer" model_name: "dslim/bert-base-NER" + backend: "torch" # or "ort" for ONNX Runtime supported_languages: - en supported_entities: ["PERSON", "LOCATION", "ORGANIZATION"] @@ -99,6 +100,18 @@ The recognizer list comprises of both the predefined and custom recognizers, for device: "cpu" ``` +!!! tip "Optimized inference (GPU, CPU, Intel)" + + `HuggingFaceNerRecognizer` supports a `torch` backend (default) and an + `ort` backend (ONNX Runtime via `optimum`). The `ort` backend can + target NVIDIA GPU (`CUDAExecutionProvider`, + `TensorrtExecutionProvider`), Intel CPU/iGPU/NPU + (`OpenVINOExecutionProvider`), AMD GPU (`ROCMExecutionProvider`), and + Apple Silicon (`CoreMLExecutionProvider`) via execution providers. + See [HuggingFace NER inference backends](huggingface_ner_inference.md) + for install instructions, YAML examples per accelerator, and guidance + on picking quantized ONNX variants. + ### The recognizer parameters - `supported_languages`: A list of supported languages that the analyzer will support. In case this field is missing, a recognizer will be created for each supported language provided to the `AnalyzerEngine`. diff --git a/mkdocs.yml b/mkdocs.yml index 8ae5d2d1c8..5455e4052c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -44,6 +44,7 @@ nav: - Tutorial: analyzer/adding_recognizers.md - Best practices: analyzer/developing_recognizers.md - Recognizer registry from file: analyzer/recognizer_registry_provider.md + - HuggingFace NER inference backends: analyzer/huggingface_ner_inference.md - Filtering recognizers by country: analyzer/filtering_by_country.md - Multi-language support: analyzer/languages.md - Customizing the NLP model: diff --git a/presidio-analyzer/presidio_analyzer/conf/hf_ner_onnx.yaml b/presidio-analyzer/presidio_analyzer/conf/hf_ner_onnx.yaml new file mode 100644 index 0000000000..c31537147b --- /dev/null +++ b/presidio-analyzer/presidio_analyzer/conf/hf_ner_onnx.yaml @@ -0,0 +1,40 @@ +supported_languages: + - en +default_score_threshold: 0 +nlp_configuration: + nlp_engine_name: slim + models: + - lang_code: en + model_name: en_core_web_sm + +recognizer_registry: + recognizers: + - name: SpacyRecognizer + type: predefined + enabled: false + + - name: "HuggingFace NER (ONNX)" + type: predefined + class_name: HuggingFaceNerRecognizer + model_name: onnx-community/stanford-deidentifier-base-ONNX + backend: ort + subfolder: onnx + file_name: model.onnx + supported_languages: + - en + supported_entities: + - PERSON + - ORGANIZATION + - DATE_TIME + - PHONE_NUMBER + - ID + label_mapping: + PATIENT: PERSON + HCW: PERSON + HOSPITAL: ORGANIZATION + VENDOR: ORGANIZATION + DATE: DATE_TIME + PHONE: PHONE_NUMBER + ID: ID + aggregation_strategy: simple + threshold: 0.3 diff --git a/presidio-analyzer/presidio_analyzer/predefined_recognizers/ner/huggingface_ner_recognizer.py b/presidio-analyzer/presidio_analyzer/predefined_recognizers/ner/huggingface_ner_recognizer.py index ba544b53ca..69b60c9851 100644 --- a/presidio-analyzer/presidio_analyzer/predefined_recognizers/ner/huggingface_ner_recognizer.py +++ b/presidio-analyzer/presidio_analyzer/predefined_recognizers/ner/huggingface_ner_recognizer.py @@ -35,6 +35,11 @@ except ImportError: torch = None +try: + from optimum.pipelines import pipeline as optimum_pipeline +except ImportError: + optimum_pipeline = None + logger = logging.getLogger("presidio-analyzer") @@ -118,7 +123,8 @@ def __init__( tokenizer_name: Optional[str] = None, text_chunker: Optional[BaseTextChunker] = None, label_prefixes: Optional[List[str]] = None, - **kwargs, + backend: str = "torch", + **model_kwargs, ): """Initialize the HuggingFace NER Recognizer. @@ -137,30 +143,65 @@ def __init__( ("simple", "first", "average", "max"). Recommendation: Use "simple" or "first" so that entities are pre-aggregated by the model, preserving performance and alignment. - :param device: Device to use. Accepts: + :param device: Device to use ("torch" backend only). Accepts: - "cpu" or -1 for CPU - "cuda" or "cuda:N" or int N for GPU - None for auto-detection (GPU if available, else CPU) - Defaults to None. + Defaults to None. Ignored by the "ort" backend — select + hardware there via the `provider` model kwarg. :param chunk_overlap: Number of characters to overlap between chunks. :param chunk_size: Maximum number of characters per chunk. :param tokenizer_name: Name of the tokenizer. Defaults to model_name. :param text_chunker: Custom text chunking strategy. If None, uses CharacterBasedTextChunker with provided chunk_size and chunk_overlap. :param label_prefixes: List of label prefixes to strip (e.g., B-, I-). - :raises ImportError: If transformers or torch libraries are not installed. + :param backend: Inference backend to use. + - "torch" (default): PyTorch via transformers pipeline. + Requires: torch, transformers. + - "ort": ONNX Runtime via optimum. + Requires: optimum, optimum-onnx[onnxruntime]. + For NVIDIA GPU, install `onnxruntime-gpu` and pass + `provider="CUDAExecutionProvider"` via model_kwargs. + :param model_kwargs: Additional keyword arguments forwarded to the + underlying model loader. + For the "torch" backend, passed to `transformers.pipeline` as + `model_kwargs=`. For "ort", passed to + `ORTModel.from_pretrained` directly (so they scope to the model + loader only — important for mixed-layout repos where ONNX is + under `onnx/` but the tokenizer/config are at the repo root). + Use this for e.g. `file_name`, `subfolder`, `revision`, + `cache_dir`, `provider`, `provider_options`, `session_options`. + :raises ValueError: If `backend` is not one of "torch" or "ort". + :raises ImportError: If required libraries for the chosen backend + are not installed. """ + if backend not in ("torch", "ort"): + raise ValueError( + f"Unsupported backend: {backend!r}. Expected 'torch' or 'ort'." + ) + self.backend = backend + # Early check for required dependencies if hf_pipeline is None: raise ImportError( "transformers is not installed. Please install it " - "(pip install transformers torch) to use this recognizer." - ) - if torch is None: - raise ImportError( - "torch is not installed. Please install it " - "(pip install torch) to use this recognizer." + "(pip install 'presidio-analyzer[transformers]') " + "to use this recognizer." ) + if self.backend == "torch": + if torch is None: + raise ImportError( + "torch is not installed. Please install it " + "(pip install 'presidio-analyzer[transformers]') " + "to use the 'torch' backend." + ) + elif self.backend == "ort": + if optimum_pipeline is None: + raise ImportError( + "optimum is not installed. Please install it " + "(pip install 'presidio-analyzer[onnxruntime]') " + "to use the 'ort' backend." + ) self.model_name = model_name self.tokenizer_name = tokenizer_name or model_name @@ -174,16 +215,22 @@ def __init__( "aggregation_strategy='none' may result in fragmented entities " "(e.g., 'B-PER', 'I-PER'). Recommended: 'simple' or 'first'." ) - self.device = self._parse_device(device) + if self.backend == "ort": + if device not in (None, "cpu", -1): + logger.warning( + "The 'device' parameter is ignored by the 'ort' backend. " + "Select hardware via the 'provider' model kwarg instead, " + "e.g. provider='CUDAExecutionProvider'." + ) + # ort selects hardware via the execution provider, not device. + # Skip parsing/auto-detection and keep self.device consistent + # with actual behavior. + self.device = -1 + else: + self.device = self._parse_device(device) self.label_prefixes = label_prefixes or ["B-", "I-", "U-", "L-"] self.ner_pipeline = None - - if kwargs: - logger.warning( - "Ignoring unsupported kwargs in %s: %s", - name, - sorted(kwargs.keys()), - ) + self.model_kwargs = model_kwargs # Derive supported entities from label mapping if supported_entities: @@ -248,8 +295,10 @@ def load(self) -> None: """Load the HuggingFace NER pipeline. This method handles: - 1. Hardware acceleration setup (CUDA validation and fallback) - 2. Lazy-loading of the heavyweight ML pipeline. + 1. Backend selection (torch or ort) + 2. Hardware acceleration setup (CUDA validation and fallback for + the torch backend; provider selection for ort via model_kwargs) + 3. Lazy-loading of the heavyweight ML pipeline. :raises ValueError: If model_name is not set """ @@ -262,6 +311,13 @@ def load(self) -> None: "Pass it to __init__() or set it directly." ) + if self.backend == "torch": + self._load_torch_pipeline() + else: + self._load_ort_pipeline() + + def _load_torch_pipeline(self) -> None: + """Load the NER pipeline using PyTorch backend.""" # Device validation and fallback device = self.device if device >= 0: @@ -276,7 +332,10 @@ def load(self) -> None: ) device = -1 - logger.info(f"Loading HuggingFace model: {self.model_name}, device={device}") + logger.info( + f"Loading HuggingFace model: {self.model_name}, " + f"backend=torch, device={device}" + ) try: self.ner_pipeline = hf_pipeline( @@ -285,12 +344,51 @@ def load(self) -> None: tokenizer=self.tokenizer_name, aggregation_strategy=self.aggregation_strategy, device=device, + model_kwargs=self.model_kwargs or None, ) logger.info(f"Successfully loaded {self.model_name}") except Exception: logger.exception(f"Failed to load model {self.model_name}") raise + def _load_ort_pipeline(self) -> None: + """Load the NER pipeline using optimum's ONNX Runtime backend. + + Pre-loads ``ORTModelForTokenClassification`` explicitly so that + model_kwargs like ``subfolder`` and ``file_name`` are scoped to the + model loader only. Passing them at the pipeline level leaks them + into transformers' config/tokenizer loading, which breaks + mixed-layout repos (e.g. onnx-community/*, Xenova/*) where the ONNX + file lives under ``onnx/`` but config/tokenizer live at the repo + root. + """ + try: + from optimum.onnxruntime import ORTModelForTokenClassification + except ImportError as e: + raise ImportError( + "optimum-onnx is not installed. Please install it " + "(pip install 'presidio-analyzer[onnxruntime]') " + "to use the 'ort' backend." + ) from e + + logger.info(f"Loading HuggingFace model: {self.model_name}, backend=ort") + + try: + model = ORTModelForTokenClassification.from_pretrained( + self.model_name, **self.model_kwargs + ) + self.ner_pipeline = optimum_pipeline( + self.DEFAULT_HF_TASK, + model=model, + tokenizer=self.tokenizer_name, + aggregation_strategy=self.aggregation_strategy, + accelerator="ort", + ) + logger.info(f"Successfully loaded {self.model_name} with ort backend") + except Exception: + logger.exception(f"Failed to load model {self.model_name} with ort backend") + raise + def _normalize_label(self, label: str) -> str: """Normalize label by removing prefixes like B-/I-/U-/L-. diff --git a/presidio-analyzer/pyproject.toml b/presidio-analyzer/pyproject.toml index 7b9b2ad89f..af8cd5779a 100644 --- a/presidio-analyzer/pyproject.toml +++ b/presidio-analyzer/pyproject.toml @@ -72,6 +72,11 @@ langextract = [ "more-itertools (>=10.0.0,<12.0.0)", "jinja2 (>=3.0.0,<4.0.0)", ] +onnxruntime = [ + "optimum (>=2.1.0,<3.0.0)", + "optimum-onnx[onnxruntime] (>=0.1.0,<2.0.0)", + "transformers (>=4.0.0,<5.0.0)", +] [dependency-groups] dev = [ diff --git a/presidio-analyzer/tests/test_huggingface_ner_recognizer.py b/presidio-analyzer/tests/test_huggingface_ner_recognizer.py index 7191aa6a43..f4ef488a3f 100644 --- a/presidio-analyzer/tests/test_huggingface_ner_recognizer.py +++ b/presidio-analyzer/tests/test_huggingface_ner_recognizer.py @@ -1,6 +1,7 @@ """Tests for HuggingFaceNerRecognizer.""" import logging +import sys from unittest.mock import MagicMock, patch import pytest @@ -277,6 +278,7 @@ def test_load_invokes_hf_pipeline_with_expected_args(): tokenizer="test-model", aggregation_strategy="simple", device=-1, + model_kwargs=None, ) @@ -472,14 +474,28 @@ def test_hf_recognizer_device_fallback_and_validation(): @pytest.mark.usefixtures("mock_torch_installed") -@patch(HF_PIPELINE_PATH, new=MagicMock()) -def test_hf_recognizer_init_logs_warning_for_extra_kwargs(caplog): - """Test that valid but unsupported kwargs trigger a warning.""" - caplog.set_level(logging.WARNING, logger="presidio-analyzer") - # Passed 'unsupported_arg' which is not in __init__ - HuggingFaceNerRecognizer(model_name="test-model", unsupported_arg="some_value") +def test_hf_recognizer_forwards_extra_kwargs_as_model_kwargs(): + """Test that extra kwargs are forwarded to the pipeline via model_kwargs.""" + with patch(HF_PIPELINE_PATH, new=MagicMock()) as mock_hf_pipeline: + rec = HuggingFaceNerRecognizer( + model_name="test-model", + device=-1, + revision="main", + cache_dir="/tmp/cache", + ) - assert "Ignoring unsupported kwargs" in caplog.text + assert rec.model_kwargs == { + "revision": "main", + "cache_dir": "/tmp/cache", + } + mock_hf_pipeline.assert_called_once_with( + "token-classification", + model="test-model", + tokenizer="test-model", + aggregation_strategy="simple", + device=-1, + model_kwargs={"revision": "main", "cache_dir": "/tmp/cache"}, + ) @pytest.mark.usefixtures("mock_torch_installed") @@ -602,6 +618,248 @@ def test_hf_recognizer_analyze_handles_malformed_pipeline_output( assert rec.analyze("test", entities=["PERSON"]) == [] +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_ort_backend_requires_optimum(): + """ort backend raises ImportError when optimum is not installed.""" + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.optimum_pipeline", + None, + ): + with pytest.raises(ImportError, match="optimum is not installed"): + HuggingFaceNerRecognizer(model_name="test-model", backend="ort") + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_unknown_backend_raises(): + """Backends other than 'torch' or 'ort' are rejected at construction.""" + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with pytest.raises(ValueError, match="Unsupported backend"): + HuggingFaceNerRecognizer(model_name="test-model", backend="ov") + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_ort_backend_warns_when_device_set(caplog): + """Explicit device with ort backend logs a warning (device is ignored).""" + caplog.set_level(logging.WARNING, logger="presidio-analyzer") + mock_optimum = MagicMock() + mock_ort_model_cls = MagicMock() + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.optimum_pipeline", + mock_optimum, + ): + with patch( + "optimum.onnxruntime.ORTModelForTokenClassification", + mock_ort_model_cls, + ): + HuggingFaceNerRecognizer( + model_name="test-model", backend="ort", device="cuda" + ) + + assert "ignored by the 'ort' backend" in caplog.text + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_ort_backend_ignores_invalid_device(caplog): + """ort backend skips device parsing: an invalid device must not raise.""" + caplog.set_level(logging.WARNING, logger="presidio-analyzer") + mock_optimum = MagicMock() + mock_ort_model_cls = MagicMock() + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.optimum_pipeline", + mock_optimum, + ): + with patch( + "optimum.onnxruntime.ORTModelForTokenClassification", + mock_ort_model_cls, + ): + # "not-a-device" would raise ValueError via _parse_device on + # the torch backend; ort skips parsing and forces CPU. + rec = HuggingFaceNerRecognizer( + model_name="test-model", + backend="ort", + device="not-a-device", + ) + + assert rec.device == -1 + assert "ignored by the 'ort' backend" in caplog.text + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_ort_backend_cpu_device_no_warning(caplog): + """device='cpu' on ort is consistent with default behavior; no warning.""" + caplog.set_level(logging.WARNING, logger="presidio-analyzer") + mock_optimum = MagicMock() + mock_ort_model_cls = MagicMock() + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.optimum_pipeline", + mock_optimum, + ): + with patch( + "optimum.onnxruntime.ORTModelForTokenClassification", + mock_ort_model_cls, + ): + rec = HuggingFaceNerRecognizer( + model_name="test-model", backend="ort", device="cpu" + ) + + assert rec.device == -1 + assert "ignored by the 'ort' backend" not in caplog.text + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_ort_backend_loads_optimum_pipeline(): + """ort backend pre-loads ORTModel, then hands it to optimum_pipeline.""" + mock_optimum = MagicMock() + mock_ort_model_cls = MagicMock() + mock_model_instance = MagicMock() + mock_ort_model_cls.from_pretrained.return_value = mock_model_instance + + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.optimum_pipeline", + mock_optimum, + ): + with patch( + "optimum.onnxruntime.ORTModelForTokenClassification", + mock_ort_model_cls, + ): + HuggingFaceNerRecognizer(model_name="test-model", backend="ort") + + mock_ort_model_cls.from_pretrained.assert_called_once_with("test-model") + mock_optimum.assert_called_once_with( + "token-classification", + model=mock_model_instance, + tokenizer="test-model", + aggregation_strategy="simple", + accelerator="ort", + ) + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_optimum_model_kwargs_scoped_to_model_loader(): + """model_kwargs flow only to ORTModel.from_pretrained, not the pipeline. + + Pipeline-level kwargs would leak into transformers' tokenizer/config + loading and break mixed-layout repos (e.g. onnx-community/* where the + ONNX file is in ``onnx/`` but the tokenizer is at the repo root). + """ + mock_optimum = MagicMock() + mock_ort_model_cls = MagicMock() + mock_model_instance = MagicMock() + mock_ort_model_cls.from_pretrained.return_value = mock_model_instance + + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.optimum_pipeline", + mock_optimum, + ): + with patch( + "optimum.onnxruntime.ORTModelForTokenClassification", + mock_ort_model_cls, + ): + HuggingFaceNerRecognizer( + model_name="test-model", + backend="ort", + subfolder="onnx", + file_name="model_fp16.onnx", + ) + + mock_ort_model_cls.from_pretrained.assert_called_once_with( + "test-model", subfolder="onnx", file_name="model_fp16.onnx" + ) + _, pipeline_kwargs = mock_optimum.call_args + assert "subfolder" not in pipeline_kwargs + assert "file_name" not in pipeline_kwargs + assert "model_kwargs" not in pipeline_kwargs + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_torch_backend_no_torch_raises(): + """Test that torch backend raises ImportError when torch is missing.""" + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.torch", + None, + ): + with pytest.raises(ImportError, match="torch is not installed"): + HuggingFaceNerRecognizer(model_name="test-model", backend="torch") + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_ort_backend_no_torch_ok(): + """Test that ort backend works without torch installed.""" + mock_optimum = MagicMock() + mock_ort_model_cls = MagicMock() + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.torch", + None, + ): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.optimum_pipeline", + mock_optimum, + ): + with patch( + "optimum.onnxruntime.ORTModelForTokenClassification", + mock_ort_model_cls, + ): + rec = HuggingFaceNerRecognizer( + model_name="test-model", backend="ort" + ) + assert rec.backend == "ort" + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_ort_backend_requires_optimum_onnx(): + """The ort backend raises ImportError when optimum.onnxruntime is missing.""" + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.optimum_pipeline", + MagicMock(), + ): + # A None entry in sys.modules makes the import raise ImportError, + # simulating optimum installed without the optimum-onnx package. + with patch.dict(sys.modules, {"optimum.onnxruntime": None}): + with pytest.raises(ImportError, match="optimum-onnx is not installed"): + HuggingFaceNerRecognizer(model_name="test-model", backend="ort") + + +@pytest.mark.usefixtures("mock_torch_installed") +def test_hf_recognizer_ort_backend_load_failure_logs_and_raises(caplog): + """A model load failure on the ort backend is logged and re-raised.""" + caplog.set_level(logging.ERROR, logger="presidio-analyzer") + mock_ort_model_cls = MagicMock() + mock_ort_model_cls.from_pretrained.side_effect = RuntimeError("no such model") + with patch(HF_PIPELINE_PATH, new=MagicMock()): + with patch( + "presidio_analyzer.predefined_recognizers.ner." + "huggingface_ner_recognizer.optimum_pipeline", + MagicMock(), + ): + with patch( + "optimum.onnxruntime.ORTModelForTokenClassification", + mock_ort_model_cls, + ): + with pytest.raises(RuntimeError, match="no such model"): + HuggingFaceNerRecognizer(model_name="test-model", backend="ort") + + assert "Failed to load model test-model with ort backend" in caplog.text + + def test_hf_recognizer_loader_supported_entities_filtering(): """Verify if supported_entities survives the RecognizerListLoader logic.""" rec_conf = { diff --git a/presidio-analyzer/tests/test_huggingface_ner_recognizer_e2e.py b/presidio-analyzer/tests/test_huggingface_ner_recognizer_e2e.py new file mode 100644 index 0000000000..1a95440adc --- /dev/null +++ b/presidio-analyzer/tests/test_huggingface_ner_recognizer_e2e.py @@ -0,0 +1,165 @@ +"""End-to-end tests for HuggingFaceNerRecognizer with real model loading. + +Unlike test_huggingface_ner_recognizer.py (fully mocked), these tests +download real models from the HuggingFace Hub and exercise the actual +transformers/optimum pipelines. They are the only coverage for the +recognizer's load() path against real library behavior. + +Two tiers: + +1. Mechanics tests with hf-internal-testing/tiny-random-bert (~100KB). + The weights are random, so they assert on mechanics (spans, types, + thresholds, torch/ort parity), not on meaningful predictions. +2. Semantic tests with the Stanford de-identifier — the model family used + by conf/hf_ner_onnx.yaml and already downloaded by the engine tests (conftest + references the torch variant). These assert on actual PII detection, + and the ort test covers the mixed-layout repo scenario (ONNX under + onnx/, tokenizer at root) that requires subfolder/file_name scoping. +""" + +import pytest +from presidio_analyzer import RecognizerResult +from presidio_analyzer.predefined_recognizers import ( + HuggingFaceNerRecognizer, +) + +TINY_MODEL = "hf-internal-testing/tiny-random-bert" +TINY_TEXT = "John Smith works at Contoso in Berlin since 2019." +# Random-weight model emits LABEL_0/LABEL_1; map both so output is non-empty. +TINY_LABEL_MAPPING = {"LABEL_0": "PERSON", "LABEL_1": "LOCATION"} + + +def _assert_valid_results(results, text): + assert isinstance(results, list) + assert len(results) > 0 + for r in results: + assert isinstance(r, RecognizerResult) + assert r.entity_type in ("PERSON", "LOCATION") + assert 0 <= r.start < r.end <= len(text) + assert 0.0 <= r.score <= 1.0 + + +def test_hf_recognizer_e2e_torch_backend(): + """Real torch pipeline end-to-end on a tiny random model.""" + pytest.importorskip("torch", reason="torch is not installed") + + rec = HuggingFaceNerRecognizer( + model_name=TINY_MODEL, + backend="torch", + device="cpu", + label_mapping=TINY_LABEL_MAPPING, + threshold=0.0, + ) + results = rec.analyze(TINY_TEXT, entities=["PERSON", "LOCATION"]) + _assert_valid_results(results, TINY_TEXT) + + +def test_hf_recognizer_e2e_ort_backend(): + """Real ONNX Runtime pipeline end-to-end on a tiny random model. + + The repo has no .onnx weights, so this also exercises optimum's + export-on-the-fly path (export=True forwarded via **model_kwargs). + """ + pytest.importorskip( + "optimum.onnxruntime", reason="optimum-onnx is not installed" + ) + + rec = HuggingFaceNerRecognizer( + model_name=TINY_MODEL, + backend="ort", + label_mapping=TINY_LABEL_MAPPING, + threshold=0.0, + export=True, + ) + results = rec.analyze(TINY_TEXT, entities=["PERSON", "LOCATION"]) + _assert_valid_results(results, TINY_TEXT) + + +def test_hf_recognizer_e2e_torch_and_ort_agree_on_spans(): + """Both backends run the same model; spans and scores should match.""" + pytest.importorskip("torch", reason="torch is not installed") + pytest.importorskip( + "optimum.onnxruntime", reason="optimum-onnx is not installed" + ) + + common = dict( + model_name=TINY_MODEL, + label_mapping=TINY_LABEL_MAPPING, + threshold=0.0, + ) + torch_results = HuggingFaceNerRecognizer( + backend="torch", device="cpu", **common + ).analyze(TINY_TEXT, entities=["PERSON", "LOCATION"]) + ort_results = HuggingFaceNerRecognizer( + backend="ort", export=True, **common + ).analyze(TINY_TEXT, entities=["PERSON", "LOCATION"]) + + torch_spans = [(r.entity_type, r.start, r.end) for r in torch_results] + ort_spans = [(r.entity_type, r.start, r.end) for r in ort_results] + assert torch_spans == ort_spans + for tr, orr in zip(torch_results, ort_results): + assert abs(tr.score - orr.score) < 1e-3 + + +DEID_TEXT = ( + "Hi, I'm Dr. Sarah Chen from Mount Sinai Hospital. " + "Please call me at 555-123-4567 on March 5th, 2026." +) +DEID_LABEL_MAPPING = { + "PATIENT": "PERSON", + "HCW": "PERSON", + "HOSPITAL": "ORGANIZATION", + "VENDOR": "ORGANIZATION", + "DATE": "DATE_TIME", + "PHONE": "PHONE_NUMBER", + "ID": "ID", +} +DEID_ENTITIES = ["PERSON", "ORGANIZATION", "DATE_TIME", "PHONE_NUMBER"] + + +def _assert_deid_detections(results, text): + detected = {(r.entity_type, text[r.start : r.end]) for r in results} + assert ("PERSON", "Dr. Sarah Chen") in detected + assert ("ORGANIZATION", "Mount Sinai Hospital") in detected + assert ("PHONE_NUMBER", "555-123-4567") in detected + + +def test_hf_recognizer_e2e_torch_stanford_deidentifier(): + """Real PII detection with the torch backend on the Stanford model.""" + pytest.importorskip("torch", reason="torch is not installed") + + rec = HuggingFaceNerRecognizer( + model_name="StanfordAIMI/stanford-deidentifier-base", + backend="torch", + device="cpu", + label_mapping=DEID_LABEL_MAPPING, + threshold=0.5, + ) + results = rec.analyze(DEID_TEXT, entities=DEID_ENTITIES) + _assert_deid_detections(results, DEID_TEXT) + + +def test_hf_recognizer_e2e_ort_mixed_layout_repo(): + """Real PII detection with ort on a mixed-layout repo. + + onnx-community/stanford-deidentifier-base-ONNX keeps config/tokenizer at + the repo root and ONNX files under onnx/. This is the scenario that + requires subfolder/file_name to be scoped to the model loader only — + regression coverage for the pipeline-level kwarg leak. + """ + pytest.importorskip( + "optimum.onnxruntime", reason="optimum-onnx is not installed" + ) + + rec = HuggingFaceNerRecognizer( + model_name="onnx-community/stanford-deidentifier-base-ONNX", + backend="ort", + subfolder="onnx", + # INT8 variant: same detections as model.onnx on this text, but a + # 105MB download instead of 416MB (matters in CI, no HF cache there). + file_name="model_quantized.onnx", + label_mapping=DEID_LABEL_MAPPING, + threshold=0.5, + ) + results = rec.analyze(DEID_TEXT, entities=DEID_ENTITIES) + _assert_deid_detections(results, DEID_TEXT) diff --git a/presidio-analyzer/uv.lock b/presidio-analyzer/uv.lock index 1462cc818f..dca60ea0f7 100644 --- a/presidio-analyzer/uv.lock +++ b/presidio-analyzer/uv.lock @@ -6,11 +6,14 @@ resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.13.*' and sys_platform == 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32'", + "python_full_version == '3.12.*' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version == '3.13.*' and sys_platform == 'emscripten'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'emscripten'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.12.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version < '3.11'", ] @@ -839,7 +842,7 @@ name = "cuda-bindings" version = "13.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cuda-pathfinder" }, + { name = "cuda-pathfinder", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/a9/21/8464d133752951c154feafb3b65c297e7d80f301183d220bec4c830f1441/cuda_bindings-13.3.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:120fcc53d57903df529c3486962c56528cba5b7d6c57c99537320ed9922c8b86", size = 6073403, upload-time = "2026-05-29T23:11:36.22Z" }, @@ -874,43 +877,43 @@ wheels = [ [package.optional-dependencies] cublas = [ - { name = "nvidia-cublas", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, - { name = "nvidia-cuda-nvrtc", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-cublas", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nvidia-cuda-nvrtc", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] cudart = [ - { name = "nvidia-cuda-runtime", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-cuda-runtime", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] cufft = [ - { name = "nvidia-cufft", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, - { name = "nvidia-nvjitlink", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-cufft", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nvidia-nvjitlink", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] cufile = [ { name = "nvidia-cufile", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] cupti = [ - { name = "nvidia-cuda-cupti", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-cuda-cupti", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] curand = [ - { name = "nvidia-curand", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-curand", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] cusolver = [ - { name = "nvidia-cublas", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, - { name = "nvidia-cusolver", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, - { name = "nvidia-cusparse", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, - { name = "nvidia-nvjitlink", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-cublas", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nvidia-cusolver", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nvidia-cusparse", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nvidia-nvjitlink", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] cusparse = [ - { name = "nvidia-cusparse", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, - { name = "nvidia-nvjitlink", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-cusparse", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "nvidia-nvjitlink", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] nvjitlink = [ - { name = "nvidia-nvjitlink", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-nvjitlink", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] nvrtc = [ - { name = "nvidia-cuda-nvrtc", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-cuda-nvrtc", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] nvtx = [ - { name = "nvidia-nvtx", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32')" }, + { name = "nvidia-nvtx", marker = "(python_full_version < '3.11' and platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, ] [[package]] @@ -1362,7 +1365,7 @@ name = "gunicorn" version = "25.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "packaging" }, + { name = "packaging", marker = "python_full_version < '3.11' or sys_platform != 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c4/f4/e78fa054248fab913e2eab0332c6c2cb07421fca1ce56d8fe43b6aef57a4/gunicorn-25.3.0.tar.gz", hash = "sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889", size = 634883, upload-time = "2026-03-27T00:00:26.092Z" } wheels = [ @@ -1774,6 +1777,52 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ab/8a/18d4ff2c7bd83f30d6924bd4ad97abf418488c3f908dea228d6f0961ad68/ml_collections-1.1.0-py3-none-any.whl", hash = "sha256:23b6fa4772aac1ae745a96044b925a5746145a70734f087eaca6626e92c05cbc", size = 76707, upload-time = "2025-04-17T08:24:59.038Z" }, ] +[[package]] +name = "ml-dtypes" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/4a/c27b42ed9b1c7d13d9ba8b6905dece787d6259152f2309338aed29b2447b/ml_dtypes-0.5.4.tar.gz", hash = "sha256:8ab06a50fb9bf9666dd0fe5dfb4676fa2b0ac0f31ecff72a6c3af8e22c063453", size = 692314, upload-time = "2025-11-17T22:32:31.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/3a/c5b855752a70267ff729c349e650263adb3c206c29d28cc8ea7ace30a1d5/ml_dtypes-0.5.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b95e97e470fe60ed493fd9ae3911d8da4ebac16bd21f87ffa2b7c588bf22ea2c", size = 679735, upload-time = "2025-11-17T22:31:31.367Z" }, + { url = "https://files.pythonhosted.org/packages/41/79/7433f30ee04bd4faa303844048f55e1eb939131c8e5195a00a96a0939b64/ml_dtypes-0.5.4-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4b801ebe0b477be666696bda493a9be8356f1f0057a57f1e35cd26928823e5a", size = 5051883, upload-time = "2025-11-17T22:31:33.658Z" }, + { url = "https://files.pythonhosted.org/packages/10/b1/8938e8830b0ee2e167fc75a094dea766a1152bde46752cd9bfc57ee78a82/ml_dtypes-0.5.4-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:388d399a2152dd79a3f0456a952284a99ee5c93d3e2f8dfe25977511e0515270", size = 5030369, upload-time = "2025-11-17T22:31:35.595Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a3/51886727bd16e2f47587997b802dd56398692ce8c6c03c2e5bb32ecafe26/ml_dtypes-0.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:4ff7f3e7ca2972e7de850e7b8fcbb355304271e2933dd90814c1cb847414d6e2", size = 210738, upload-time = "2025-11-17T22:31:37.43Z" }, + { url = "https://files.pythonhosted.org/packages/c6/5e/712092cfe7e5eb667b8ad9ca7c54442f21ed7ca8979745f1000e24cf8737/ml_dtypes-0.5.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6c7ecb74c4bd71db68a6bea1edf8da8c34f3d9fe218f038814fd1d310ac76c90", size = 679734, upload-time = "2025-11-17T22:31:39.223Z" }, + { url = "https://files.pythonhosted.org/packages/4f/cf/912146dfd4b5c0eea956836c01dcd2fce6c9c844b2691f5152aca196ce4f/ml_dtypes-0.5.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bc11d7e8c44a65115d05e2ab9989d1e045125d7be8e05a071a48bc76eb6d6040", size = 5056165, upload-time = "2025-11-17T22:31:41.071Z" }, + { url = "https://files.pythonhosted.org/packages/a9/80/19189ea605017473660e43762dc853d2797984b3c7bf30ce656099add30c/ml_dtypes-0.5.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19b9a53598f21e453ea2fbda8aa783c20faff8e1eeb0d7ab899309a0053f1483", size = 5034975, upload-time = "2025-11-17T22:31:42.758Z" }, + { url = "https://files.pythonhosted.org/packages/b4/24/70bd59276883fdd91600ca20040b41efd4902a923283c4d6edcb1de128d2/ml_dtypes-0.5.4-cp311-cp311-win_amd64.whl", hash = "sha256:7c23c54a00ae43edf48d44066a7ec31e05fdc2eee0be2b8b50dd1903a1db94bb", size = 210742, upload-time = "2025-11-17T22:31:44.068Z" }, + { url = "https://files.pythonhosted.org/packages/a0/c9/64230ef14e40aa3f1cb254ef623bf812735e6bec7772848d19131111ac0d/ml_dtypes-0.5.4-cp311-cp311-win_arm64.whl", hash = "sha256:557a31a390b7e9439056644cb80ed0735a6e3e3bb09d67fd5687e4b04238d1de", size = 160709, upload-time = "2025-11-17T22:31:46.557Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b8/3c70881695e056f8a32f8b941126cf78775d9a4d7feba8abcb52cb7b04f2/ml_dtypes-0.5.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a174837a64f5b16cab6f368171a1a03a27936b31699d167684073ff1c4237dac", size = 676927, upload-time = "2025-11-17T22:31:48.182Z" }, + { url = "https://files.pythonhosted.org/packages/54/0f/428ef6881782e5ebb7eca459689448c0394fa0a80bea3aa9262cba5445ea/ml_dtypes-0.5.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7f7c643e8b1320fd958bf098aa7ecf70623a42ec5154e3be3be673f4c34d900", size = 5028464, upload-time = "2025-11-17T22:31:50.135Z" }, + { url = "https://files.pythonhosted.org/packages/3a/cb/28ce52eb94390dda42599c98ea0204d74799e4d8047a0eb559b6fd648056/ml_dtypes-0.5.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ad459e99793fa6e13bd5b7e6792c8f9190b4e5a1b45c63aba14a4d0a7f1d5ff", size = 5009002, upload-time = "2025-11-17T22:31:52.001Z" }, + { url = "https://files.pythonhosted.org/packages/f5/f0/0cfadd537c5470378b1b32bd859cf2824972174b51b873c9d95cfd7475a5/ml_dtypes-0.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:c1a953995cccb9e25a4ae19e34316671e4e2edaebe4cf538229b1fc7109087b7", size = 212222, upload-time = "2025-11-17T22:31:53.742Z" }, + { url = "https://files.pythonhosted.org/packages/16/2e/9acc86985bfad8f2c2d30291b27cd2bb4c74cea08695bd540906ed744249/ml_dtypes-0.5.4-cp312-cp312-win_arm64.whl", hash = "sha256:9bad06436568442575beb2d03389aa7456c690a5b05892c471215bfd8cf39460", size = 160793, upload-time = "2025-11-17T22:31:55.358Z" }, + { url = "https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c760d85a2f82e2bed75867079188c9d18dae2ee77c25a54d60e9cc79be1bc48", size = 676888, upload-time = "2025-11-17T22:31:56.907Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce756d3a10d0c4067172804c9cc276ba9cc0ff47af9078ad439b075d1abdc29b", size = 5036993, upload-time = "2025-11-17T22:31:58.497Z" }, + { url = "https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:533ce891ba774eabf607172254f2e7260ba5f57bdd64030c9a4fcfbd99815d0d", size = 5010956, upload-time = "2025-11-17T22:31:59.931Z" }, + { url = "https://files.pythonhosted.org/packages/e1/8b/200088c6859d8221454825959df35b5244fa9bdf263fd0249ac5fb75e281/ml_dtypes-0.5.4-cp313-cp313-win_amd64.whl", hash = "sha256:f21c9219ef48ca5ee78402d5cc831bd58ea27ce89beda894428bc67a52da5328", size = 212224, upload-time = "2025-11-17T22:32:01.349Z" }, + { url = "https://files.pythonhosted.org/packages/8f/75/dfc3775cb36367816e678f69a7843f6f03bd4e2bcd79941e01ea960a068e/ml_dtypes-0.5.4-cp313-cp313-win_arm64.whl", hash = "sha256:35f29491a3e478407f7047b8a4834e4640a77d2737e0b294d049746507af5175", size = 160798, upload-time = "2025-11-17T22:32:02.864Z" }, + { url = "https://files.pythonhosted.org/packages/4f/74/e9ddb35fd1dd43b1106c20ced3f53c2e8e7fc7598c15638e9f80677f81d4/ml_dtypes-0.5.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:304ad47faa395415b9ccbcc06a0350800bc50eda70f0e45326796e27c62f18b6", size = 702083, upload-time = "2025-11-17T22:32:04.08Z" }, + { url = "https://files.pythonhosted.org/packages/74/f5/667060b0aed1aa63166b22897fdf16dca9eb704e6b4bbf86848d5a181aa7/ml_dtypes-0.5.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a0df4223b514d799b8a1629c65ddc351b3efa833ccf7f8ea0cf654a61d1e35d", size = 5354111, upload-time = "2025-11-17T22:32:05.546Z" }, + { url = "https://files.pythonhosted.org/packages/40/49/0f8c498a28c0efa5f5c95a9e374c83ec1385ca41d0e85e7cf40e5d519a21/ml_dtypes-0.5.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:531eff30e4d368cb6255bc2328d070e35836aa4f282a0fb5f3a0cd7260257298", size = 5366453, upload-time = "2025-11-17T22:32:07.115Z" }, + { url = "https://files.pythonhosted.org/packages/8c/27/12607423d0a9c6bbbcc780ad19f1f6baa2b68b18ce4bddcdc122c4c68dc9/ml_dtypes-0.5.4-cp313-cp313t-win_amd64.whl", hash = "sha256:cb73dccfc991691c444acc8c0012bee8f2470da826a92e3a20bb333b1a7894e6", size = 225612, upload-time = "2025-11-17T22:32:08.615Z" }, + { url = "https://files.pythonhosted.org/packages/e5/80/5a5929e92c72936d5b19872c5fb8fc09327c1da67b3b68c6a13139e77e20/ml_dtypes-0.5.4-cp313-cp313t-win_arm64.whl", hash = "sha256:3bbbe120b915090d9dd1375e4684dd17a20a2491ef25d640a908281da85e73f1", size = 164145, upload-time = "2025-11-17T22:32:09.782Z" }, + { url = "https://files.pythonhosted.org/packages/72/4e/1339dc6e2557a344f5ba5590872e80346f76f6cb2ac3dd16e4666e88818c/ml_dtypes-0.5.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2b857d3af6ac0d39db1de7c706e69c7f9791627209c3d6dedbfca8c7e5faec22", size = 673781, upload-time = "2025-11-17T22:32:11.364Z" }, + { url = "https://files.pythonhosted.org/packages/04/f9/067b84365c7e83bda15bba2b06c6ca250ce27b20630b1128c435fb7a09aa/ml_dtypes-0.5.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:805cef3a38f4eafae3a5bf9ebdcdb741d0bcfd9e1bd90eb54abd24f928cd2465", size = 5036145, upload-time = "2025-11-17T22:32:12.783Z" }, + { url = "https://files.pythonhosted.org/packages/c6/bb/82c7dcf38070b46172a517e2334e665c5bf374a262f99a283ea454bece7c/ml_dtypes-0.5.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14a4fd3228af936461db66faccef6e4f41c1d82fcc30e9f8d58a08916b1d811f", size = 5010230, upload-time = "2025-11-17T22:32:14.38Z" }, + { url = "https://files.pythonhosted.org/packages/e9/93/2bfed22d2498c468f6bcd0d9f56b033eaa19f33320389314c19ef6766413/ml_dtypes-0.5.4-cp314-cp314-win_amd64.whl", hash = "sha256:8c6a2dcebd6f3903e05d51960a8058d6e131fe69f952a5397e5dbabc841b6d56", size = 221032, upload-time = "2025-11-17T22:32:15.763Z" }, + { url = "https://files.pythonhosted.org/packages/76/a3/9c912fe6ea747bb10fe2f8f54d027eb265db05dfb0c6335e3e063e74e6e8/ml_dtypes-0.5.4-cp314-cp314-win_arm64.whl", hash = "sha256:5a0f68ca8fd8d16583dfa7793973feb86f2fbb56ce3966daf9c9f748f52a2049", size = 163353, upload-time = "2025-11-17T22:32:16.932Z" }, + { url = "https://files.pythonhosted.org/packages/cd/02/48aa7d84cc30ab4ee37624a2fd98c56c02326785750cd212bc0826c2f15b/ml_dtypes-0.5.4-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:bfc534409c5d4b0bf945af29e5d0ab075eae9eecbb549ff8a29280db822f34f9", size = 702085, upload-time = "2025-11-17T22:32:18.175Z" }, + { url = "https://files.pythonhosted.org/packages/5a/e7/85cb99fe80a7a5513253ec7faa88a65306be071163485e9a626fce1b6e84/ml_dtypes-0.5.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2314892cdc3fcf05e373d76d72aaa15fda9fb98625effa73c1d646f331fcecb7", size = 5355358, upload-time = "2025-11-17T22:32:19.7Z" }, + { url = "https://files.pythonhosted.org/packages/79/2b/a826ba18d2179a56e144aef69e57fb2ab7c464ef0b2111940ee8a3a223a2/ml_dtypes-0.5.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d2ffd05a2575b1519dc928c0b93c06339eb67173ff53acb00724502cda231cf", size = 5366332, upload-time = "2025-11-17T22:32:21.193Z" }, + { url = "https://files.pythonhosted.org/packages/84/44/f4d18446eacb20ea11e82f133ea8f86e2bf2891785b67d9da8d0ab0ef525/ml_dtypes-0.5.4-cp314-cp314t-win_amd64.whl", hash = "sha256:4381fe2f2452a2d7589689693d3162e876b3ddb0a832cde7a414f8e1adf7eab1", size = 236612, upload-time = "2025-11-17T22:32:22.579Z" }, + { url = "https://files.pythonhosted.org/packages/ad/3f/3d42e9a78fe5edf792a83c074b13b9b770092a4fbf3462872f4303135f09/ml_dtypes-0.5.4-cp314-cp314t-win_arm64.whl", hash = "sha256:11942cbf2cf92157db91e5022633c0d9474d4dfd813a909383bd23ce828a4b7d", size = 168825, upload-time = "2025-11-17T22:32:23.766Z" }, +] + [[package]] name = "more-itertools" version = "11.1.0" @@ -2041,11 +2090,14 @@ resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.13.*' and sys_platform == 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32'", + "python_full_version == '3.12.*' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version == '3.13.*' and sys_platform == 'emscripten'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'emscripten'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.12.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] sdist = { url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" } wheels = [ @@ -2135,11 +2187,14 @@ resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.13.*' and sys_platform == 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32'", + "python_full_version == '3.12.*' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version == '3.13.*' and sys_platform == 'emscripten'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'emscripten'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.12.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] sdist = { url = "https://files.pythonhosted.org/packages/d0/ad/fed0499ce6a338d2a03ebae59cd15093910c8875328855781952abf6c2fe/numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda", size = 20735807, upload-time = "2026-05-18T23:37:14.07Z" } wheels = [ @@ -2221,7 +2276,7 @@ name = "nvidia-cublas" version = "13.1.1.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cuda-nvrtc" }, + { name = "nvidia-cuda-nvrtc", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/a7/a1/0bd24ee8c8d03adac032fd2909426a00c88f8c57961b1277ded97f91119f/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:b7a210458267ac818974c53038fbec2e969d5c99f305ab15c72522fa9f001dd5", size = 542848918, upload-time = "2026-04-08T18:46:22.985Z" }, @@ -2260,7 +2315,7 @@ name = "nvidia-cudnn-cu13" version = "9.20.0.48" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas" }, + { name = "nvidia-cublas", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/56/c5/83384d846b2fd17c44bd499b36c75a45ed4f095fbbb2252294e89cea5c5c/nvidia_cudnn_cu13-9.20.0.48-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:e31454ae00094b0c55319d9d15b6fa2fc50a9e1c0f5c8c80fb75258234e731e1", size = 444574296, upload-time = "2026-03-09T19:28:27.751Z" }, @@ -2272,7 +2327,7 @@ name = "nvidia-cufft" version = "12.0.0.61" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink" }, + { name = "nvidia-nvjitlink", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/8b/ae/f417a75c0259e85c1d2f83ca4e960289a5f814ed0cea74d18c353d3e989d/nvidia_cufft-12.0.0.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2708c852ef8cd89d1d2068bdbece0aa188813a0c934db3779b9b1faa8442e5f5", size = 214053554, upload-time = "2025-09-04T08:31:38.196Z" }, @@ -2302,9 +2357,9 @@ name = "nvidia-cusolver" version = "12.0.4.66" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas" }, - { name = "nvidia-cusparse" }, - { name = "nvidia-nvjitlink" }, + { name = "nvidia-cublas", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, + { name = "nvidia-cusparse", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, + { name = "nvidia-nvjitlink", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/c8/c3/b30c9e935fc01e3da443ec0116ed1b2a009bb867f5324d3f2d7e533e776b/nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:02c2457eaa9e39de20f880f4bd8820e6a1cfb9f9a34f820eb12a155aa5bc92d2", size = 223467760, upload-time = "2025-09-04T08:33:04.222Z" }, @@ -2316,7 +2371,7 @@ name = "nvidia-cusparse" version = "12.6.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink" }, + { name = "nvidia-nvjitlink", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/f8/94/5c26f33738ae35276672f12615a64bd008ed5be6d1ebcb23579285d960a9/nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:80bcc4662f23f1054ee334a15c72b8940402975e0eab63178fc7e670aa59472c", size = 162155568, upload-time = "2025-09-04T08:33:42.864Z" }, @@ -2368,6 +2423,44 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a8/64/3708a90d1ebe202ffdeb7185f878a3c84d15c2b2c31858da2ce0583e2def/nvidia_nvtx-13.0.85-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb7780edb6b14107373c835bf8b72e7a178bac7367e23da7acb108f973f157a6", size = 148878, upload-time = "2025-09-04T08:28:53.627Z" }, ] +[[package]] +name = "onnx" +version = "1.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ml-dtypes" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "protobuf" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/19/8ea73a64b368b75fe339771a20a02bc61ea1f551484c9e3d9d0bfbd0450f/onnx-1.22.0.tar.gz", hash = "sha256:ef40c0aaf0b643857ea9306fc7eddce17eaf9fb0407e4801f1fc5758443a38e0", size = 12024721, upload-time = "2026-06-15T12:50:05.354Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/04/471f234e2716c83f17a26e1b50cd64c39428373e91dd018aafb3d499c108/onnx-1.22.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:6d0ffffd63a4ecc21ddaeddd5bf02099cb701aa4243f2de00122726869065ca4", size = 20167110, upload-time = "2026-06-15T12:48:59.152Z" }, + { url = "https://files.pythonhosted.org/packages/99/40/540a2fe3c49ce1709ff2015de20d9a351264fb442f8998f92cf0ba7e279e/onnx-1.22.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33ce94119bbb7f05d9caea4ea7549f5185a54369f6bbc9f70171bd5ee6935bbc", size = 18892738, upload-time = "2026-06-15T12:49:02.139Z" }, + { url = "https://files.pythonhosted.org/packages/f8/0c/f41d5b89c38fb2ec410ab23c24fa110af786093b140644f7f953e436743b/onnx-1.22.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:87a3077958f66f9a26dec10077ac28326d9cec2cbe1f0b040947243449754573", size = 19110354, upload-time = "2026-06-15T12:49:05.031Z" }, + { url = "https://files.pythonhosted.org/packages/11/8e/9f41d132855e93c2808cdd4afab1b5af67bd5e82e4a4fa9248006e4df87e/onnx-1.22.0-cp310-cp310-win32.whl", hash = "sha256:8a5eccce2d5fc6c5046928a9aa7cdd9750ea4a586f8de341d3d40d820c35fdec", size = 17083595, upload-time = "2026-06-15T12:49:08.599Z" }, + { url = "https://files.pythonhosted.org/packages/e8/52/86caff81786a5428485795c79175ae2b12a630795bcb267b84e5f9e98450/onnx-1.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:5c1c0408a9d4b4df33851672e5fc7590b96301ee123396d608f9ab6f045ab06b", size = 17215270, upload-time = "2026-06-15T12:49:11.483Z" }, + { url = "https://files.pythonhosted.org/packages/0c/55/30825c02c92a0380ce84c3feeeec95d329fa77548ba58cb10ad4bbfd83c6/onnx-1.22.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:2d8f229a553fa440fe623ed7b36fca5e7762da3af871c3f8f8ce451df73e2914", size = 20167891, upload-time = "2026-06-15T12:49:14.212Z" }, + { url = "https://files.pythonhosted.org/packages/4b/24/cd4ab52ecaf41c3fbed674772ccbfe39041cb257b8471a47a37e48bff3f8/onnx-1.22.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1a89a7cb9ba13d78f009bdec448ec82a98972589734f157022a2bff7a5973a6", size = 18892720, upload-time = "2026-06-15T12:49:16.904Z" }, + { url = "https://files.pythonhosted.org/packages/2b/a0/c9d9d56ceadb1c0a90a7cbec5a0510520ab6538938944fa84548e4b5b054/onnx-1.22.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1d0a2bdb15eb2b3cb65c438f3423d9620d14fdce32f92380e6bb1b2e09568ef5", size = 19110720, upload-time = "2026-06-15T12:49:19.812Z" }, + { url = "https://files.pythonhosted.org/packages/0a/6e/e43e5a68d9cadde55df75310027f87127333a77e5ddcea14c73e96a10cac/onnx-1.22.0-cp311-cp311-win32.whl", hash = "sha256:239958534464612fbcb6ed23d5228aaa925b39b8773f58726809ffdccb4edd1c", size = 17083746, upload-time = "2026-06-15T12:49:22.935Z" }, + { url = "https://files.pythonhosted.org/packages/54/57/cc0a9f2cf4522e42829d089927b4b75924d32f50dca237482e7b741df003/onnx-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:8561a2c00041c07e08db0c228593b5b4694100398685f348532af7dbb84189da", size = 17215684, upload-time = "2026-06-15T12:49:26.084Z" }, + { url = "https://files.pythonhosted.org/packages/c9/99/0f049f9eaa06c8383060c5f0a338e3a6caac8822e6e326c9162f05abf95a/onnx-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:8907b9b9389893bc0dc6314cc00ee1e3a69844e48d689eacc6a0340411a7da58", size = 17210398, upload-time = "2026-06-15T12:49:29.091Z" }, + { url = "https://files.pythonhosted.org/packages/ee/6a/481561f1093834376ed493e4ca42a73e5be0d50031f2969c86593bdc7c96/onnx-1.22.0-cp312-abi3-macosx_12_0_universal2.whl", hash = "sha256:596fbf0490947533c1c1045ba860851dc9fb77471023dac9a71ba5b42ceab103", size = 20167081, upload-time = "2026-06-15T12:49:32.078Z" }, + { url = "https://files.pythonhosted.org/packages/84/55/b34fc2aa30aa54b4a775402d24c4082242c720283a274fe976ac8eb94480/onnx-1.22.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae5a563f281cd9d2845622cecf6c092a57e4ee1b138f66fdbbdd4200567a5e16", size = 18889249, upload-time = "2026-06-15T12:49:34.7Z" }, + { url = "https://files.pythonhosted.org/packages/09/a6/bd32357e6cc1ecb473afd78193d7231724f284435d2db25696ecfaaa1503/onnx-1.22.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:955e02e1f6d385b53d52f9cd7b9cdf5caf417c300bcfe3c64c6d542be763845b", size = 19106514, upload-time = "2026-06-15T12:49:37.424Z" }, + { url = "https://files.pythonhosted.org/packages/5a/9d/3af461ac6c714b8b369cb71499659932f4f12cfb066250b62f7567c3d530/onnx-1.22.0-cp312-abi3-pyemscripten_2025_0_wasm32.whl", hash = "sha256:82e9f27fc1223cb06d68a56bed6f9d3caf3d0dad1b61bce45006d529b15bd94c", size = 16966387, upload-time = "2026-06-15T12:49:40.918Z" }, + { url = "https://files.pythonhosted.org/packages/d0/f0/68195b5e5a53e333faf2660f5352ee43738d0e42fc5216cc6b1871a9fbfb/onnx-1.22.0-cp312-abi3-win32.whl", hash = "sha256:cc8b66b312f8f03a53e268afb67180a2d97dd12cc79e2b61361c6c0073448016", size = 17081568, upload-time = "2026-06-15T12:49:43.398Z" }, + { url = "https://files.pythonhosted.org/packages/13/a8/734725bb703c5fabb687f79c79e51249475212b3eb37771ac4a4ac9b487f/onnx-1.22.0-cp312-abi3-win_amd64.whl", hash = "sha256:72ccebab3bac07215c204ce8848d42e78eaaa666badbf72d25cd359b9f269e3a", size = 17213290, upload-time = "2026-06-15T12:49:45.933Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2a/8ce48d8ae26a8761ad4e5dc771961b155c5c3c7c8540ec7f2f2d71b69af0/onnx-1.22.0-cp312-abi3-win_arm64.whl", hash = "sha256:f3c120dcdb70ad738f3c061b32798f408ea299eb69f84dd69ab4a6bf3c2ec01f", size = 17207030, upload-time = "2026-06-15T12:49:48.635Z" }, + { url = "https://files.pythonhosted.org/packages/f3/13/47323b97846387848efb1044ded11bb94b83526f3d1fbdb37c6480d4520f/onnx-1.22.0-cp314-cp314t-macosx_12_0_universal2.whl", hash = "sha256:19e45e4af88e3fe3261458d4b8cc461957ae2782a358a3560503569bf3b23b72", size = 20176465, upload-time = "2026-06-15T12:49:51.311Z" }, + { url = "https://files.pythonhosted.org/packages/13/0c/d3b8a7e7eee123938586c608bb9894b5723f2342b9450c0eec59fbec7099/onnx-1.22.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c21a0e59fd967a95b358e4a6e756d1f1eec2d304a83480f329f66e30d2bf0223", size = 18894028, upload-time = "2026-06-15T12:49:54.451Z" }, + { url = "https://files.pythonhosted.org/packages/b8/8a/da2a97ab46fe6e0cd9beb3ac14603a22f5be492f9ca347faf8233a07bb33/onnx-1.22.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2632406b8f523ef2e2873c363f90b20a3d88c0fbcfac757d3addffccf8f452c2", size = 19110420, upload-time = "2026-06-15T12:49:57.665Z" }, + { url = "https://files.pythonhosted.org/packages/b9/a3/ce984063017518307ebfaa545782fc400e593dc2d7fdf4f23ce4be1ed197/onnx-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:a3a39fc4643867aecb33417fdddb11e308ee79d2d4a584b9d50cc7aec2091b13", size = 17237547, upload-time = "2026-06-15T12:50:00.382Z" }, + { url = "https://files.pythonhosted.org/packages/00/50/257a880384a1dd502d543b0067945074d63cd17d0840e958355bc8197da8/onnx-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:8e268cdc0547e3949799ffd4a44451dc2b9080b57d0824a2db680b6ec65506f0", size = 17231391, upload-time = "2026-06-15T12:50:03.047Z" }, +] + [[package]] name = "onnxruntime" version = "1.23.2" @@ -2417,11 +2510,14 @@ resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.13.*' and sys_platform == 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32'", + "python_full_version == '3.12.*' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version == '3.13.*' and sys_platform == 'emscripten'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'emscripten'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.12.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ { name = "flatbuffers", marker = "python_full_version >= '3.11'" }, @@ -2475,6 +2571,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/b0/2291689e3ec4723fbf5bbf3b54afcd7b160f9ddc98ca7aedfd0132af5677/openai-2.45.0-py3-none-any.whl", hash = "sha256:5df105f5f8c9b711fcb9d06d2d3888cebc82506db216484c14a4e53cdf651777", size = 1629470, upload-time = "2026-07-09T18:02:42.21Z" }, ] +[[package]] +name = "optimum" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging" }, + { name = "torch" }, + { name = "transformers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f0/69/e1e9fe4d54f6b1b90cc278d6da74dd90eb4d9fd9228882886d7c275712e2/optimum-2.1.0.tar.gz", hash = "sha256:0a2a13f91500e41d34863ffdb08fcb886b3ce68a84a386e59653e3064a45dd4b", size = 125896, upload-time = "2025-12-19T10:47:18.571Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/98/c409ed937331839fdadc03cef6ebd19982bf3834711134db8898eeb31585/optimum-2.1.0-py3-none-any.whl", hash = "sha256:bc3af32e1236a9b2c2ca1d27ed9d3ab1b6591e24c6bcd47f9671a8198a30ea88", size = 161231, upload-time = "2025-12-19T10:47:17.054Z" }, +] + +[[package]] +name = "optimum-onnx" +version = "0.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "onnx" }, + { name = "optimum" }, + { name = "transformers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/da/3a0073af8f436d72c1e4d9c655c00628b857bd1d9ccc101d35301d5bb2df/optimum_onnx-0.1.0.tar.gz", hash = "sha256:182c54b25eddaded1618af7b58516da34749393a987ec7111f74677f249676f9", size = 165531, upload-time = "2025-12-23T14:20:18.97Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/89/4be9d226bc74fd0eb405d1efea62e86d6f0f31841dae9c5898ee12eb482f/optimum_onnx-0.1.0-py3-none-any.whl", hash = "sha256:0301ec7a6ec5c77a57581e9970d380a6dc104bdb8f15b282e05af40d829c2eda", size = 194155, upload-time = "2025-12-23T14:20:17.741Z" }, +] + +[package.optional-dependencies] +onnxruntime = [ + { name = "onnxruntime", version = "1.23.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "onnxruntime", version = "1.27.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] + [[package]] name = "packaging" version = "26.2" @@ -2557,11 +2690,14 @@ resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'emscripten'", "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", "python_full_version == '3.13.*' and sys_platform == 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32'", + "python_full_version == '3.12.*' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", "python_full_version == '3.13.*' and sys_platform == 'emscripten'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'emscripten'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", "python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", - "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.12.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, @@ -2770,6 +2906,11 @@ langextract = [ { name = "more-itertools" }, { name = "openai" }, ] +onnxruntime = [ + { name = "optimum" }, + { name = "optimum-onnx", extra = ["onnxruntime"] }, + { name = "transformers" }, +] server = [ { name = "flask" }, { name = "gunicorn", marker = "sys_platform != 'win32'" }, @@ -2818,6 +2959,8 @@ requires-dist = [ { name = "onnxruntime", marker = "python_full_version == '3.10.*' and extra == 'gliner'", specifier = ">=1.19,<1.24.1" }, { name = "onnxruntime", marker = "python_full_version >= '3.11' and extra == 'gliner'", specifier = ">=1.19" }, { name = "openai", marker = "extra == 'langextract'", specifier = ">=1.50.0,<3.0.0" }, + { name = "optimum", marker = "extra == 'onnxruntime'", specifier = ">=2.1.0,<3.0.0" }, + { name = "optimum-onnx", extras = ["onnxruntime"], marker = "extra == 'onnxruntime'", specifier = ">=0.1.0,<2.0.0" }, { name = "phonenumbers", specifier = ">=9.0.28,<10.0.0" }, { name = "pydantic", specifier = ">=2.12.5,<3.0.0" }, { name = "pyyaml", specifier = ">=6.0.3,<7.0.0" }, @@ -2828,10 +2971,11 @@ requires-dist = [ { name = "stanza", marker = "extra == 'stanza'", specifier = ">=1.11.1,<2.0.0" }, { name = "tldextract", specifier = ">=5.3.1,<6.0.0" }, { name = "transformers", marker = "extra == 'gliner'" }, + { name = "transformers", marker = "extra == 'onnxruntime'", specifier = ">=4.0.0,<5.0.0" }, { name = "transformers", marker = "extra == 'transformers'", specifier = ">=4.0.0,<6.0.0" }, { name = "waitress", marker = "sys_platform == 'win32' and extra == 'server'", specifier = ">=2.0.0,<4.0.0" }, ] -provides-extras = ["server", "transformers", "stanza", "azure-ai-language", "ahds", "gliner", "langextract"] +provides-extras = ["server", "transformers", "stanza", "azure-ai-language", "ahds", "gliner", "langextract", "onnxruntime"] [package.metadata.requires-dev] dev = [