Skip to content

feat(inspect): render composite pipeline structure (pipeline-led)#903

Open
timenick wants to merge 8 commits into
mainfrom
zhiwang/inspect-composite-ui
Open

feat(inspect): render composite pipeline structure (pipeline-led)#903
timenick wants to merge 8 commits into
mainfrom
zhiwang/inspect-composite-ui

Conversation

@timenick

Copy link
Copy Markdown
Collaborator

Summary

winml inspect now surfaces the composite pipeline structure for composite models (encoder-decoder seq2seq, etc.). Previously a composite was shown as its single exported component — e.g. a bart decoder rendered as Task: text2text-generation with a dangling encoder_hidden_states input ("non-runnable half"), with no hint that the model serves higher-level pipelines.

Before

Task            text2text-generation (via tasks-manager)

After (pipeline-led)

Task            summarization · table-question-answering [composite]
Export          encoder: feature-extraction, decoder: text2text-generation (via tasks-manager)

plus a dedicated Composite Pipeline panel listing the components and how to build a specific pipeline.

Behavior

  • Scoped to auto-detected composites. Gated on the resolver's detected composite (TaskResolution.composite), so only models whose resolved task bridges to a composite show the view. A CLIP inspected for feature-extraction (a runnable single encoder) and all non-composites are unchanged.
  • Architecture-agnostic. The pipeline-task list is derived from the live COMPOSITE_MODEL_REGISTRY (new loader.composite_pipeline_tasks) — no hardcoded model/task names. bart → summarization · table-question-answering, marian → translation, qwen3 → text-generation, etc.
  • JSON contract preserved. task stays the granular machine task (text2text-generation); pipeline_tasks + composite are additive.

API

  • loader.composite_pipeline_tasks(model_type) -> list[str]
  • inspect.CompositeInfo, inspect.resolve_composite_info(...)

Notes

  • Explicit --task / --model-class yields no composite view (pins composite=None) — the pipeline-led view is intentionally scoped to auto-detection.
  • blip (infers image-text-to-text, registers under image-to-text) is not reached by the seq2seq detection bridge today; out of scope here.

timenick added 2 commits June 16, 2026 16:18
Composite models (encoder-decoder seq2seq, etc.) previously inspected as a single
non-runnable component (e.g. a bart decoder shown as Task: text2text-generation with a
dangling encoder_hidden_states input). Inspect now surfaces the composite structure:

- Model Information: the Task row shows the pipeline tasks the model_type serves
  (e.g. 'summarization · table-question-answering [composite]'), with an Export row
  for the component -> export-task breakdown.
- A dedicated 'Composite Pipeline' panel lists the components and how to build one.
- JSON: 'task' stays the granular machine task (unchanged contract); additive
  'pipeline_tasks' + 'composite' fields.

Gated on the resolver's detected composite (TaskResolution.composite), so only
auto-detected composites render the view -- CLIP inspected for feature-extraction and
other single-component exports are unchanged. pipeline_tasks are derived from the live
COMPOSITE_MODEL_REGISTRY (new loader.composite_pipeline_tasks), architecture-agnostic.

New API: loader.composite_pipeline_tasks; inspect.CompositeInfo + resolve_composite_info.
@timenick timenick requested a review from a team as a code owner June 16, 2026 08:21

@DingmaomaoBJTU DingmaomaoBJTU left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Good overall architecture — the pipeline-led composite view is clearly scoped (gated on resolver detection, not registry presence alone) and the additive JSON design is clean. I found a few correctness issues worth fixing before merge.

Comment thread src/winml/modelkit/inspect/resolver.py Outdated
Comment thread src/winml/modelkit/loader/resolution.py Outdated
Comment thread src/winml/modelkit/inspect/formatter.py
Comment thread src/winml/modelkit/loader/resolution.py Outdated
Comment thread tests/unit/inspect/test_composite_rendering.py
timenick added 3 commits June 17, 2026 14:47
Address review on #903: resolve_composite_info now returns None when the detected
composite yields no pipeline tasks for the model_type (registry divergence), instead of
building a CompositeInfo with empty pipeline_tasks that renders a broken '[composite]'
Task row. Add a regression test pinning the guard.

@DingmaomaoBJTU DingmaomaoBJTU left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Follow-up review after commit 90f24b8.

Resolved: Finding #1 (downstream): the pipeline_tasks=[] guard was added in resolve_composite_infoCompositeInfo with empty pipeline_tasks no longer reaches the formatter. Finding #5: the registry-divergence monkeypatch test was added.

Still open: Three issues remain — the falsy None/{} conflation in the same guard, the issubclass registry inconsistency that is the root cause of finding #2, and the formatter's own lack of a guard (finding #3). The side-effect import warning (#4) is also unaddressed.

Comment thread src/winml/modelkit/inspect/resolver.py Outdated
Comment thread src/winml/modelkit/loader/resolution.py Outdated
Comment thread src/winml/modelkit/inspect/formatter.py
Comment thread src/winml/modelkit/loader/resolution.py Outdated
timenick added 3 commits June 18, 2026 10:18
…tighten guards

- register_composite_model now requires a WinMLCompositeModel subclass, making the
  registry invariant explicit at its single write point; the (now redundant)
  issubclass filters in composite_pipeline_tasks and _composite_components_for_task
  are removed so all readers uniformly trust the registry (matching resolve_composite)
- resolve_composite_info gates on `detected_components is None` (not falsy) so a
  genuine empty-breakdown composite is not conflated with the un-set case
- output_table guards both composite branches on pipeline_tasks so a directly
  constructed CompositeInfo with empty pipeline_tasks cannot render a bare
  [composite] Task row
- tests: registry invariant, empty-components case, formatter empty-pipeline guard
…accessor

- Add _composite_registry(): the single registry-load trigger the three readers
  (resolve_composite / composite_pipeline_tasks / _composite_components_for_task)
  now share. It raises RuntimeError when COMPOSITE_MODEL_REGISTRY is empty, so a
  moved/renamed registration fails loudly instead of silently returning []/None
  and disabling the composite feature unnoticed.
- Fix a mypy break the main merge surfaced: #896 re-tightened the
  _composite_components_for_task annotation to type[WinMLCompositeModel] while the
  prior commit had removed that import; re-add it under TYPE_CHECKING.
- Test: the accessor raises loudly when the registry is empty.
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.

2 participants