onnx-diagnostic 0.8.7__py3-none-any.whl → 0.8.8__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.
@@ -3,5 +3,5 @@ Patches, Investigates onnx models.
3
3
  Functions, classes to dig into a model when this one is right, slow, wrong...
4
4
  """
5
5
 
6
- __version__ = "0.8.7"
6
+ __version__ = "0.8.8"
7
7
  __author__ = "Xavier Dupré"
@@ -973,7 +973,7 @@ def main(
973
973
  kwargs=export_inputs,
974
974
  dynamic_shapes=use_dyn_not_str(dynamic_shapes),
975
975
  )
976
- patches = details.patches_involded_in_graph(ep.graph)
976
+ patches = details.patches_involved_in_graph(ep.graph)
977
977
  report = details.make_report(patches, format="rst")
978
978
  with open(f"{basename}.patches_details.rst", "w") as f:
979
979
  f.write(report)
@@ -1,6 +1,11 @@
1
- from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
1
+ import inspect
2
+ import os
3
+ import textwrap
4
+ from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Tuple, Union
2
5
  import torch
6
+ from .dynamic_shapes import ModelInputs
3
7
  from .onnx_plug import EagerDirectReplacementWithOnnx
8
+ from ..helpers import string_type
4
9
 
5
10
 
6
11
  def get_main_dispatcher(
@@ -70,6 +75,7 @@ def to_onnx(
70
75
  inline: bool = True,
71
76
  ) -> Any:
72
77
  """
78
+ Exports one model into ONNX.
73
79
  Common API for exporters. By default, the models are optimized to use the
74
80
  most efficient kernels implemented in :epkg:`onnxruntime`.
75
81
 
