Skip to content

Commit 4e70d8d

Browse files
justinchubyCopilot
andauthored
Migrate task files to new GraphBuilder input/output APIs (#231)
## Summary Migrate all 24 task files under `src/mobius/tasks/` to use the new onnxscript `GraphBuilder.input()` and `GraphBuilder.add_output()` APIs, replacing manual `ir.Value()` construction and `graph.outputs.append()` patterns. ## Changes - **`_base.py`**: `_make_graph()` no longer takes an inputs parameter. Inputs are now created via `builder.input(name, dtype, shape)` which auto-registers them on the graph. - **`_cache_utils.py`**: Cache helper functions (`_make_kv_cache_inputs`, `_make_hybrid_cache_inputs`, `_register_kv_cache_outputs`, `_register_hybrid_cache_outputs`) now take `builder` as first parameter. Return types simplified — flat input lists removed since `builder.input()` auto-registers. - **All 24 task files**: `ir.Value(name=..., shape=ir.Shape(...), type=ir.TensorType(...))` → `builder.input(name, dtype=..., shape=[...])`; `value.name = name; graph.outputs.append(value)` → `builder.add_output(value, name)` - **Import cleanup**: `GraphBuilder` imported from public `onnxscript` namespace instead of `onnxscript._internal.builder` - **Naming consistency**: Standardized `builder` variable name across all files ## Impact - 24 files changed, 571 insertions, 903 deletions (net -332 lines) - Eliminates dual-bookkeeping anti-pattern (separate input list + graph registration) - Input ordering structurally guaranteed by call order - Output registration is atomic (single call vs two-step name+append) - All 2662 tests pass ## Note `op.call()` migration for module/function invocations is out of scope — `op.call()` currently only accepts `ir.Function`, not `nn.Module`, and treats kwargs as ONNX attributes rather than tensor inputs. This requires upstream onnxscript changes. --------- Signed-off-by: Justin Chu <justinchu@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 419467e commit 4e70d8d

24 files changed

Lines changed: 706 additions & 902 deletions

src/mobius/tasks/_adapter.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,31 @@ def build(
2323
module,
2424
config,
2525
) -> ModelPackage:
26+
graph, builder = _make_graph()
27+
op = builder.op
28+
2629
# Determine input shape based on adapter type
2730
if hasattr(config, "in_channels"):
2831
# T2I-Adapter: conditioning image input
29-
condition = ir.Value(
30-
name="condition",
31-
type=ir.TensorType(ir.DataType.FLOAT),
32-
shape=ir.Shape(("batch", config.in_channels, "height", "width")),
32+
condition = builder.input(
33+
"condition",
34+
dtype=ir.DataType.FLOAT,
35+
shape=["batch", config.in_channels, "height", "width"],
3336
)
3437
else:
3538
# IP-Adapter: image embedding input
36-
condition = ir.Value(
37-
name="image_embeds",
38-
type=ir.TensorType(ir.DataType.FLOAT),
39-
shape=ir.Shape(("batch", config.image_embed_dim)),
39+
condition = builder.input(
40+
"image_embeds",
41+
dtype=ir.DataType.FLOAT,
42+
shape=["batch", config.image_embed_dim],
4043
)
4144

42-
graph, builder = _make_graph([condition])
43-
op = builder.op
44-
4545
outputs = module(op, condition)
4646

4747
if isinstance(outputs, list):
4848
for i, out in enumerate(outputs):
49-
out.name = f"feature_{i}"
50-
graph.outputs.append(out)
49+
builder.add_output(out, f"feature_{i}")
5150
else:
52-
outputs.name = "adapter_output"
53-
graph.outputs.append(outputs)
51+
builder.add_output(outputs, "adapter_output")
5452

5553
return ModelPackage({"model": _make_model(graph)}, config=config)

src/mobius/tasks/_audio_feature_extraction.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,15 @@ def build(
2828
module,
2929
config: ArchitectureConfig,
3030
) -> ModelPackage:
31-
input_values = ir.Value(
32-
name="input_values",
33-
type=ir.TensorType(ir.DataType.FLOAT),
34-
shape=ir.Shape(("batch", "time")),
35-
)
36-
37-
graph, builder = _make_graph([input_values])
31+
graph, builder = _make_graph()
3832
op = builder.op
3933

34+
input_values = builder.input(
35+
"input_values", dtype=ir.DataType.FLOAT, shape=["batch", "time"]
36+
)
37+
4038
last_hidden_state = module(op, input_values=input_values)
4139

42-
last_hidden_state.name = "last_hidden_state"
43-
graph.outputs.append(last_hidden_state)
40+
builder.add_output(last_hidden_state, "last_hidden_state")
4441

4542
return ModelPackage({"model": _make_model(graph)}, config=config)

src/mobius/tasks/_base.py

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
from typing import ClassVar
1010

1111
import onnx_ir as ir
12-
from onnxscript import nn
13-
from onnxscript._internal.builder import GraphBuilder
12+
from onnxscript import GraphBuilder, nn
1413

1514
import mobius
1615
from mobius._configs import BaseModelConfig
@@ -103,16 +102,18 @@ def __repr__(self) -> str:
103102

104103

105104
def _make_graph(
106-
inputs: list[ir.Value],
107105
name: str = "main_graph",
108106
) -> tuple[ir.Graph, GraphBuilder]:
109107
"""Create an empty graph and its builder.
110108
109+
Inputs should be added after creation via ``builder.input()``.
110+
Outputs should be registered via ``builder.add_output()``.
111+
111112
Returns:
112113
``(graph, builder)`` — call ``builder.op`` to get the op handle.
113114
"""
114115
graph = ir.Graph(
115-
inputs,
116+
[],
116117
[],
117118
nodes=[],
118119
name=name,
@@ -237,45 +238,44 @@ def build_decoder_from_embeds(
237238
seq_len = ir.SymbolicDim("sequence_len")
238239
past_seq_len = ir.SymbolicDim("past_sequence_len")
239240

240-
inputs_embeds = ir.Value(
241-
name="inputs_embeds",
242-
shape=ir.Shape([batch, seq_len, config.hidden_size]),
243-
type=ir.TensorType(config.dtype),
241+
graph, builder = _make_graph()
242+
inputs_embeds = builder.input(
243+
"inputs_embeds",
244+
dtype=config.dtype,
245+
shape=[batch, seq_len, config.hidden_size],
244246
)
245-
attention_mask = ir.Value(
246-
name="attention_mask",
247-
shape=ir.Shape([batch, "past_seq_len + seq_len"]),
248-
type=ir.TensorType(ir.DataType.INT64),
247+
attention_mask = builder.input(
248+
"attention_mask",
249+
dtype=ir.DataType.INT64,
250+
shape=[batch, "past_seq_len + seq_len"],
249251
)
250252
# MRoPE: 3D position IDs (temporal, height, width) — shape [3, batch, seq_len]
251253
# Standard: shape [batch, seq_len]
252-
position_ids = ir.Value(
253-
name="position_ids",
254-
shape=ir.Shape([3, batch, seq_len] if mrope else [batch, seq_len]),
255-
type=ir.TensorType(ir.DataType.INT64),
254+
position_ids = builder.input(
255+
"position_ids",
256+
dtype=ir.DataType.INT64,
257+
shape=[3, batch, seq_len] if mrope else [batch, seq_len],
256258
)
257259

258-
graph_inputs = [inputs_embeds, attention_mask, position_ids]
259-
260260
if hybrid:
261-
cache_inputs, past_key_values = _make_hybrid_cache_inputs(
261+
past_key_values = _make_hybrid_cache_inputs(
262+
builder,
262263
config,
263264
config.dtype,
264265
batch,
265266
past_seq_len,
266267
)
267268
else:
268-
cache_inputs, past_key_values = _make_kv_cache_inputs(
269+
past_key_values = _make_kv_cache_inputs(
270+
builder,
269271
config.num_hidden_layers,
270272
config.num_key_value_heads,
271273
config.head_dim,
272274
config.dtype,
273275
batch,
274276
past_seq_len,
275277
)
276-
graph_inputs.extend(cache_inputs)
277278

278-
graph, builder = _make_graph(graph_inputs)
279279
logits, present_key_values = decoder(
280280
builder.op,
281281
inputs_embeds=inputs_embeds,
@@ -284,20 +284,19 @@ def build_decoder_from_embeds(
284284
past_key_values=past_key_values,
285285
)
286286

287-
logits.name = "logits"
288-
graph.outputs.append(logits)
287+
builder.add_output(logits, "logits")
289288

290289
if hybrid:
291290
_register_hybrid_cache_outputs(
292-
graph,
291+
builder,
293292
present_key_values,
294293
config.layer_types or [],
295294
)
296295
model = _make_model(graph)
297296
_register_linear_attention_functions(model, config)
298297
return model
299298
else:
300-
_register_kv_cache_outputs(graph, present_key_values)
299+
_register_kv_cache_outputs(builder, present_key_values)
301300
return _make_model(graph)
302301

303302

@@ -328,24 +327,23 @@ def build_embedding_from_features(
328327
seq_len = ir.SymbolicDim("sequence_len")
329328
num_feature_tokens = ir.SymbolicDim("num_feature_tokens")
330329

331-
input_ids = ir.Value(
332-
name="input_ids",
333-
shape=ir.Shape([batch, seq_len]),
334-
type=ir.TensorType(ir.DataType.INT64),
330+
graph, builder = _make_graph(name="embedding")
331+
input_ids = builder.input(
332+
"input_ids",
333+
dtype=ir.DataType.INT64,
334+
shape=[batch, seq_len],
335335
)
336-
features = ir.Value(
337-
name=feature_name,
338-
shape=ir.Shape([num_feature_tokens, feature_dim]),
339-
type=ir.TensorType(config.dtype),
336+
features = builder.input(
337+
feature_name,
338+
dtype=config.dtype,
339+
shape=[num_feature_tokens, feature_dim],
340340
)
341341

342-
graph, builder = _make_graph([input_ids, features], name="embedding")
343342
inputs_embeds = embedding(
344343
builder.op,
345344
input_ids=input_ids,
346345
**{feature_name: features},
347346
)
348347

349-
inputs_embeds.name = "inputs_embeds"
350-
graph.outputs.append(inputs_embeds)
348+
builder.add_output(inputs_embeds, "inputs_embeds")
351349
return _make_model(graph)

0 commit comments

Comments
 (0)