Commit 8c5b096
MobiusBuilder + cache: produce loadable ORT GenAI composite packages (microsoft#2472)
Three fixes that together let `MobiusBuilder`-produced multimodal ORT
GenAI packages round-trip through Olive without corruption.
## Problem 1: Composite output flattened, sidecars dropped
`mobius.build()` writes a multi-component ORT GenAI package laid out as:
```
<output_dir>/
├── decoder/model.onnx
├── embedding/model.onnx
├── vision_encoder/model.onnx
├── audio_encoder/model.onnx
├── genai_config.json
├── tokenizer.json / tokenizer_config.json / chat_template.jinja
├── image_processor.json
└── audio_feature_extraction.json
```
ORT GenAI reads `genai_config.json` from the root and resolves each
component's relative `filename` (e.g. `decoder/model.onnx`) underneath.
By default Olive's cache **flattens** `CompositeModelHandler` outputs to
top-level `<component_name>.onnx` and **drops sidecars**
(`olive/cache.py:394-407`). Result:
```
output/
├── decoder.onnx, decoder.onnx.data, embedding.onnx, vision_encoder.onnx, audio_encoder.onnx
└── (no genai_config.json, no tokenizer*, no image_processor.json)
```
Breaks ORT GenAI loading entirely.
### Fix (commit 1: `15f7c0f0`)
Set `no_flatten=True` on the `CompositeModelHandler.model_attributes`.
Olive's cache then uses the `shutil.copytree(source_path,
actual_output_dir)` branch, preserving the `<component>/model.onnx`
subdirectory layout and copying every sidecar file alongside.
## Problem 2: Sidecars duplicated into each component dir after a
downstream pass
When a downstream pass (e.g. `OnnxKQuantQuantization`) runs on the
composite, Olive splits it and runs the pass per component
(`olive_pass.py:230-241`). `_carry_forward_additional_files` then copies
each input component's `additional_files` into the output component's
directory.
The original implementation attached the shared package sidecars to
**every** component's `additional_files`. After the quant pass:
```
cuda/int4/models/
├── decoder/{model.onnx, model.onnx.data, genai_config.json, tokenizer.json, image_processor.json, ...}
├── embedding/{model.onnx, model.onnx.data, genai_config.json, tokenizer.json, ...}
├── vision_encoder/...
├── audio_encoder/...
└── (no genai_config.json at root!)
```
Sidecars live in every subdirectory but the root has none — still broken
for ORT GenAI.
### Fix (commit 2: `3b2ac939`)
Attach shared package sidecars to the **CompositeModelHandler**'s
`model_attributes['additional_files']`, not each component's. The
composite's `model_path` *is* the package root, so the cross-pass
carry-forward / `no_flatten` copytree puts them at the root.
Per-component `additional_files` now only carries files that genuinely
live inside the component dir.
## Problem 3: `model_config.json` records nonexistent component paths
`Cache.save_model()`'s `no_flatten` branch (`olive/cache.py:404-407`)
rewrites every component's `model_path` to the composite root while
leaving `onnx_file_name` untouched. For models whose components live
under `<root>/<component>/model.onnx` (both `MobiusBuilder` packages and
`optimum`-exported diffusers pipelines from
`conversion.py:829-831,863`), the saved `model_config.json` then points
each component at `<root>/model.onnx`, which does not exist. Reloading
the saved composite fails.
### Fix (commit 3: `14a15462`)
Rebase each component's `model_path` by its position relative to the
original source dir. A component at `<source>/decoder/` now lands at
`<actual_output_dir>/decoder/`, with `onnx_file_name` unchanged.
Components that fall outside the source tree fall back to the package
root.
## Verification
Two recipes from microsoft/olive-recipes#381:
**`cpu/fp32/config.json` (MobiusBuilder only):**
```
cpu/fp32/models/
├── audio_encoder/model.onnx
├── decoder/model.onnx
├── embedding/model.onnx
├── vision_encoder/model.onnx
├── audio_feature_extraction.json
├── chat_template.jinja
├── genai_config.json
├── image_processor.json
├── tokenizer.json
└── tokenizer_config.json
```
**`cuda/int4/config.json` (MobiusBuilder → OnnxKQuantQuantization):**
```
cuda/int4/models/
├── audio_encoder/{model.onnx, model.onnx.data}
├── decoder/{model.onnx, model.onnx.data}
├── embedding/{model.onnx, model.onnx.data}
├── vision_encoder/{model.onnx, model.onnx.data}
├── audio_feature_extraction.json
├── chat_template.jinja
├── genai_config.json
├── image_processor.json
├── tokenizer.json
└── tokenizer_config.json
```
`model_config.json` records the correct component paths
(`decoder/model.onnx`, `embedding/model.onnx`,
`vision_encoder/model.onnx`,
`audio_encoder/model.onnx`), matching the on-disk layout.
`ruff check` and `ruff format --check` both pass on the changed files.
## Notes
- `no_flatten=True` reuses the existing pattern from the
diffusers/optimum integration (`olive/cache.py:398`).
- `_carry_forward_additional_files` already works for any model whose
`model_path` is a directory (`olive_pass.py:266` `is_dir()` branch), so
`CompositeModelHandler` (whose `model_path` is the package root dir) is
supported without any framework changes.
- The cache-layer component-path rebasing also fixes a latent bug in the
existing optimum/diffusers `no_flatten` consumer; nobody hit it because
nobody had reloaded those saved configs.
- No public API change.
---------
Signed-off-by: justinchuby <11205048+justinchuby@users.noreply.github.com>
Co-authored-by: justinchuby <11205048+justinchuby@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>1 parent 1db66b8 commit 8c5b096
4 files changed
Lines changed: 154 additions & 13 deletions
File tree
- olive
- passes/onnx
- test
- passes/onnx
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
396 | 396 | | |
397 | 397 | | |
398 | 398 | | |
399 | | - | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
400 | 402 | | |
| 403 | + | |
401 | 404 | | |
402 | 405 | | |
403 | 406 | | |
404 | | - | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
405 | 436 | | |
406 | | - | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
407 | 450 | | |
408 | 451 | | |
409 | 452 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
201 | 201 | | |
202 | 202 | | |
203 | 203 | | |
204 | | - | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
205 | 207 | | |
206 | 208 | | |
207 | 209 | | |
| |||
211 | 213 | | |
212 | 214 | | |
213 | 215 | | |
214 | | - | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
215 | 221 | | |
216 | 222 | | |
217 | | - | |
218 | | - | |
219 | 223 | | |
220 | 224 | | |
221 | 225 | | |
222 | 226 | | |
223 | 227 | | |
224 | 228 | | |
225 | | - | |
| 229 | + | |
226 | 230 | | |
227 | 231 | | |
228 | 232 | | |
| |||
234 | 238 | | |
235 | 239 | | |
236 | 240 | | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
237 | 250 | | |
238 | 251 | | |
239 | 252 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
220 | 220 | | |
221 | 221 | | |
222 | 222 | | |
223 | | - | |
| 223 | + | |
224 | 224 | | |
225 | 225 | | |
226 | 226 | | |
227 | 227 | | |
228 | 228 | | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
229 | 239 | | |
230 | 240 | | |
231 | 241 | | |
| |||
240 | 250 | | |
241 | 251 | | |
242 | 252 | | |
243 | | - | |
244 | | - | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
245 | 260 | | |
246 | | - | |
247 | | - | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
248 | 266 | | |
249 | 267 | | |
250 | 268 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
350 | 350 | | |
351 | 351 | | |
352 | 352 | | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
353 | 420 | | |
354 | 421 | | |
355 | 422 | | |
| |||
0 commit comments