@@ -126,8 +132,12 @@ def to_onnx(
126
132
  from experimental_experiment.xbuilder import OptimizationOptions
127
133
 
128
134
  options = None
135
+ export_options = None
129
136
  if exporter_kwargs is not None:
130
137
  options = exporter_kwargs.pop("options", None)
138
+ export_options = exporter_kwargs.pop("export_options", None)
139
+ if export_options is None:
140
+ export_options = ExportOptions(save_ep=save_ep)
131
141
  if options is None and optimize:
132
142
  options = OptimizationOptions(
133
143
  patterns="default+onnxruntime" if optimizer_for_ort else "default"
@@ -138,7 +148,7 @@ def to_onnx(
138
148
  else None
139
149
  )
140
150
 
141
- return _to_onnx(
151
+ proto, opt_stats = _to_onnx(
142
152
  mod,
143
153
  args=args,
144
154
  kwargs=kwargs,
@@ -150,16 +160,52 @@ def to_onnx(
150
160
  dynamic_shapes=dynamic_shapes,
151
161
  large_model=True,
152
162
  output_dynamic_shapes=output_dynamic_shapes,
153
- export_options=ExportOptions(save_ep=save_ep),
163
+ export_options=export_options,
154
164
  options=options,
155
165
  inline=inline,
156
166
  dispatcher=main_dispatcher,
157
167
  optimize=optimize,
168
+ return_optimize_report=True,
158
169
  **(exporter_kwargs or {}),
159
170
  )
171
+ if opt_stats and filename and os.path.exists(filename):
172
+ import pandas
173
+
174
+ stat_filename = f"{os.path.splitext(filename)[0]}.opt.xlsx"
175
+ pattern_stats = []
176
+ for k, v in opt_stats.items():
177
+ if "time" in k:
178
+ pattern_stats.append(dict(level="main", pattern=k, time_in=v))
179
+ pattern_stats.extend(
180
+ [{**obs, "level": "detailed"} for obs in opt_stats["optimization"]]
181
+ )
182
+ df = pandas.DataFrame(pattern_stats)
183
+ df.to_excel(stat_filename, index=False)
184
+ cols = [
185
+ c
186
+ for c in [
187
+ "level",
188
+ "pattern",
189
+ "time_in",
190
+ "iteration",
191
+ "inlined",
192
+ "removed",
193
+ "added",
194
+ "instances",
195
+ "changed",
196
+ "scale",
197
+ ]
198
+ if c in df.columns
199
+ ]
200
+ agg = {k: "sum" for k in cols if k not in ("level", "pattern")}
201
+ agg.update(dict(iteration="max", instances="mean"))
202
+ agg = {k: v for k, v in agg.items() if k in df.columns}
203
+ stat_filename = f"{os.path.splitext(filename)[0]}.opt.agg.xlsx"
204
+ df[cols].groupby(["level", "pattern"]).agg(agg).to_excel(stat_filename)
205
+
206
+ return proto
160
207
 
161
208
  if exporter in ("dynamo", "onnx-dynamo"):
162
- import os
163
209
  from ..helpers import flatten_object
164
210
  import onnxscript.rewriter.ort_fusions as ort_fusions
165
211
 
@@ -226,7 +272,6 @@ def to_onnx(
226
272
  return epo
227
273
 
228
274
  if exporter == "modelbuilder":
229
- import os
230
275
  from ..helpers import flatten_object, string_type
231
276
  from ..helpers.model_builder_helper import create_model_builder, save_model_builder
232
277
 
@@ -267,3 +312,247 @@ def to_onnx(
267
312
  return onx
268
313
 
269
314
  raise ValueError(f"Unknown exporter={exporter!r}")
315
+
316
+
317
+ class _WrapperToExportMethodToOnnx(torch.nn.Module):
318
+ """
319
+ Wraps an existing models in order to spy on inputs.
320
+ This is used by :func:`onnx_diagnostic.export.api.method_to_onnx`.
321
+ """
322
+
323
+ def __init__(
324
+ self,
325
+ mod: "torch.nn.Module",
326
+ method_name: str = "forward",
327
+ input_names: Optional[Sequence[str]] = None,
328
+ target_opset: Optional[Union[int, Dict[str, int]]] = None,
329
+ verbose: int = 0,
330
+ filename: Optional[str] = None,
331
+ output_names: Optional[List[str]] = None,
332
+ output_dynamic_shapes: Optional[Union[Dict[str, Any], Tuple[Any]]] = None,
333
+ exporter: str = "onnx-dynamo",
334
+ exporter_kwargs: Optional[Dict[str, Any]] = None,
335
+ save_ep: Optional[str] = None,
336
+ optimize: bool = True,
337
+ optimizer_for_ort: bool = True,
338
+ use_control_flow_dispatcher: bool = False,
339
+ onnx_plugs: Optional[List[EagerDirectReplacementWithOnnx]] = None,
340
+ inline: bool = True,
341
+ convert_after_n_calls: int = 2,
342
+ patch_kwargs: Optional[Dict[str, Any]] = None,
343
+ skip_kwargs_names: Optional[Set[str]] = None,
344
+ dynamic_shapes: Optional[Union[Dict[str, Any], Tuple[Any]]] = None,
345
+ ):
346
+ super().__init__()
347
+ self._model_to_call = mod
348
+ self._method_name = method_name
349
+ self._method_call = (
350
+ self._model_to_call.forward
351
+ if method_name == "forward"
352
+ else getattr(mod, method_name)
353
+ )
354
+ self._inputs: List[Tuple[Tuple[Any, ...], Dict[str, Any]]] = []
355
+ self._convert_after_n_calls = convert_after_n_calls
356
+ self._patch_kwargs = patch_kwargs
357
+ self._method_src = None
358
+ self.verbose = verbose
359
+ self.skip_kwargs_names = skip_kwargs_names
360
+ self.dynamic_shapes = dynamic_shapes
361
+ self._to_onnx_kwargs = dict(
362
+ input_names=input_names,
363
+ target_opset=target_opset,
364
+ verbose=verbose,
365
+ filename=filename,
366
+ output_names=output_names,
367
+ output_dynamic_shapes=output_dynamic_shapes,
368
+ exporter=exporter,
369
+ exporter_kwargs=exporter_kwargs,
370
+ save_ep=save_ep,
371
+ optimize=optimize,
372
+ optimizer_for_ort=optimizer_for_ort,
373
+ use_control_flow_dispatcher=use_control_flow_dispatcher,
374
+ onnx_plugs=onnx_plugs,
375
+ inline=inline,
376
+ )
377
+ self._export_done = False
378
+
379
+ def __str__(self) -> str:
380
+ return self.__repr__()
381
+
382
+ def __repr__(self) -> str:
383
+ return (
384
+ f"{self.__class__.__name__}({self._model_to_call.__class__.__name__}."
385
+ f"{self._method_name})"
386
+ )
387
+
388
+ def forward(self, *args, **kwargs):
389
+ if not self._export_done:
390
+ self._inputs.append(
391
+ (
392
+ args,
393
+ (
394
+ kwargs
395
+ if not kwargs or not self.skip_kwargs_names
396
+ else {
397
+ k: v for k, v in kwargs.items() if k not in self.skip_kwargs_names
398
+ }
399
+ ),
400
+ )
401
+ )
402
+ if self.verbose:
403
+ print(
404
+ f"[method_to_onnx] input[{len(self._inputs)-1}]: "
405
+ f"{string_type(self._inputs[-1], with_shape=True)}"
406
+ )
407
+ if len(self._inputs) >= self._convert_after_n_calls:
408
+ self._convert_method_to_onnx()
409
+ del self._inputs[:]
410
+ self._export_done = True
411
+ return self._method_call(*args, **kwargs)
412
+
413
+ def _convert_method_to_onnx(self):
414
+
415
+ def make_method(self):
416
+ inner_sig = inspect.signature(self._method_call)
417
+ params = [
418
+ p.replace(annotation=inspect._empty) for p in inner_sig.parameters.values()
419
+ ]
420
+ simple_sig = inspect.Signature(params, return_annotation=inspect._empty)
421
+ args = str(simple_sig)[1:-1]
422
+ calls_args = ", ".join(f"{p}={p}" for p in simple_sig.parameters)
423
+ src = textwrap.dedent(
424
+ f"""
425
+ def f(self, {args}):
426
+ return self._method_call({calls_args})
427
+ """
428
+ )
429
+ self._method_src = src
430
+ ns = {}
431
+ try:
432
+ exec(src, ns)
433
+ except NameError as e:
434
+ raise NameError(f"Unable to compile due to {e}\n{src}") from e
435
+ return ns["f"]
436
+
437
+ class WrapWithExactSignature(torch.nn.Module):
438
+ def __init__(self, parent):
439
+ super().__init__()
440
+ self._model_to_call = parent._model_to_call
441
+ self._method_call = parent._method_call
442
+
443
+ forward = make_method(self)
444
+
445
+ compiled_model = WrapWithExactSignature(self)
446
+
447
+ if self.dynamic_shapes is None:
448
+ mi = ModelInputs(compiled_model, self._inputs)
449
+ ds = mi.guess_dynamic_shapes()
450
+ if self.verbose:
451
+ print(f"[method_to_onnx] guess_dynamic_shapes={string_type(ds)}")
452
+ a, kw, nds = mi.move_to_kwargs(*self._inputs[-1], ds)
453
+ else:
454
+ a, kw = self._inputs[-1]
455
+ nds = [self.dynamic_shapes]
456
+ if self.verbose:
457
+ print(f"[method_to_onnx] export args={string_type(a, with_shape=True)}")
458
+ print(f"[method_to_onnx] export kwargs={string_type(kw, with_shape=True)}")
459
+ print(f"[method_to_onnx] dynamic_shapes={string_type(nds)}")
460
+ if self._patch_kwargs is None:
461
+ to_onnx(
462
+ compiled_model,
463
+ args=a,
464
+ kwargs=kw,
465
+ dynamic_shapes=nds[-1],
466
+ **self._to_onnx_kwargs,
467
+ )
468
+ return
469
+ from ..torch_export_patches import torch_export_patches
470
+
471
+ with torch_export_patches(**self._patch_kwargs):
472
+ to_onnx(
473
+ compiled_model,
474
+ args=a,
475
+ kwargs=kw,
476
+ dynamic_shapes=nds[-1],
477
+ **self._to_onnx_kwargs,
478
+ )
479
+
480
+
481
+ def method_to_onnx(
482
+ mod: "torch.nn.Module",
483
+ method_name: str = "forward",
484
+ input_names: Optional[Sequence[str]] = None,
485
+ target_opset: Optional[Union[int, Dict[str, int]]] = None,
486
+ verbose: int = 0,
487
+ filename: Optional[str] = None,
488
+ output_names: Optional[List[str]] = None,
489
+ output_dynamic_shapes: Optional[Union[Dict[str, Any], Tuple[Any]]] = None,
490
+ exporter: str = "onnx-dynamo",
491
+ exporter_kwargs: Optional[Dict[str, Any]] = None,
492
+ save_ep: Optional[str] = None,
493
+ optimize: bool = True,
494
+ optimizer_for_ort: bool = True,
495
+ use_control_flow_dispatcher: bool = False,
496
+ onnx_plugs: Optional[List[EagerDirectReplacementWithOnnx]] = None,
497
+ inline: bool = True,
498
+ convert_after_n_calls: int = 2,
499
+ patch_kwargs: Optional[Dict[str, Any]] = None,
500
+ skip_kwargs_names: Optional[Set[str]] = None,
501
+ dynamic_shapes: Optional[Union[Dict[str, Any], Tuple[Any]]] = None,
502
+ ) -> Callable:
503
+ """
504
+ Exports one method into ONNX for a module into ONNX.
505
+ It returns a new method which must be called by the user
506
+ at least twice with different values for the dynamic dimension
507
+ between triggering the conversion into ONNX.
508
+
509
+ :param mod_meth: function to export into ONNX
510
+ :param input_names: input names for the onnx model (optional)
511
+ :param target_opset: opset to target, if not specified, each converter
512
+ keeps its default value
513
+ :param verbose: verbosity level
514
+ :param filename: output filename, mandatory, the onnx model is saved on disk
515
+ :param output_names: to change the output of the onnx model
516
+ :param output_dynamic_shapes: to overwrite the dynamic shapes names
517
+ :param exporter: exporter to use (``onnx-dynamo``, ``modelbuilder``, ``custom``)
518
+ :param exporter_kwargs: additional parameters sent to the exporter
519
+ :param save_ep: saves the exported program
520
+ :param optimize: optimizes the model
521
+ :param optimizer_for_ort: optimizes the model for onnxruntime
522
+ :param use_control_flow_dispatcher: use the dispatcher created to supported
523
+ custom loops (see :func:`onnx_diagnostic.export.control_flow_onnx.loop_for_onnx`)
524
+ :param onnx_plugs: the code was modified to replace some parts with onnx translation
525
+ :param inline: inline local functions
526
+ :param convert_after_n_calls: converts the model after this number of calls.
527
+ :param patch_kwargs: patch arguments
528
+ :param skip_kwargs_names: use default values for these parameters part of
529
+ the signature of the method to export
530
+ :param dynamic_shapes: dynamic shapes to use if the guessed ones are not right
531
+ :return: the output of the selected exporter, usually a structure including
532
+ an onnx model
533
+
534
+ See :ref:`l-plot-tiny-llm-export-method-generate` for an example.
535
+ """
536
+ wrapped_model = _WrapperToExportMethodToOnnx(
537
+ mod=mod,
538
+ method_name=method_name,
539
+ input_names=input_names,
540
+ target_opset=target_opset,
541
+ verbose=verbose,
542
+ filename=filename,
543
+ output_names=output_names,
544
+ output_dynamic_shapes=output_dynamic_shapes,
545
+ exporter=exporter,
546
+ exporter_kwargs=exporter_kwargs,
547
+ save_ep=save_ep,
548
+ optimize=optimize,
549
+ optimizer_for_ort=optimizer_for_ort,
550
+ use_control_flow_dispatcher=use_control_flow_dispatcher,
551
+ onnx_plugs=onnx_plugs,
552
+ inline=inline,
553
+ convert_after_n_calls=convert_after_n_calls,
554
+ patch_kwargs=patch_kwargs,
555
+ skip_kwargs_names=skip_kwargs_names,
556
+ dynamic_shapes=dynamic_shapes,
557
+ )
558
+ return wrapped_model
@@ -352,6 +352,19 @@ class CoupleInputsDynamicShapes:
352
352
  else None
353
353
  )
354
354
  assert type(inputs) is dict, f"Unexpected type for inputs {type(inputs)}"
355
+ if set(inputs) != set(ds):
356
+ not_in_ds = {k for k in inputs if k not in ds}
357
+ not_in_inputs = {k for k in ds if k not in inputs}
358
+ assert not_in_inputs == {"kwargs"} and set(ds["kwargs"]) == not_in_ds, (
359
+ f"Keys mismatch between inputs {set(inputs)} and ds={set(ds)}, "
360
+ f"inputs={string_type(inputs, with_shape=True)}, ds={ds}, "
361
+ f"not_in_ds={not_in_ds}, not_in_inputs={not_in_inputs}"
362
+ )
363
+ # Tweak...
364
+ kws = ds["kwargs"]
365
+ del ds["kwargs"]
366
+ ds.update(kws)
367
+
355
368
  assert set(inputs) == set(ds), (
356
369
  f"Keys mismatch between inputs {set(inputs)} and ds={set(ds)}, "
357
370
  f"inputs={string_type(inputs, with_shape=True)}, ds={ds}"
@@ -366,13 +379,15 @@ class CoupleInputsDynamicShapes:
366
379
  return dvalue if dvalue else None
367
380
 
368
381
  # A custom class.
369
- assert inputs.__class__ in torch.utils._pytree.SUPPORTED_NODES, (
382
+ assert inputs is None or inputs.__class__ in torch.utils._pytree.SUPPORTED_NODES, (
370
383
  f"Class {inputs.__class__.__name__!r} was not registered using "
371
384
  f"torch.utils._pytree.register_pytree_node, it is not possible to "
372
385
  f"map this class with the given dynamic shapes."
373
386
  )
374
387
  if flatten_unflatten:
375
388
  flatunflat = flatten_unflatten_for_dynamic_shapes(inputs)
389
+ if isinstance(flatunflat, (list, tuple, dict)) and len(flatunflat) == 0:
390
+ return flatunflat
376
391
  res = cls._generic_walker_step(
377
392
  processor, flatunflat, ds, flatten_unflatten=flatten_unflatten
378
393
  )
@@ -667,6 +682,11 @@ class ModelInputs:
667
682
  if self.signature
668
683
  else None
669
684
  )
685
+ self.forward_parameters_kinds = (
686
+ {p.name: p.kind for p in self.signature.parameters.values()}
687
+ if self.signature
688
+ else None
689
+ )
670
690
  self.forward_ordered_parameter_names = (
671
691
  list(self.signature.parameters) if self.signature else None
672
692
  )
@@ -973,7 +993,13 @@ class ModelInputs:
973
993
  len(s1) == 1
974
994
  ), f"Different numbers of positional arguments {s1} for {self.full_name}"
975
995
  s2 = set(tuple(sorted(set(i[1]))) for i in self.inputs)
976
- assert len(s2) == 1, f"Different named arguments {s2} for {self.full_name}"
996
+ assert len(s2) > 0, f"empty {s2} for {self.full_name}"
997
+ if len(s2) > 1:
998
+ # We need to keep the largest set of inputs, the one including all the others.
999
+ sum_s2 = set()
1000
+ for s in s2:
1001
+ sum_s2 |= set(s)
1002
+ s2 = {tuple(sum_s2)}
977
1003
  args = []
978
1004
  kwargs = {}
979
1005
  for i in range(s1.pop()):
@@ -993,12 +1019,18 @@ class ModelInputs:
993
1019
  f"\ninputs[1]={string_type(self.inputs[1], with_shape=True)}"
994
1020
  )
995
1021
 
996
- objs = [_[1][name] for _ in self.inputs]
1022
+ objs = [_[1][name] for _ in self.inputs if name in _[1]]
997
1023
  kwargs[name] = self.guess_dynamic_shape_object(
998
1024
  *objs,
999
1025
  auto=auto if isinstance(auto, bool) else f"{auto}_{i}I",
1000
1026
  msg=lambda name=name: f" failing input {name!r}",
1001
1027
  )
1028
+ # reordering
1029
+ if kwargs is not None and self.forward_ordered_parameter_names:
1030
+ kwargs1 = {
1031
+ p: kwargs[p] for p in self.forward_ordered_parameter_names if p in kwargs
1032
+ }
1033
+ kwargs = {**kwargs1, **{k: v for k, v in kwargs.items() if k not in kwargs1}}
1002
1034
  return tuple(args), kwargs
1003
1035
 
1004
1036
  def move_to_kwargs(
@@ -1061,6 +1093,16 @@ class ModelInputs:
1061
1093
  f"and kwargs={set(kwargs)}, "
1062
1094
  f"forward_ordered_parameter_names={self.forward_ordered_parameter_names}"
1063
1095
  )
1096
+ if kwargs is not None and self.forward_ordered_parameter_names:
1097
+ kwargs1 = {
1098
+ p: kwargs[p] for p in self.forward_ordered_parameter_names if p in kwargs
1099
+ }
1100
+ kwargs = {**kwargs1, **{k: v for k, v in kwargs.items() if k not in kwargs1}}
1101
+ if kw_dyn is not None and self.forward_ordered_parameter_names:
1102
+ kw_dyn1 = {
1103
+ p: kw_dyn[p] for p in self.forward_ordered_parameter_names if p in kw_dyn
1104
+ }
1105
+ kw_dyn = {**kw_dyn1, **{k: v for k, v in kw_dyn.items() if k not in kw_dyn1}}
1064
1106
  return args, kwargs, (tuple(), kw_dyn)
1065
1107
 
1066
1108
  def validate_inputs_for_export(
@@ -210,6 +210,7 @@ def make_fake_with_dynamic_dimensions(
210
210
  This uses function :func:`onnx_diagnostic.helpers.fake_tensor_helper.make_fake`.
211
211
  Parameter ``existing`` is used to reused the same object when the dynamic
212
212
  dimension is given the same name as another one.
213
+ This function works with caches only if ``transformers>=4.57``.
213
214
 
214
215
  A simple tensor:
215
216
 
@@ -28,14 +28,6 @@ class CacheKeyValue:
28
28
  ]
29
29
  self.key_cache = [layer.keys for layer in layers]
30
30
  self.value_cache = [layer.values for layer in layers]
31
- if None in self.key_cache or None in self.value_cache:
32
- from .helper import string_type
33
-
34
- raise AssertionError(
35
- f"issue with key_cache={string_type(self.key_cache)}, "
36
- f"or value_cache={string_type(self.value_cache)}, "
37
- f"cache.layers={string_type(cache.layers)}"
38
- )
39
31
  elif cache is not None and hasattr(cache, "key_cache"):
40
32
  self.key_cache = cache.key_cache
41
33
  self.value_cache = cache.value_cache
@@ -105,6 +105,8 @@ class FakeTensorContext:
105
105
  reduced_tensor = self.from_tensor(true_tensor, static_shapes=True).sum(
106
106
  axis=tuple(sorted(sh)), keepdim=True
107
107
  )
108
+ if len(reduced_tensor.shape) == 0 == len(new_shape):
109
+ return reduced_tensor
108
110
  return reduced_tensor.expand(*new_shape)
109
111
 
110
112
  def make_fake(self, x: Any) -> Optional["FakeTensor"]: # noqa: F821
@@ -144,19 +146,22 @@ class FakeTensorContext:
144
146
  """
145
147
  See
146
148
  :func:`onnx_diagnostic.export.shape_helper.make_fake_with_dynamic_dimensions`.
149
+ If caches are used, it requires ``transformers>=4.57``.
147
150
  """
148
151
  if x is None:
149
152
  return None, None
150
- if isinstance(x, (list, tuple)):
153
+ if type(x) in (list, tuple):
151
154
  return x.__class__(
152
155
  [
153
156
  self.make_fake_with_dynamic_dimensions(i, dynamic_shapes=ds)
154
157
  for i, ds in zip(x, dynamic_shapes)
155
158
  ]
156
159
  )
157
- if isinstance(x, dict):
160
+ if type(x) is dict:
158
161
  return {
159
- k: self.make_fake_with_dynamic_dimensions(v, dynamic_shapes=dynamic_shapes[k])
162
+ k: self.make_fake_with_dynamic_dimensions(
163
+ v, dynamic_shapes=dynamic_shapes[k] if dynamic_shapes else None
164
+ )
160
165
  for k, v in x.items()
161
166
  }
162
167
  if x.__class__.__name__ in {"DynamicCache", "StaticCache", "HybridCache"}:
@@ -187,6 +192,17 @@ class FakeTensorContext:
187
192
  x.cross_attention_cache, dynamic_shapes=dynamic_shapes[1]
188
193
  )
189
194
  return x
195
+ if x.__class__.__name__ == "BaseModelOutput":
196
+ assert (
197
+ list(x.keys()) == ["last_hidden_state"] and x.last_hidden_state is not None
198
+ ), (
199
+ f"Field 'last_hidden_state' is empty for {type(x)} or other fields "
200
+ f"{list(x.keys())} are used."
201
+ )
202
+ x.last_hidden_state = self.make_fake_with_dynamic_dimensions(
203
+ x.last_hidden_state, dynamic_shapes=dynamic_shapes[0]
204
+ )
205
+ return x
190
206
  if hasattr(x, "shape"):
191
207
  assert dynamic_shapes is None or isinstance(dynamic_shapes, dict), (
192
208
  f"dynamic_shapes must be a dictionary at this stage but "
@@ -197,9 +213,11 @@ class FakeTensorContext:
197
213
  for idim, dim in enumerate(x.shape):
198
214
  if dynamic_shapes is not None and idim in dynamic_shapes:
199
215
  s = dynamic_shapes[idim]
216
+ if s.__class__.__name__ == "Dim":
217
+ s = s.__name__
200
218
  assert isinstance(s, str), (
201
219
  f"Unexpected type {type(s)} in dynamic_shapes={dynamic_shapes} "
202
- f"at index {idim}"
220
+ f"at index {idim}, self._mapping_str={self._mapping_str}"
203
221
  )
204
222
  if s in self._mapping_str:
205
223
  dim = self._mapping_str[s]
@@ -217,10 +235,13 @@ class FakeTensorContext:
217
235
 
218
236
  x = torch.empty(tuple(new_shape), dtype=x.dtype, device=x.device)
219
237
 
220
- t = self.fake_reshape(x, dynamic_shapes) # type: ignore[arg-type]
238
+ t = self.fake_reshape(x, dynamic_shapes) if dynamic_shapes else x # type: ignore[arg-type]
221
239
  assert t.device == x.device, f"device mismatch {x.device} -> {t.device}"
222
240
  assert t.dtype == x.dtype, f"dtype mismatch {x.dtype} -> {t.dtype}"
223
241
  return t
242
+ if isinstance(x, (int, bool, float)):
243
+ # It is a constant, we don't change that.
244
+ return x
224
245
  from ..helpers import string_type
225
246
 
226
247
  raise TypeError(
@@ -704,9 +704,35 @@ def string_type(
704
704
  if obj.__class__.__name__ == "VirtualTensor":
705
705
  if verbose:
706
706
  print(f"[string_type] TT4:{type(obj)}")
707
+
708
+ def _torch_sym_int_to_str(value: "torch.SymInt") -> Union[int, str]: # noqa: F821
709
+ if isinstance(value, str):
710
+ return value
711
+ if hasattr(value, "node") and isinstance(value.node, str):
712
+ return f"{value.node}"
713
+
714
+ from torch.fx.experimental.sym_node import SymNode
715
+
716
+ if hasattr(value, "node") and isinstance(value.node, SymNode):
717
+ # '_expr' is safer than expr
718
+ return str(value.node._expr).replace(" ", "")
719
+
720
+ try:
721
+ val_int = int(value)
722
+ return val_int
723
+ except (
724
+ TypeError,
725
+ ValueError,
726
+ AttributeError,
727
+ torch.fx.experimental.symbolic_shapes.GuardOnDataDependentSymNode,
728
+ ):
729
+ pass
730
+
731
+ raise AssertionError(f"Unable to convert {value!r} into string")
732
+
707
733
  return (
708
734
  f"{obj.__class__.__name__}(name={obj.name!r}, "
709
- f"dtype={obj.dtype}, shape={obj.shape})"
735
+ f"dtype={obj.dtype}, shape={tuple(_torch_sym_int_to_str(_) for _ in obj.shape)})"
710
736
  )
711
737
 
712
738
  if obj.__class__.__name__ == "KeyValuesWrapper":
@@ -775,6 +801,9 @@ def string_type(
775
801
  print(f"[string_type] TT8:{type(obj)}")
776
802
  return repr(obj).replace(" ", "").replace("\n", " ")
777
803
 
804
+ if isinstance(obj, torch.fx.proxy.Proxy):
805
+ return repr(obj)
806
+
778
807
  if ignore:
779
808
  if verbose:
780
809
  print(f"[string_type] CACHE4:{type(obj)}")
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
2
3
  import onnx
3
4
  import numpy as np
@@ -76,6 +77,10 @@ class _InferenceSession:
76
77
  session_options.enable_profiling = enable_profiling
77
78
  if optimized_model_filepath:
78
79
  session_options.optimized_model_filepath = optimized_model_filepath
80
+ session_options.add_session_config_entry(
81
+ "session.optimized_model_external_initializers_file_name",
82
+ f"{os.path.splitext(os.path.split(optimized_model_filepath)[-1])[0]}.data",
83
+ )
79
84
  if log_severity_level is not None:
80
85
  session_options.log_severity_level = log_severity_level
81
86
  if log_verbosity_level is not None:
@@ -172,10 +172,10 @@ def _get_inputs_gemma3(
172
172
  assert expected & set(
173
173
  dummies
174
174
  ), f"Unable to find expected inputs {expected} in loaded inputs {set(dummies)}"
175
- assert sequence_length == dummies["input_ids"].shape[-1], (
176
- f"sequence_length={sequence_length} != {dummies['input_ids'].shape[-1]} for "
177
- f"model class {model.__class__.__name__}"
178
- )
175
+ # assert sequence_length == dummies["input_ids"].shape[-1], (
176
+ # f"sequence_length={sequence_length} != {dummies['input_ids'].shape[-1]} for "
177
+ # f"model class {model.__class__.__name__}"
178
+ # )
179
179
  assert batch_size == dummies["input_ids"].shape[0], (
180
180
  f"batch_size={batch_size} != {dummies['input_ids'].shape[0]} for "
181
181
  f"model class {model.__class__.__name__}"
@@ -191,7 +191,7 @@ class PatchDetails:
191
191
  ep = torch.export.export(
192
192
  model, (), kwargs=inputs, dynamic_shapes=use_dyn_not_str(ds)
193
193
  )
194
- patches = details.patches_involded_in_graph(ep.graph)
194
+ patches = details.patches_involved_in_graph(ep.graph)
195
195
  report = details.make_report(patches, format="rst")
196
196
  print(report)
197
197
  """
@@ -235,7 +235,7 @@ class PatchDetails:
235
235
  """Returns the data for a dataframe."""
236
236
  return [p.to_dict() for p in self.patched]
237
237
 
238
- def patches_involded_in_graph(
238
+ def patches_involved_in_graph(
239
239
  self, graph: "torch.fx.Graph" # noqa: F821
240
240
  ) -> List[Tuple[PatchInfo, List["torch.fx.Node"]]]: # noqa: F821
241
241
  """
@@ -322,7 +322,7 @@ class PatchDetails:
322
322
  """
323
323
  Creates a report based on the involved patches.
324
324
 
325
- :param patches: from method :meth:`patches_involded_in_graph`
325
+ :param patches: from method :meth:`patches_involved_in_graph`
326
326
  :param format: format of the report
327
327
  :return: report
328
328
  """
@@ -22,13 +22,22 @@ if patch_DynamicLayer:
22
22
  _PATCHES_ = ["lazy_initialization"]
23
23
  _PATCHED_CLASS_ = DynamicLayer
24
24
 
25
- def lazy_initialization(self, key_states: torch.Tensor):
25
+ def lazy_initialization(
26
+ self, key_states: torch.Tensor, value_states: torch.Tensor = None
27
+ ):
26
28
  self.dtype, self.device = key_states.dtype, key_states.device
27
- new_shape = list(key_states.shape)
28
- new_shape[-2] = 0
29
+ assert (
30
+ hasattr(key_states, "shape") and key_states is not None
31
+ ), f"Attribute 'shape' is wrong for type {type(key_states)}"
32
+ like = torch.narrow(key_states, dim=-2, start=0, length=0)
29
33
  # PATCHED: used a tensor with an empty shape and not en empty list to initialize
30
- self.keys = torch.empty(new_shape, dtype=self.dtype, device=self.device)
31
- self.values = torch.empty(new_shape, dtype=self.dtype, device=self.device)
34
+ if isinstance(key_states, torch._subclasses.fake_tensor.FakeTensor):
35
+ with key_states.fake_mode:
36
+ self.keys = torch.empty_like(like, dtype=self.dtype, device=self.device)
37
+ self.values = torch.empty_like(like, dtype=self.dtype, device=self.device)
38
+ else:
39
+ self.keys = torch.empty_like(like, dtype=self.dtype, device=self.device)
40
+ self.values = torch.empty_like(like, dtype=self.dtype, device=self.device)
32
41
  if patch_is_initialized:
33
42
  self.is_initialized = True
34
43
 
@@ -214,7 +214,7 @@ def patched_dynamic_rope_update(rope_forward):
214
214
  cond,
215
215
  (lambda x, y: x.clone()),
216
216
  (lambda x, y: y.clone()),
217
- [long_inv_freq, original_inv_freq],
217
+ [long_inv_freq.to(original_inv_freq.dtype), original_inv_freq],
218
218
  )
219
219
  setattr(self, f"{prefix}inv_freq", inv_freq)
220
220
  # if seq_len > original_max_position_embeddings:
@@ -293,7 +293,7 @@ def patched_dynamic_rope_update(rope_forward):
293
293
  cond,
294
294
  (lambda x, y: x.clone()),
295
295
  (lambda x, y: y.clone()),
296
- [long_inv_freq, original_inv_freq],
296
+ [long_inv_freq.to(original_inv_freq.dtype), original_inv_freq],
297
297
  )
298
298
  setattr(self, f"{prefix}inv_freq", inv_freq)
299
299
 
@@ -1771,6 +1771,10 @@ def validate_onnx_model(
1771
1771
  if os.environ.get("DUMPORTOPT", "") in ("1", "true", "True"):
1772
1772
  opts = onnxruntime.SessionOptions()
1773
1773
  opts.optimized_model_filepath = f"{data['onnx_filename']}.rtopt.onnx"
1774
+ opts.add_session_config_entry(
1775
+ "session.optimized_model_external_initializers_file_name",
1776
+ f"{os.path.split(data['onnx_filename'])[0]}.rtopt.data",
1777
+ )
1774
1778
  if verbose:
1775
1779
  print(
1776
1780
  f"[validate_onnx_model] saved optimized onnxruntime "
@@ -2326,6 +2330,7 @@ def call_torch_export_custom(
2326
2330
  "custom-dec",
2327
2331
  "custom-decall",
2328
2332
  "custom-fake",
2333
+ "custom-tracing",
2329
2334
  }
2330
2335
  assert exporter in available, f"Unexpected value for exporter={exporter!r} in {available}"
2331
2336
  assert "model" in data, f"model is missing from data: {sorted(data)}"
@@ -2338,11 +2343,16 @@ def call_torch_export_custom(
2338
2343
  f"Options strict cannot be specified in the exporter name {exporter!r} "
2339
2344
  f"and in the options {exporter_options}"
2340
2345
  )
2346
+ assert ("-tracing" not in exporter) or ("tracing" not in exporter_options), (
2347
+ f"Options tracing cannot be specified in the exporter name {exporter!r} "
2348
+ f"and in the options {exporter_options}"
2349
+ )
2341
2350
  summary: Dict[str, Union[str, int, float]] = {}
2342
2351
  strict = "-strict" in exporter or exporter_options.pop("strict", False)
2343
2352
  args, kwargs = split_args_kwargs(data["inputs_export"])
2344
2353
  ds = data.get("dynamic_shapes", None)
2345
2354
  fake = "-fake" in exporter or exporter_options.pop("fake", False)
2355
+ tracing = "-tracing" in exporter or exporter_options.pop("tracing", False)
2346
2356
  if fake:
2347
2357
  from onnx_diagnostic.export.shape_helper import make_fake_with_dynamic_dimensions
2348
2358
 
@@ -2366,6 +2376,7 @@ def call_torch_export_custom(
2366
2376
  summary["export_exporter"] = exporter
2367
2377
  summary["export_optimization"] = optimization or ""
2368
2378
  summary["export_strict"] = strict
2379
+ summary["export_tracing"] = tracing
2369
2380
  summary["export_fake"] = fake
2370
2381
  summary["export_args"] = string_type(args, with_shape=True)
2371
2382
  summary["export_kwargs"] = string_type(kwargs, with_shape=True)
@@ -2388,6 +2399,7 @@ def call_torch_export_custom(
2388
2399
  )
2389
2400
  )
2390
2401
  large_model = bool(exporter_options.pop("large_model", True))
2402
+ exporter_options.pop("tracing", False)
2391
2403
  return_optimize_report = bool(exporter_options.pop("return_optimize_report", True))
2392
2404
  export_modules_as_functions = bool(
2393
2405
  exporter_options.pop("export_modules_as_functions", False)
@@ -2401,6 +2413,7 @@ def call_torch_export_custom(
2401
2413
  summary["export_external_threshold"] = str(external_threshold)
2402
2414
 
2403
2415
  export_options = ExportOptions(
2416
+ tracing=tracing,
2404
2417
  strict=strict,
2405
2418
  decomposition_table=decomposition_table,
2406
2419
  save_ep=(
@@ -2445,6 +2458,41 @@ def call_torch_export_custom(
2445
2458
  )
2446
2459
  ),
2447
2460
  )
2461
+ if "optimization" in opt_stats and dump_folder:
2462
+ import pandas
2463
+
2464
+ pattern_stats = []
2465
+ for k, v in opt_stats.items():
2466
+ if "time" in k:
2467
+ pattern_stats.append(dict(level="main", pattern=k, time_in=v))
2468
+ pattern_stats.extend(
2469
+ [{**obs, "level": "detailed"} for obs in opt_stats["optimization"]]
2470
+ )
2471
+ stat_filename = os.path.join(dump_folder, "optimization_stats.xlsx")
2472
+ df = pandas.DataFrame(pattern_stats)
2473
+ df.to_excel(stat_filename, index=False)
2474
+ cols = [
2475
+ c
2476
+ for c in [
2477
+ "level",
2478
+ "pattern",
2479
+ "time_in",
2480
+ "iteration",
2481
+ "inlined",
2482
+ "removed",
2483
+ "added",
2484
+ "instances",
2485
+ "changed",
2486
+ "scale",
2487
+ ]
2488
+ if c in df.columns
2489
+ ]
2490
+ agg = {k: "sum" for k in cols if k not in ("level", "pattern")}
2491
+ agg.update(dict(iteration="max", instances="mean"))
2492
+ agg = {k: v for k, v in agg.items() if k in df.columns}
2493
+ stat_filename = os.path.join(dump_folder, "optimization_stats.agg.xlsx")
2494
+ df[cols].groupby(["level", "pattern"]).agg(agg).to_excel(stat_filename)
2495
+
2448
2496
  if "ERR_export_onnx_c" in summary:
2449
2497
  return summary, data
2450
2498
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onnx-diagnostic
3
- Version: 0.8.7
3
+ Version: 0.8.8
4
4
  Summary: Tools to help converting pytorch models into ONNX.
5
5
  Home-page: https://github.com/sdpython/onnx-diagnostic
6
6
  Author: Xavier Dupré
@@ -90,6 +90,8 @@ Enlightening Examples
90
90
 
91
91
  * `Export microsoft/phi-2
92
92
  <https://sdpython.github.io/doc/onnx-diagnostic/dev/auto_examples/plot_export_tiny_phi2.html>`_
93
+ * `Export a model through method generate (with Tiny-LLM)
94
+ <https://sdpython.github.io/doc/onnx-diagnostic/dev/auto_examples/plot_export_tiny_llm_method_generate.html>`_
93
95
 
94
96
  **Torch Export**
95
97
 
@@ -1,4 +1,4 @@
1
- onnx_diagnostic/__init__.py,sha256=4PdbZ6FK0yyAhH9AUn7XujsN3PJ3vNr0EsPuwV8XoWc,173
1
+ onnx_diagnostic/__init__.py,sha256=Is5g4yyLoruIq2F94HTISS_8sTf8w9AHzf6qlhhytZ0,173
2
2
  onnx_diagnostic/__main__.py,sha256=YmyV_Aq_ianDlHyKLHMa6h8YK3ZmFPpLVHLKjM91aCk,79
3
3
  onnx_diagnostic/_command_lines_parser.py,sha256=g_udwHBHmY6X_d41Qby_DqMpEHL1p9GfUhJGBCihl8c,57784
4
4
  onnx_diagnostic/api.py,sha256=BhCl_yCd78N7TlVtPOHjeYv1QBEy39TjZ647rcHqLh0,345
@@ -6,34 +6,34 @@ onnx_diagnostic/doc.py,sha256=t3RELgfooYnVMAi0JSpggWkQEgUsREz8NmRvn0TnLI8,2829
6
6
  onnx_diagnostic/ext_test_case.py,sha256=A6BkrRm-QbvM8A-qRRMLt9o9ZO6wMXE9jrotggjpGfE,50460
7
7
  onnx_diagnostic/ci_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  onnx_diagnostic/ci_models/ci_helpers.py,sha256=lblOF7z2kLcCRAwMOdqp-Tz1EL1oBywHfVokhqiTQRg,15592
9
- onnx_diagnostic/ci_models/export_phi4_mm.py,sha256=FZik8jN0GdQ7sAo_a9PiuulUpbgG_4BrZugWQ7YbuaU,41668
9
+ onnx_diagnostic/ci_models/export_phi4_mm.py,sha256=DH225jXhOG_S8KZE9Kn7FGNE4VqFyc9ZDnG-qxZn-hk,41668
10
10
  onnx_diagnostic/ci_models/export_qwen25_vl.py,sha256=_rYPr8PPraWizr2MPcGuYjrJ55ilJOyKl8kg0wq4L90,20405
11
11
  onnx_diagnostic/export/__init__.py,sha256=yEIoWiOeTwBsDhyYt2fTKuhtA0Ya1J9u9ZzMTOTWaWs,101
12
- onnx_diagnostic/export/api.py,sha256=5ESg0rcK0EFGMNl76_K2O0rvCC8hVi7Nfj0O3OI7tQA,10657
12
+ onnx_diagnostic/export/api.py,sha256=V-2IhcxfMRFIh-CBb3c7QUUTcd_11FjRLHXLhIOy4Fk,22111
13
13
  onnx_diagnostic/export/cf_simple_loop_for.py,sha256=OHPGQc9AC-0TBtCYpP6cm-iHP9gmNt8WYRrPlO9ewlc,21158
14
14
  onnx_diagnostic/export/control_flow_onnx.py,sha256=izGlctqQANrHzSxPMbT7hoauNbnIBdx6hb8ry7HtVmM,18263
15
- onnx_diagnostic/export/dynamic_shapes.py,sha256=M2hlpHSTbkzZwGKAbrpQXng5HQrwjF5Z6wGGxEgnp74,42061
15
+ onnx_diagnostic/export/dynamic_shapes.py,sha256=z6BgCAHyrB6SLcCdjy5CMr8lOy-dm-CUQgJc_GyQVTw,44138
16
16
  onnx_diagnostic/export/onnx_plug.py,sha256=U13fL0BjnhMzcDGxaAOqM4TQte5Z4zKDg4ESS0iktjM,22704
17
- onnx_diagnostic/export/shape_helper.py,sha256=m628y0oRCQbeZkeh8JDHIfWMsSjoJoeX-IPiPGDHT-w,11273
17
+ onnx_diagnostic/export/shape_helper.py,sha256=L0RKUufLQDM5PqDMYk-9L3YZMnv4Zpz2t18KL_37RUU,11341
18
18
  onnx_diagnostic/export/validate.py,sha256=_PGUql2DJhIgGKo0WjTGUc5AgsZUx8fEs00MePy-w98,6043
19
19
  onnx_diagnostic/helpers/__init__.py,sha256=GJ2GT7cgnlIveVUwMZhuvUwidbTJaKv8CsSIOpZDsJg,83
20
20
  onnx_diagnostic/helpers/_log_helper.py,sha256=OTwQH0OIxs9B6nrSvR7MoxMimSw_8mU0mj133NvLk5o,16832
21
21
  onnx_diagnostic/helpers/args_helper.py,sha256=SRWnqC7EENg09RZlA50B_PcdiIhdbgA4C3ACfzl5nMs,4419
22
22
  onnx_diagnostic/helpers/bench_run.py,sha256=Vvzb7Wy0baIT5O0dx4RKQTx-5V08PiHxPJh6XPkY-lU,16544
23
- onnx_diagnostic/helpers/cache_helper.py,sha256=OLghsSUuZ8cWGkua8eH75KBF-mbVqejnNUYfFo5lRf0,28498
23
+ onnx_diagnostic/helpers/cache_helper.py,sha256=RsPuYRQ_RiA4I-J2loD-gXnmLsvxskp_nqv_C9hQlrU,28114
24
24
  onnx_diagnostic/helpers/config_helper.py,sha256=cWRETgFhZ7tayIZPnMqF8BF5AvTU64G2BMqyzgO7lzs,5670
25
25
  onnx_diagnostic/helpers/doc_helper.py,sha256=pl5MZd3_FaE8BqQnqoBuSBxoNCFcd2OJd3eITUSku5c,5897
26
26
  onnx_diagnostic/helpers/dot_helper.py,sha256=hwgTJsbsUv0qq7euyPDnc1NsBZDGOwv32JXSZxIHJkE,8118
27
- onnx_diagnostic/helpers/fake_tensor_helper.py,sha256=J7wnK3WTuVKnYiMzLVTAPkdJr3hQfIfMC9ZlOu7oGmI,11024
27
+ onnx_diagnostic/helpers/fake_tensor_helper.py,sha256=59046wDIw84or6PJxLaa2CFqaWT7Y3mpYr-BB2shcBE,12027
28
28
  onnx_diagnostic/helpers/graph_helper.py,sha256=hevQT5a7_QuriVPQcbT5qe18n99Doyl5h3-qshx1-uk,14093
29
- onnx_diagnostic/helpers/helper.py,sha256=x8EYQmgrz_G5QS_IsbeFIoDcN_sUs-CslJMHseBj1Fw,65482
29
+ onnx_diagnostic/helpers/helper.py,sha256=Fa5wB0CAva2d82RDjCoJxbf1AafYWPZEHKlyz7PZLg0,66505
30
30
  onnx_diagnostic/helpers/log_helper.py,sha256=3mWQd-nLKCctKZt9N8SpoWgLC8O7YdNQ2pfW5QXYWDQ,93232
31
31
  onnx_diagnostic/helpers/memory_peak.py,sha256=M3m4_thWFIwP5HytbJYEqaijXIv5v5BW_vlcJowIYI4,6434
32
32
  onnx_diagnostic/helpers/mini_onnx_builder.py,sha256=jR2lkRZEQ0N30H0FqeBwaxJd_w_6kyxFagrnulqFjhE,23883
33
33
  onnx_diagnostic/helpers/model_builder_helper.py,sha256=qKIq4Naqq03gk6NfqXLQjSDiKL5FFNc1AEyVX0R8GmA,18540
34
34
  onnx_diagnostic/helpers/onnx_helper.py,sha256=MshvqMSTNUUZIpkkRYGDymdW2t2KtB2BgYtOPHIDwvQ,57508
35
35
  onnx_diagnostic/helpers/optim_helper.py,sha256=0NiYRwV9GLTub4SEny0dqEhLcajRjEhcgkeBDVr9bGQ,4424
36
- onnx_diagnostic/helpers/ort_session.py,sha256=XvRazj7yyepaQwYHpPkKKi9v8u_h9A4ZiFH6IxjqPKs,30502
36
+ onnx_diagnostic/helpers/ort_session.py,sha256=Y6iJojJcQtPesy9dRaaxRSeRTLXk0Pdh6-_fzdiPDm0,30779
37
37
  onnx_diagnostic/helpers/rt_helper.py,sha256=OOxHSCKZup2u7zTvVJxPkRHb4jQZ03KpkiDGrfwibMM,38135
38
38
  onnx_diagnostic/helpers/torch_fx_graph_helper.py,sha256=7xFe4svdbr4gV3OTNcx8eJejjDyHAv4hD_RNNKSxL0c,6571
39
39
  onnx_diagnostic/helpers/torch_helper.py,sha256=ADV81WWCskQ-jmzn1GI_LU8GqBtufCHS3oeLG-3Uw0E,38954
@@ -89,7 +89,7 @@ onnx_diagnostic/tasks/automatic_speech_recognition.py,sha256=aMufLDGW005f7aLMZ9a
89
89
  onnx_diagnostic/tasks/feature_extraction.py,sha256=IS9z9fPNE0hhGUebBfmNZl0twdXobMc7MFKpQB9qZI0,5388
90
90
  onnx_diagnostic/tasks/fill_mask.py,sha256=5Gt6zlj0p6vuifox7Wmj-TpHXJvPS0CEH8evgdBHDNA,2640
91
91
  onnx_diagnostic/tasks/image_classification.py,sha256=nLpBBB1Gkog3Fk6pu2waiHcuQr4ILPptc9FhQ-pn460,4682
92
- onnx_diagnostic/tasks/image_text_to_text.py,sha256=21gbNU8ZZCSzWWmNpwlUmROD_5pC_u74GgnzTLELzd8,22136
92
+ onnx_diagnostic/tasks/image_text_to_text.py,sha256=A3mg3t7zh2Z_kAJ4cQBrW9x6O1knMPjL_LwMlH78m-k,22142
93
93
  onnx_diagnostic/tasks/image_to_video.py,sha256=SoF2cVIJr6P30Abp-FCuixFDh5RvTuNEOL36QthGY6U,3860
94
94
  onnx_diagnostic/tasks/mask_generation.py,sha256=fjdD3rd-O-mFL0hQy3la3JXKth_0bH2HL7Eelq-3Dbs,5057
95
95
  onnx_diagnostic/tasks/mixture_of_expert.py,sha256=al4tk1BrHidtRiHlAaiflWiJaAte0d5M8WcBioANG9k,2808
@@ -106,7 +106,7 @@ onnx_diagnostic/tasks/data/dummies_imagetext2text_generation_gemma3.onnx,sha256=
106
106
  onnx_diagnostic/torch_export_patches/__init__.py,sha256=0SaZedwznm1hQUCvXZsGZORV5vby954wEExr5faepGg,720
107
107
  onnx_diagnostic/torch_export_patches/onnx_export_errors.py,sha256=XHYtU7w3vsaTMCuF5X1YtOKxgwL8eEuktXzVZpRz55o,43431
108
108
  onnx_diagnostic/torch_export_patches/onnx_export_serialization.py,sha256=0HdubI06EGpxOICqDWZoVmZkVO9gAaFADEmby197EyM,11935
109
- onnx_diagnostic/torch_export_patches/patch_details.py,sha256=MSraVo5ngBhihi8ssPMXSY9B4fJ17J-GAADaw3dT-rc,11794
109
+ onnx_diagnostic/torch_export_patches/patch_details.py,sha256=UHBo4QTLF3ZgQ4951yYHIQqxOeRYNaG7x56XFcRTtg4,11794
110
110
  onnx_diagnostic/torch_export_patches/patch_expressions.py,sha256=VOsv71FsR_UZtxz4-5_VKL2sHQhOkHy9RkPJME2h7UU,3271
111
111
  onnx_diagnostic/torch_export_patches/patch_inputs.py,sha256=-TgcyjVzxTb5Y-_ibssTeaA5PFz6FJrV6q84HMUAsJw,8075
112
112
  onnx_diagnostic/torch_export_patches/patch_module.py,sha256=1Mn3xdpK1jSdRs6z1C-mJGkfGmD2TNRwLNoPaOW_EFI,40061
@@ -117,7 +117,7 @@ onnx_diagnostic/torch_export_patches/patches/__init__.py,sha256=47DEQpj8HBSa-_TI
117
117
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_attention.py,sha256=5JOyT95BNwHIuxaSFJDSEGsoI-6IwbgNnFwg2q3UM-Q,7731
118
118
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_cache_utils.py,sha256=UdxLii-od2OpQmUJbmXmZinXeLBItVFrr75BVT1Y0zw,2041
119
119
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_causal_mask.py,sha256=h37DPVxsq8iAWECnTlKW5tVqSBgPBF52xr3uxsjdi2k,3113
120
- onnx_diagnostic/torch_export_patches/patches/_patch_transformers_dynamic_cache.py,sha256=lEdYqX60pyi_w6PrbCTk7NC96nB8FFcFRf_JMjXSAZE,7961
120
+ onnx_diagnostic/torch_export_patches/patches/_patch_transformers_dynamic_cache.py,sha256=aiRtT1SUTrH7wYpBF7YjPEgb-fRYXlnilims4Y5a0JA,8516
121
121
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_funnel.py,sha256=QAMFiA8MGQgbowZzpfLsh7gXTuzXc3eGmZ7hLKF1i78,3352
122
122
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_gemma3.py,sha256=nVgYQk0xXpHiictN1wOHVMN2lTH9b0vfIJ4ie-uKopg,1999
123
123
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_generation_mixin.py,sha256=VIZsVHgR8NmAcBQalPl5I6ZzNgcBxjGb6ars31m9gRg,21936
@@ -126,7 +126,7 @@ onnx_diagnostic/torch_export_patches/patches/_patch_transformers_masking_utils.p
126
126
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_qwen2.py,sha256=OxYdlLrwtd_KGHt3E17poduxvWFg-CfGS57-yN1i6gI,3827
127
127
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_qwen2_5.py,sha256=oYz0tr-6KH0DabpgaISytnXAGxQosoA8gV5LpksO4yI,34834
128
128
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_qwen3.py,sha256=cND9Iqo1aKdlX-BXGr9Qlq_Y4EW1L5VWSwZfqYTVazU,4888
129
- onnx_diagnostic/torch_export_patches/patches/_patch_transformers_rotary_embedding.py,sha256=4bJ_z2gizZQla_fcCVt0dmuhzO9Vu-D7CCMWdxMlrKM,16893
129
+ onnx_diagnostic/torch_export_patches/patches/_patch_transformers_rotary_embedding.py,sha256=LAqoL5SWISekZO15G1HIcCkN1JlBxGqb9XbK_eLzalA,16949
130
130
  onnx_diagnostic/torch_export_patches/patches/_patch_transformers_sam_mask_decoder.py,sha256=-6TuBm3sLAFEGuW3vRfOTtE5uP6aINFfu7xMnl27Dws,5703
131
131
  onnx_diagnostic/torch_export_patches/patches/patch_helper.py,sha256=kK_CGW643iVXxa-m6pttDBS7HTyMQaPypza7iqIInn4,721
132
132
  onnx_diagnostic/torch_export_patches/patches/patch_torch.py,sha256=VCs3uZHcuzosCqn9sSEskEWHJym_RrDJM6-G6FcTC08,45117
@@ -137,7 +137,7 @@ onnx_diagnostic/torch_export_patches/serialization/transformers_impl.py,sha256=s
137
137
  onnx_diagnostic/torch_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
138
  onnx_diagnostic/torch_models/code_sample.py,sha256=rCDZY64pkn6uIbJJSBuC5TlU_-uleI73I9GlbXtJd54,12923
139
139
  onnx_diagnostic/torch_models/llms.py,sha256=soyg4yC87ptGoeulJhKqw5opGmuLvH1pn_ZDXZ4Jr8E,90
140
- onnx_diagnostic/torch_models/validate.py,sha256=fnbTl5v1n5nM2MpmCgCMaWa6c7DGpb5mZYSuHXXCJEs,94829
140
+ onnx_diagnostic/torch_models/validate.py,sha256=JsEMv7aeg9tGGriKZ_CJeqGDfNUmZNdGtPu5jQN9TWY,96739
141
141
  onnx_diagnostic/torch_models/hghub/__init__.py,sha256=vi1Q7YHdddj1soiBN42MSvJdFqe2_KUoWafHISjwOu8,58
142
142
  onnx_diagnostic/torch_models/hghub/hub_api.py,sha256=V3azxUqb7mkmHQ8m5DCgg1WUU2NYBK12USEUy_sfYIA,14709
143
143
  onnx_diagnostic/torch_models/hghub/hub_data.py,sha256=6jR8A83cGP4Xw1Wg-q1zzKFpqzoVrybqm0Fm3yurkrE,9030
@@ -152,8 +152,8 @@ onnx_diagnostic/torch_onnx/compare.py,sha256=O0lws4kzn8WAXr8-x-YMPr7oyBC9DtSIs4O
152
152
  onnx_diagnostic/torch_onnx/runtime_info.py,sha256=u1bD6VXqzBCRmqmbzQtDswaPs1PH_ygr1r-CrcfXpNU,8562
153
153
  onnx_diagnostic/torch_onnx/sbs.py,sha256=8okBEIupMgw7TtKc80YFimMtwnY3GchdY05FsA9ooa0,40749
154
154
  onnx_diagnostic/torch_onnx/sbs_dataclasses.py,sha256=UctdBjzoPTQG1LS0tZ8A6E9hpoq5HWUYaJLPOPJc9FI,20299
155
- onnx_diagnostic-0.8.7.dist-info/licenses/LICENSE.txt,sha256=Vv6TXglX6Rc0d-f8aREhayhT-6PMQXEyOmI2NKlUCMc,1045
156
- onnx_diagnostic-0.8.7.dist-info/METADATA,sha256=H6o_1MWw2N8hO2BYh499xYb0Mm_KjgxkwirLXxiHQHI,6734
157
- onnx_diagnostic-0.8.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
158
- onnx_diagnostic-0.8.7.dist-info/top_level.txt,sha256=KwNkXewmcobM3ZT1DJLVWH6ebJzA5qKg7cWqKfpGNT4,16
159
- onnx_diagnostic-0.8.7.dist-info/RECORD,,
155
+ onnx_diagnostic-0.8.8.dist-info/licenses/LICENSE.txt,sha256=Vv6TXglX6Rc0d-f8aREhayhT-6PMQXEyOmI2NKlUCMc,1045
156
+ onnx_diagnostic-0.8.8.dist-info/METADATA,sha256=sxPBIjOSLqQITi527dnl_3gk3RxT9kNCu47gPPyrg7Q,6905
157
+ onnx_diagnostic-0.8.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
158
+ onnx_diagnostic-0.8.8.dist-info/top_level.txt,sha256=KwNkXewmcobM3ZT1DJLVWH6ebJzA5qKg7cWqKfpGNT4,16
159
+ onnx_diagnostic-0.8.8.dist-info/RECORD,,