Skip to content

Emit explicit ONNX GenAI inference metadata - #434

Merged
justinchuby merged 3 commits into
mainfrom
squad/377-emit-explicit-metadata
Jul 30, 2026
Merged

Emit explicit ONNX GenAI inference metadata#434
justinchuby merged 3 commits into
mainfrom
squad/377-emit-explicit-metadata

Conversation

@justinchuby

Copy link
Copy Markdown
Member

Summary

Emits the explicit, name-agnostic inference metadata required by justinchuby/onnx-genai#377 from the actual exported ONNX graph ports.

  • decoder families: model.io.token_input, inputs_embeds_input, logits_output, sequence_source, kv_ownership, positional kv_inputs/kv_outputs, cross-attention KV ports, and hidden output
  • TensorScatter static-cache exports: model.io.static_cache with the control ports and positionally paired key/value cache input/output lists
  • nested autoregressive Qwen3-TTS: pipeline.strategy.inner_embedding_output plus explicit talker/code-predictor component I/O
  • encoder-decoder exports: explicit encoder prompt role via audio_features_input or token_input, and explicit decoder encoder_hidden_states_input
  • multimodal, speech-to-text, TTS, and bare decoder emission are augmented through one shared graph-introspection path

Example:

model:
  io:
    token_input: input_ids
    sequence_source: token_ids
    logits_output: logits
    kv_ownership: owned
    static_cache:
      write_indices_input: write_indices
      kv_sequence_length_input: nonpad_kv_seqlen
      key_cache_inputs: [key_cache.0]
      value_cache_inputs: [value_cache.0]
      key_cache_outputs: [updated_key_cache.0]
      value_cache_outputs: [updated_value_cache.0]

Validation

  • 81 passed, 1 skipped for ONNX GenAI auto-export/inference/decoder metadata tests
  • 67 passed while validating against the regenerated schema from onnx-genai branch squad/377-explicit-metadata
  • Ruff passed for all changed files

A real large-model export smoke test was not run because weights were not available; synthetic graph fixtures cover dynamic KV, static cache, encoder roles, and nested autoregressive metadata.

Closes justinchuby/onnx-genai#377

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

🏗️ Architecture Diff

Comparing 3791080e609609

Model Sub-model Changes Status

No architecture changes detected.


Legend: ⚪ No change · 🔵 Minor (attrs/inits) · 🟡 Moderate (nodes added/removed) · 🔴 Major (interface changed)

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

Performance Comparison

Comparing 3791080e609609

Model Metric Baseline Current Delta
bert (feature-extraction) model_size_bytes 359 KB 359 KB +0.0%
bert (feature-extraction) num_nodes 60 60 +0.0%
falcon model_size_bytes 364 KB 364 KB +0.0%
falcon num_nodes 68 68 +0.0%
gemma2 model_size_bytes 428 KB 428 KB +0.0%
gemma2 num_nodes 107 107 +0.0%
gpt2 model_size_bytes 388 KB 388 KB +0.0%
gpt2 num_nodes 54 54 +0.0%
llama model_size_bytes 425 KB 425 KB +0.0%
llama num_nodes 62 62 +0.0%
llama (static-cache) model_size_bytes 425 KB 425 KB +0.0%
llama (static-cache) num_nodes 58 58 +0.0%
mamba (ssm-text-generation) model_size_bytes 296 KB 296 KB +0.0%
mamba (ssm-text-generation) num_nodes 98 98 +0.0%
phi3 model_size_bytes 421 KB 421 KB +0.0%
phi3 num_nodes 60 60 +0.0%
phi3 (static-cache) model_size_bytes 421 KB 421 KB +0.0%
phi3 (static-cache) num_nodes 56 56 +0.0%
qwen2 model_size_bytes 425 KB 425 KB +0.0%
qwen2 num_nodes 62 62 +0.0%
qwen2 (static-cache) model_size_bytes 425 KB 425 KB +0.0%
qwen2 (static-cache) num_nodes 58 58 +0.0%
qwen3_5_moe (hybrid-text-generation) model_size_bytes 506 KB 506 KB +0.0%
qwen3_5_moe (hybrid-text-generation) num_nodes 275 275 +0.0%
qwen3_5_text (hybrid-text-generation) model_size_bytes 458 KB 458 KB +0.0%
qwen3_5_text (hybrid-text-generation) num_nodes 129 129 +0.0%
qwen3_5_vl (hybrid-qwen-vl) model_size_bytes 977 KB 977 KB +0.0%
qwen3_5_vl (hybrid-qwen-vl) num_nodes 413 413 +0.0%
t5 (seq2seq) model_size_bytes 836 KB 836 KB +0.0%
t5 (seq2seq) num_nodes 166 166 +0.0%
whisper (speech-to-text) model_size_bytes 1008 KB 1008 KB +0.0%
whisper (speech-to-text) num_nodes 128 128 +0.0%

