mlflow-triton 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,459 @@
1
+ Metadata-Version: 2.4
2
+ Name: mlflow-triton
3
+ Version: 0.4.0
4
+ Summary: MLflow logging wrappers and portable Triton model repositories
5
+ License-Expression: Apache-2.0
6
+ Project-URL: Homepage, https://github.com/ai-lab-tech/mlflow-plugin
7
+ Project-URL: Documentation, https://github.com/ai-lab-tech/mlflow-plugin/blob/main/packages/mlflow-triton/README.md
8
+ Project-URL: Repository, https://github.com/ai-lab-tech/mlflow-plugin
9
+ Project-URL: Issues, https://github.com/ai-lab-tech/mlflow-plugin/issues
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: mlflow<4,>=3.14
14
+ Requires-Dist: protobuf>=3.20.3
15
+ Dynamic: license-file
16
+
17
+ # mlflow-triton
18
+
19
+ > **For demos and proofs of concept — not production-ready serving.**
20
+ >
21
+ > **Before production use, an ML Engineer must review, validate and optimize the
22
+ > serving implementation and, where needed, convert the model to a suitable
23
+ > production format/backend.** The generated Triton Python backend uses MLflow's
24
+ > prediction interface as a starting point. Successful example tests do not
25
+ > establish production readiness, throughput, latency or resource efficiency.
26
+
27
+ Core MLflow logging wrappers for sklearn, PyTorch and Hugging Face. Generate a
28
+ portable Triton repository for Data Scientist demos and PoCs, without requiring
29
+ Triton Control, deployment credentials or an LLM. Production optimization remains
30
+ a separate ML Engineering task.
31
+
32
+ ```bash
33
+ pip install mlflow-triton
34
+ ```
35
+
36
+ Requires Python 3.10+ and MLflow >=3.14,<4. Install the framework dependencies
37
+ appropriate to your saved model separately. This package registers no deployment
38
+ entry point and makes no Triton Control API calls.
39
+ `config.pbtxt` is generated in Protobuf text format, using Protobuf string escaping.
40
+
41
+ ## Log native models with a required example request
42
+
43
+ Use the plugin's framework module instead of `mlflow.<framework>.log_model`:
44
+
45
+ ```python
46
+ from mlflow_triton import sklearn, pytorch, transformers
47
+
48
+ # Already-fitted Pipeline, including its original preprocessing.
49
+ info = sklearn.log_model(
50
+ fitted_pipeline,
51
+ name="classifier",
52
+ input_example=example_dataframe,
53
+ registered_model_name="classifier",
54
+ )
55
+
56
+ # Instantiated custom architecture with its saved trained weights loaded.
57
+ # Include inference-only class/helper modules, not a training entry point.
58
+ torch_info = pytorch.log_model(
59
+ loaded_model.eval(),
60
+ name="network",
61
+ input_example=example_numpy_array,
62
+ code_paths=["inference_architecture"],
63
+ pip_requirements=["torch==<your-version>", "numpy==<your-version>"],
64
+ )
65
+
66
+ # A supported Transformers pipeline containing the model and tokenizer/processor.
67
+ hf_info = transformers.log_model(
68
+ loaded_pipeline,
69
+ name="text_model",
70
+ input_example=["Example input"],
71
+ model_config={"max_new_tokens": 32, "do_sample": False, "return_full_text": True},
72
+ )
73
+
74
+ print(info.model_uri)
75
+ ```
76
+
77
+ `input_example` is a mandatory keyword argument even when `signature=` is supplied.
78
+ It is the model's prediction input (DataFrame, NumPy array, named tensor dictionary,
79
+ or supported Transformers task input), **not** a Triton HTTP request envelope.
80
+ MLflow stores the example with the model: use appropriate non-sensitive examples.
81
+ No training is run. By default, logging executes inference using the supplied
82
+ model on its current device, without reloading its weights or moving it to CPU.
83
+ Allow memory for example inference and native serialization. Set
84
+ `validate_saved_model=True` to instead reload the saved artifact on CPU for
85
+ validation; this requires memory for an additional model copy.
86
+ Framework packages such as torch/transformers remain optional plugin dependencies;
87
+ install the versions required by your model.
88
+
89
+ The wrappers preserve an explicit signature. Otherwise they infer one with MLflow
90
+ from the example and model prediction.
91
+ They reject missing/incompatible schemas before logging or registration. Native
92
+ flavor options such as `code_paths`, requirements, sklearn's `pyfunc_predict_fn`,
93
+ and Transformers' `task`, `processor` and `model_config` are forwarded to native
94
+ packaging. `name`, `registered_model_name`, `await_registration_for`, `run_id`,
95
+ `metadata`, `tags` and logging `params` are supported. Logging `params` are tracking
96
+ metadata, not generation parameters: use `model_config` for Transformers settings.
97
+ This is an explicit wrapper API; it does not monkey-patch MLflow or autologging.
98
+
99
+ The logged artifact contains the native MLflow flavors and an additional `triton`
100
+ flavor pointing to:
101
+
102
+ ```text
103
+ model_repository/<name>/
104
+ config.pbtxt
105
+ requirements.txt
106
+ request.json
107
+ validation.json
108
+ 1/
109
+ model.py
110
+ artifact/ # Complete local MLflow package, including code and assets
111
+ ```
112
+
113
+ Native `mlflow.pyfunc.load_model(info.model_uri)` and native framework loaders
114
+ remain usable. The embedded package is a separate copy so the Triton directory
115
+ can be deployed independently; this increases artifact storage size. Dependencies
116
+ are recorded, not installed into the running Triton server automatically. Build
117
+ an environment from `requirements.txt` with a Python version matching Triton's
118
+ Python backend stub; custom code dependencies must be included or installed.
119
+
120
+ The generated configuration uses `backend: "python"` and `max_batch_size: 0`.
121
+ Tensor shapes include their full batch dimension. Column schemas map to separate
122
+ rank-one tensors; tensor schemas retain their declared shapes. The `mlflow_contract` parameter in `config.pbtxt`
123
+ records mappings between original field names and Triton-safe tensor names.
124
+ Only dynamic axes already declared by the signature are retained; a single
125
+ example does not prove that other sequence/image dimensions are variable.
126
+ Supply an explicit signature when those dimensions need to be dynamic.
127
+
128
+ `device="cpu"` is the default. `device="gpu"` emits `KIND_GPU` for PyTorch or
129
+ Transformers; `model.py` uses the assigned Triton instance device when loading.
130
+ Default validation uses the supplied model's current device, independently of the
131
+ Triton target. Optional saved-artifact validation loads on CPU even for a GPU
132
+ target. Sharded/device-mapped models or tasks unsupported by MLflow pyfunc
133
+ need a separate adapter; the wrapper does not claim universal model support.
134
+
135
+ PyTorch uses Python/pickle packaging by default, **not** an implicit LibTorch/PT2
136
+ export. Supply required architecture modules with `code_paths` or dependencies.
137
+ Pre/postprocessing outside the supplied model/Pipeline is not captured. Transformers
138
+ packages preserve their saved tokenizer, chat template and model configuration,
139
+ and expose the MLflow task interface (which can differ from raw `forward()` or
140
+ pipeline outputs). Serving is unary prediction, not streaming or a dedicated
141
+ high-throughput LLM engine. No GGUF/Q4_K_M compatibility is implied.
142
+
143
+ Supported signatures contain NumPy-compatible numeric/string tensors or required
144
+ scalar DataFrame columns. Optional columns, nested/object schemas, datetime columns,
145
+ and scalar tensors require an explicit serving adapter and fail clearly rather than
146
+ being flattened or cast speculatively.
147
+
148
+ `validation.json` identifies in-memory or saved-artifact prediction validation,
149
+ records whether the saved artifact was checked, and distinguishes local mapping
150
+ validation from actual Triton validation. Logging does **not** launch Triton, deploy a service,
151
+ or establish GPU correctness. The direct `triton.log_model()` API below remains available. Deployment is a separate concern.
152
+
153
+ ## Log API reference
154
+
155
+ The three framework wrappers have these public entry points (common keyword
156
+ options are abbreviated below; the Python signatures expose them explicitly):
157
+
158
+ ```python
159
+ sklearn.log_model(sk_model, *, input_example, **kwargs)
160
+ pytorch.log_model(pytorch_model, *, input_example, **kwargs)
161
+ transformers.log_model(transformers_model, *, input_example, **kwargs)
162
+ ```
163
+
164
+ Pass the model positionally or by its exact parameter name. `input_example` and
165
+ all other options must be keyword arguments. The tables below describe the
166
+ options handled by this plugin and commonly used native packaging options.
167
+
168
+ ### Required arguments
169
+
170
+ | Function | Model argument | Required `input_example` |
171
+ | --- | --- | --- |
172
+ | `sklearn.log_model` | `sk_model`: already-fitted estimator or complete preprocessing `Pipeline`. | A non-empty DataFrame or NumPy array accepted by the saved prediction interface. Preserve column names, order and dtypes. |
173
+ | `pytorch.log_model` | `pytorch_model`: instantiated `torch.nn.Module` with trained weights loaded; call `.eval()` first. A `state_dict` or filename alone is insufficient. | A non-empty NumPy input, or named tensor input supported by MLflow's PyTorch prediction interface. Match the model's input dtype and dimensions. |
174
+ | `transformers.log_model` | `transformers_model`: supported Transformers pipeline, or component dictionary such as `{"model": model, "tokenizer": tokenizer}`. Include the task's required tokenizer/processor assets. | A non-empty task input supported by MLflow pyfunc, such as a list of text strings or a DataFrame with the task's input fields. |
175
+
176
+ `input_example=None` and empty examples are rejected. The example remains
177
+ mandatory with an explicit signature. It is saved in the artifact and used for
178
+ prediction and tensor-mapping validation; it is not training data or a Triton
179
+ HTTP request. PyTorch models with any submodule still in training mode are rejected.
180
+
181
+ ### Common optional arguments
182
+
183
+ These arguments are accepted by all three framework wrappers through `**kwargs`.
184
+
185
+ | Argument | Type / default | Meaning |
186
+ | --- | --- | --- |
187
+ | `name` | `str`, `"model"` | MLflow logged-model name. Also supplies the Triton model name unless `triton_model_name` is set. |
188
+ | `triton_model_name` | `str` or `None`, `None` | Triton directory and `config.pbtxt` model name. Defaults to `name`; must start with an ASCII letter or underscore, followed by ASCII letters, digits, `_` or `-`. |
189
+ | `device` | `"cpu"` or `"gpu"`, `"cpu"` | Target Triton instance kind. sklearn accepts only `"cpu"`; PyTorch and Transformers accept both. Default validation uses the supplied model's current device. This does not move the model, choose a GPU index or start Triton. |
190
+ | `validate_saved_model` | `bool`, `False` | By default, validate predictions and tensor mappings using the supplied model without reloading weights. Set `True` to instead reload the saved artifact on CPU and validate it, requiring memory for another copy. |
191
+ | `signature` | MLflow `ModelSignature` or `None`, `None` | Explicit input **and output** schemas, or inference from the model and example. Explicit schemas must be compatible with the generated tensor mapping. `False` is rejected. |
192
+ | `registered_model_name` | `str` or `None`, `None` | Create a version under this MLflow Registry name. Omit to log without registering. |
193
+ | `await_registration_for` | seconds, `300` | MLflow wait timeout for registration, when registration is requested. |
194
+ | `run_id` | `str` or `None`, `None` | Optional MLflow run association, forwarded to `Model.log`. Without it, MLflow applies its active-run/default behavior. |
195
+ | `metadata` | `dict` or `None`, `None` | Model metadata, passed to native packaging and MLflow logging. |
196
+ | `tags` | `dict` or `None`, `None` | Tags for the MLflow logged model. |
197
+ | `params` | `dict` or `None`, `None` | Parameters recorded with the MLflow logged model. These do not configure inference; use Transformers `model_config` for generation settings. |
198
+
199
+ The MLflow Registry version and Triton filesystem version are independent:
200
+ logging always generates `<triton_model_name>/1/`, even when the Registry creates
201
+ version 2 or higher. There is no `triton_version` argument.
202
+
203
+ ### Native packaging arguments
204
+
205
+ Remaining keyword arguments are forwarded to **`mlflow.<framework>.save_model`**,
206
+ not to that framework's `log_model`. Availability and defaults therefore depend on
207
+ the installed MLflow version. This wrapper does not accept every argument exposed
208
+ by native `log_model`; for example, use `name`, not `artifact_path`. Unknown or
209
+ incompatible options fail during native packaging.
210
+
211
+ | Argument | Applies to | Default / purpose |
212
+ | --- | --- | --- |
213
+ | `code_paths` | All three | Native default `None`. List of local inference-code files/directories to package, e.g. custom architecture modules. Include their importable package structure; do not pass training entry points. |
214
+ | `pip_requirements` | All three | Default `None`: use native framework defaults without model-loading dependency inference. Supply a requirements list or requirements-file path for custom dependencies and a reproducible serving environment. With `validate_saved_model=True`, native dependency inference is also enabled when no explicit environment is supplied. |
215
+ | `extra_pip_requirements` | All three | Native default `None`. Add requirements to native defaults/inference. |
216
+ | `conda_env` | All three | Native default `None`. Explicit environment dictionary or environment-file path. Follow native MLflow restrictions on combining it with pip requirement arguments. |
217
+ | `pyfunc_predict_fn` | sklearn | `"predict"`. Select the estimator method used by the MLflow prediction interface, e.g. `"predict_proba"` when supported by the estimator and MLflow. This also determines the output used to infer the signature. |
218
+ | `serialization_format` | sklearn | Native MLflow default. Choose a format supported by the installed sklearn flavor. |
219
+ | `serialization_format` | PyTorch | Plugin default `"pickle"`. An explicit alternative must be supported by the installed native flavor and pass saved-model validation. The plugin does not automatically export or guarantee graph compatibility. |
220
+ | `pickle_module` | PyTorch | Native default `None`. Optional serialization module for native PyTorch packaging. |
221
+ | `task` | Transformers | Native default `None`. Task identifier such as `"text-classification"` or `"text-generation"`. Supply it when native packaging cannot infer the task, especially with custom models/component dictionaries. |
222
+ | `processor` | Transformers | Native default `None`. Task-specific processor where required; model/tokenizer components otherwise belong in the pipeline or component dictionary. |
223
+ | `model_config` | Transformers | Native default `None`. Saved inference configuration, e.g. `{"max_new_tokens": 32, "do_sample": False}`. Options must be supported by the task and MLflow prediction interface. |
224
+ | `save_pretrained` | Transformers | Native default `True`. Must not be `False`: Triton needs the model and tokenizer assets saved locally. |
225
+
226
+ Default logging skips MLflow's automatic dependency inference because it can
227
+ reload the saved model in a subprocess. Framework defaults may omit custom
228
+ dependencies; supply them with `pip_requirements` or `extra_pip_requirements`.
229
+
230
+ Custom architecture code and third-party dependencies must be available when the
231
+ saved artifact is reloaded. `code_paths` bundles local code; requirement arguments
232
+ record installable dependencies. Neither reconstructs a missing architecture.
233
+ External preprocessing must already be part of the supplied prediction interface.
234
+
235
+ ### Examples with explicit options
236
+
237
+ The objects below are already loaded/fitted; these calls do not train them.
238
+ Configure the MLflow tracking URI/experiment using MLflow's normal API before
239
+ logging, if required for your environment.
240
+
241
+ ```python
242
+ from mlflow_triton import sklearn, pytorch, transformers
243
+
244
+ # sklearn: named DataFrame columns and preprocessing travel with the Pipeline.
245
+ sk_info = sklearn.log_model(
246
+ sk_model=fitted_pipeline,
247
+ input_example=example_dataframe.iloc[:2],
248
+ name="classifier",
249
+ device="cpu",
250
+ pyfunc_predict_fn="predict_proba",
251
+ registered_model_name="demo-classifier",
252
+ )
253
+
254
+ # PyTorch: custom architecture instance, trained weights already loaded.
255
+ pt_info = pytorch.log_model(
256
+ pytorch_model=loaded_model.eval(),
257
+ input_example=example_numpy_array[:2],
258
+ name="network",
259
+ device="gpu",
260
+ code_paths=["inference_architecture"],
261
+ pip_requirements="requirements-serving.txt",
262
+ )
263
+
264
+ # Hugging Face: a pipeline includes the tokenizer; use saved generation options.
265
+ hf_info = transformers.log_model(
266
+ transformers_model=loaded_generation_pipeline,
267
+ input_example=["Explain what a model signature describes."],
268
+ name="text-generator",
269
+ triton_model_name="text_generator",
270
+ device="gpu",
271
+ task="text-generation",
272
+ model_config={"max_new_tokens": 32, "do_sample": False},
273
+ )
274
+
275
+ print(hf_info.model_uri)
276
+ ```
277
+
278
+ Logging has already generated and saved the Triton repository. If you need a local
279
+ directory to inspect or hand off to deployment tooling, optionally retrieve it:
280
+
281
+ ```python
282
+ from mlflow_triton import triton
283
+
284
+ repository = triton.load_model(hf_info.model_uri)
285
+ print(repository / "config.pbtxt")
286
+ print(repository / "1/model.py")
287
+ ```
288
+
289
+ ### Return value and validation
290
+
291
+ All three calls return MLflow `ModelInfo`. Use `info.model_uri` to load the saved
292
+ model or resolve its Triton repository, and `info.registered_model_version` when
293
+ registration was requested. `triton.load_model(info.model_uri)` returns a local
294
+ `pathlib.Path` to the model-name directory, downloading artifacts as necessary.
295
+ This optional call only retrieves the generated repository; it does not load model
296
+ weights, regenerate the repository or load it into a running Triton server.
297
+
298
+ Before logging/registration, the wrapper executes the example prediction using
299
+ MLflow's prediction adapter around the supplied model, derives/checks the signature,
300
+ saves the native model and validates the input/output tensor mapping. It reuses
301
+ the existing weights. Unsupported schemas, invalid devices or failed predictions
302
+ raise an exception. A successful default return does not establish that the saved
303
+ artifact can be reloaded in another environment.
304
+
305
+ Use `validate_saved_model=True` to instead validate a CPU reload of the saved
306
+ artifact, including whether its custom code can be imported locally. The original
307
+ model remains in memory during this check. `validation.json` records the selected
308
+ mode and validation device; actual Triton serving and GPU execution must be
309
+ tested separately. There are no `deploy`, `validate_triton`, `max_batch_size` or
310
+ GPU-index arguments in these wrappers.
311
+
312
+ ## Log a Triton model in MLflow
313
+
314
+ Like NVIDIA's Triton MLflow plugin, this package provides a `triton` model
315
+ flavor for a complete Triton model directory. The directory must contain at
316
+ least one numbered version; `config.pbtxt` may be included at
317
+ its root. The MLflow Model contains an `MLmodel` file with a `triton` flavor
318
+ entry and a copy of the entire directory under `model/`.
319
+
320
+ ```python
321
+ from mlflow_triton import triton
322
+
323
+ model_info = triton.log_model(
324
+ triton_model_path="/tmp/model-repository/iris_classifier",
325
+ name="triton-model",
326
+ registered_model_name="iris-serving",
327
+ )
328
+ print(model_info.registered_model_version)
329
+ ```
330
+
331
+ `triton.load_model("models:/iris-serving/1")` downloads the registered model
332
+ and returns the local Triton model directory. Omit `registered_model_name` to
333
+ save a model without creating a Registry version. This API is in the plugin
334
+ package, not in MLflow's `mlflow.triton` namespace.
335
+
336
+
337
+ ### Arguments for an existing Triton model directory
338
+
339
+ This separate API packages an **existing** Triton model directory. It does not
340
+ create `model.py`, infer a signature or change its configuration.
341
+
342
+ ```python
343
+ triton.log_model(
344
+ triton_model_path,
345
+ name="triton-model",
346
+ registered_model_name=None,
347
+ await_registration_for=300,
348
+ run_id=None,
349
+ metadata=None,
350
+ )
351
+ ```
352
+
353
+ | Argument | Required / default | Meaning |
354
+ | --- | --- | --- |
355
+ | `triton_model_path` | Required | Path to one model-name directory containing at least one positive numbered version directory. Symbolic links are rejected. Pass the model directory, not the parent repository containing multiple models. |
356
+ | `name` | `"triton-model"` | MLflow logged-model name. The existing Triton directory name and configuration are preserved. |
357
+ | `registered_model_name` | `None` | Optional MLflow Registry name. |
358
+ | `await_registration_for` | `300` | Registration wait timeout in seconds. |
359
+ | `run_id` | `None` | Optional MLflow run association. |
360
+ | `metadata` | `None` | Optional model metadata dictionary. |
361
+
362
+ Returns MLflow `ModelInfo`. This API has no `input_example`, `signature`, `device`,
363
+ `tags`, `params` or arbitrary `**kwargs` parameters. Configure serving directly in
364
+ the supplied Triton directory before logging it.
365
+
366
+ ## Examples and optional deployment
367
+
368
+ See [shared examples and validation](https://github.com/ai-lab-tech/mlflow-plugin/blob/main/examples/README.md) and the
369
+ [repository overview](https://github.com/ai-lab-tech/mlflow-plugin/blob/main/README.md). CPU/GPU validation is performed by the
370
+ example runner, not by starting a server inside log_model().
371
+
372
+ For optional Triton Control deployment, install
373
+ [mlflow-triton-control](https://github.com/ai-lab-tech/mlflow-plugin/blob/main/packages/mlflow-triton-control/README.md). A complete Triton
374
+ model repository is the handoff to any chosen deployment tooling.
375
+
376
+ ## Packaging and concurrent loading
377
+
378
+ Packaging checks the target name and device before saving or predicting. It builds
379
+ in a temporary sibling of the destination and renames the completed directory into
380
+ place, cleaning up staging on failure. The native artifact and independent serving
381
+ copy remain separate; intermediate full-package copies are avoided. MLflow may
382
+ still copy/upload the completed artifact during logging. `TMPDIR` selects the outer
383
+ logging workspace; choose a disk with enough room for both model copies and MLflow's
384
+ own temporary storage.
385
+
386
+ Calls through the runtime's `load_predictor` are serialized while MLflow device and
387
+ offline environment settings are temporarily applied, including restoration after
388
+ failure. This lock does not protect unrelated code that modifies `os.environ`,
389
+ direct MLflow loads, or separately imported runtime copies. Coordinate those callers
390
+ or use separate processes. Prediction requests are not serialized by this lock.
391
+
392
+ ## MLflow mapping in Triton configuration
393
+
394
+ Generated repositories store the MLflow-specific mapping as JSON in the
395
+ `parameters.mlflow_contract.string_value` field of `config.pbtxt`. It contains a
396
+ mapping version, framework flavor, input/output structure (columns, single tensor
397
+ or named tensors), original field names and text/binary semantics. Tensor names
398
+ link mapping entries to the standard `input` and `output` configuration fields;
399
+ datatypes and shapes are read exclusively from those fields.
400
+
401
+ Triton passes the configuration to `model.py.initialize()` as `args["model_config"]`.
402
+ The runtime validates and reconstructs its tensor mapping from it. Device placement
403
+ still comes from Triton's assigned instance kind/device ID. No separate
404
+ `contract.json` is generated or read by the new runtime. Unsupported mapping
405
+ versions, missing tensor mappings and nonzero `max_batch_size` fail initialization.
406
+
407
+ Existing logged artifacts retain their original `model.py` and `contract.json`.
408
+ Re-log a model to produce the new layout; do not mix old generated runtime files
409
+ with new configuration. Editing a mapping or tensor schema must remain compatible
410
+ with the saved model's prediction interface and requires renewed validation.
411
+
412
+ ## Ready-to-send inference example
413
+
414
+ Each framework wrapper generates one `request.json` beside `config.pbtxt`, using
415
+ values from `input_example`, concrete tensor shapes and all configured output names.
416
+ See the [central request instructions](https://github.com/ai-lab-tech/mlflow-plugin#send-an-example-request)
417
+ for curl commands. No per-model shell script or instruction file is generated.
418
+ Logging does not send a request.
419
+
420
+ For NaN/infinity or binary byte inputs, the example instead consists of
421
+ `request.bin` (complete HTTP body, including its JSON prefix) and `request.headers`
422
+ (the HTTP content type and JSON-prefix byte length). This uses
423
+ [Triton's binary tensor extension](https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/protocol/extension_binary_data.html)
424
+ without changing input values. Outputs are requested as binary in that case.
425
+
426
+ Example files contain the supplied input values, just like MLflow's stored input
427
+ example; use non-sensitive examples. The direct `triton.log_model()` API for
428
+ pre-existing repositories does not generate requests because it takes no input example.
429
+
430
+ ### Architecture information without loading weights
431
+
432
+ PyTorch and Transformers wrappers automatically include `architecture.json` in the
433
+ MLflow artifact and its self-contained Triton `1/artifact/` copy. Read this JSON
434
+ without importing custom model code or loading weights. It records the model class,
435
+ module classes, parameter/buffer shapes and dtypes (never tensor values), and relative
436
+ paths to packaged Python and configuration files. Transformers reports component
437
+ classes such as the tokenizer; its saved `config.json` contains model configuration.
438
+
439
+ | Argument | Required | Meaning |
440
+ | --- | --- | --- |
441
+ | `architecture_init_kwargs` | No | JSON object documenting constructor arguments, supplied by the caller. Defaults to unknown; never guessed or passed to the constructor. |
442
+
443
+ ```python
444
+ mlflow_triton.pytorch.log_model(
445
+ model,
446
+ input_example=example,
447
+ code_paths=["custom_network.py"],
448
+ architecture_init_kwargs={"input_size": 16, "hidden_size": 32},
449
+ )
450
+ ```
451
+
452
+ The same optional argument is supported by `mlflow_triton.transformers.log_model`.
453
+ Include only non-sensitive architecture settings, never credentials or training data.
454
+ This is documentation, not an automatic reconstruction recipe: module structure
455
+ cannot describe arbitrary `forward()` logic or preprocessing. Constructor settings
456
+ are caller-declared and are not verified against the model. Required custom code
457
+ must still be packaged with the native flavor's code options. Existing artifacts
458
+ are unchanged; the report is generated on subsequent logging. Serving inputs,
459
+ outputs, weights and `config.pbtxt` are unaffected.