No performance regressions.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR augments Mobius’s ONNX GenAI sidecar emission to include explicit, name-agnostic inference I/O metadata derived directly from exported ONNX graph ports, enabling runtimes to bind decoder/encoder inputs/outputs (including KV/cache/state) without relying on model-family-specific assumptions.

Changes:

  • Extend decoder I/O introspection to emit explicit roles for token/embedding inputs, logits output, owned KV ports, cross-attention KV ports, optional hidden output, and TensorScatter static-cache ABI.
  • Add add_explicit_package_io() to attach port-derived I/O roles onto emitted metadata for decoder-only, composite pipelines (encoder/decoder), and nested autoregressive (TTS) strategies.
  • Update auto-export to post-process emitted YAML metadata files to include explicit I/O roles; expand tests with dynamic KV, static cache, encoder prompt role, and nested autoregressive coverage.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/mobius/integrations/onnx_genai/inference_metadata.py Adds regex/logic to introspect exported ONNX ports and emit explicit decoder/encoder/static-cache/nested-autoregressive I/O metadata.
src/mobius/integrations/onnx_genai/inference_metadata_test.py Adds unit tests validating explicit decoder roles (dynamic/static KV) and encoder prompt role emission.
src/mobius/integrations/onnx_genai/auto_export.py Post-processes written inference metadata YAML files to inject explicit port-derived I/O metadata.
src/mobius/integrations/onnx_genai/auto_export_test.py Updates fixtures/tests to include graph outputs and assert explicit I/O fields in emitted metadata.

Comment on lines 1013 to 1027
@@ -898,6 +1025,25 @@ def _input_source_map(
"from": f"{decoder_name}.{pair['output']}",
"update": pair["update"],
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 50eb36b. Cross-attention KV input/output pairs are now classified through the same stateful loop mapping as self-attention KV pairs. The new encoder-decoder regression test verifies that both cross key and value inputs point to their matching present outputs with append updates.

Comment on lines +1283 to +1292
if strategy.get("kind") == "nested_autoregressive":
inner_name = strategy.get("inner")
inner_io = component_ios.get(inner_name, {})
hidden_output = inner_io.get("hidden_output")
if not hidden_output:
raise ValueError(
"Cannot emit pipeline.strategy.inner_embedding_output: the inner "
f"decoder {inner_name!r} has no unique non-logits float output"
)
strategy["inner_embedding_output"] = hidden_output

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 50eb36b. Explicit inner_embedding_output values are now preserved without derivation or validation against the unique-output heuristic. Added coverage for preserving an explicit value, deriving it when absent, and raising an actionable error only when absent and ambiguous.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 29, 2026 23:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/mobius/integrations/onnx_genai/auto_export.py:53

  • yaml.safe_load() returns None for an empty file, which will crash in add_explicit_package_io(metadata, ...) (expects a dict and uses metadata.get(...)). Since this helper runs post-write on all generated sidecars, a truncated/empty metadata file would fail the whole export.

Default to {} and guard against non-dict YAML payloads before mutating.

    with open(path, encoding="utf-8") as handle:
        metadata = yaml.safe_load(handle)
    add_explicit_package_io(metadata, pkg, config)
    with open(path, "w", encoding="utf-8") as handle:
        yaml.safe_dump(metadata, handle, sort_keys=False)

Comment thread src/mobius/integrations/onnx_genai/inference_metadata.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 30, 2026 04:50
@justinchuby
justinchuby merged commit 967ab2e into main Jul 30, 2026
22 checks passed
@justinchuby
justinchuby deleted the squad/377-emit-explicit-metadata branch July 30, 2026 04:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

src/mobius/integrations/onnx_genai/auto_export.py:51

  • yaml.safe_load() can return None for an empty document (or a non-mapping type for malformed YAML). _add_explicit_io_to_file() passes that value into add_explicit_package_io(), which will then crash with an unhelpful AttributeError (e.g., 'NoneType' object has no attribute 'get'). Add a small type/None guard here so failures are actionable and don’t surface as a generic attribute error.
    with open(path, encoding="utf-8") as handle:
        metadata = yaml.safe_load(handle)
    add_explicit_package_io(metadata, pkg, config)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make model pipeline metadata name agnostic

2 participants