← All extensions
MLOps DVC banner

MLOps DVC

ivyx

Adds DVC to the MLOps extension so you can version training data and read which data a run used

MLOps DVC

The DVC engine for the MLOps hub: reproduce the training DAG, read its graph, and see which stages are out of date.

DVC is the real upstream tool — this extension manages it, it does not imitate it. dvc.yaml stays the DAG, dvc repro stays the reproduction, and the cache is DVC's.

What you can do

  • Reproduce your training pipeline and have DVC skip the stages that are already up to date
  • See the shape of your DAG, read straight from dvc.yaml
  • Find out which stages have gone stale, and why, before you rerun anything
  • Have a failed stage stop an MLOps run and name itself, instead of failing obscurely
  • Write a new stage into dvc.yaml without leaving the editor, keeping the comments a hand-written pipeline already has

Requirements

The MLOps extension, the desktop app, and DVC in the Python environment your workspace already uses.

Getting started

This is step 4 of the walkthrough in the MLOps extension's README, which starts from an empty folder and ends with a run that a gate stops. Install this alongside MLOps and the hub picks it up.

How it runs

The interpreter comes from Python Environments (python.env.resolve) and DVC is invoked as <interpreter> -m dvc. There is deliberately no bare dvc and no bare python3: a PATH lookup would pick a different DVC than the one the notebooks and kernels see, and a system Python refuses installs outright (PEP 668).

Install DVC with the panel's install action, or into the active environment yourself. The range this provider is written against is dvc>=3,<4, and the output parsing was measured on 3.67.1.

Capabilities

Capability Policy What it does
mlops.dvc.repro medium / none Runs dvc repro; reports which stages ran, which were cache hits, and where it stopped
mlops.dvc.dag low / none The DAG from dvc.yaml as nodes with dependencies
mlops.dvc.status low / none Which stages are stale, and why
mlops.dvc.lineage low / none Which data the pipeline used and what it produced, each with DVC's digest
mlops.dvc.add medium / none Track a file or directory as data
mlops.dvc.push medium / none Send tracked data to the configured remote
mlops.dvc.pull medium / none Bring tracked data back from the remote
mlops.dvc.checkout medium / none Restore tracked data to the version the cache holds
mlops.dvc.stageAdd medium / none Write one stage into dvc.yaml with its command, dependencies, outputs and metrics
mlops.dvc.stageList low / none Name the stages dvc.yaml already declares
mlops.dvc.reveal low / none Reveal the DVC panel

mlops.dvc.repro answers pass: false with a reason when a stage fails — that is the verdict the MLOps hub records. An unusable environment (no interpreter, no DVC, not a DVC repository, no remote configured) throws instead, with a different sentence for each, because each has a different fix.

Which data a run used

A dvc repro row in an audit trail used to say a pipeline ran and nothing else, which is a problem for anyone who has to show which data a model came from: training happens inside the stage rather than as a governed call, so there is nothing there to derive from.

dvc.lock already holds an md5 for every dependency and every output, so a reproduced run now carries that on its own record. Every path arrives with DVC's own digest beside it, split three ways: the data the run read, the code it read, and what it produced. DVC's bookkeeping decides which is which — a path another stage produces is data, and so is a path with a .dvc file beside it.

A cache hit carries no lineage. It reproduced no stage, so it consumed no dataset and trained no model, and saying otherwise would attach a data claim to a run that did nothing. mlops.dvc.lineage reads the current state of the lock on demand, which is how a report about last week's run gets its answer.

Limits worth knowing

  • No live log. runtime.tasks.run runs a command to completion, so a long dvc repro reports nothing until it finishes. Streaming needs a host-side seam; this is a stated v1 limit.
  • dvc pull with no remote exits 0 and prints "Everything is up to date", and a failed pull prints it too. Both are reported here as what they are rather than as a successful transfer.
  • Electron-only: running processes is not something a browser host does.
  • One reproduction at a time — the hub enforces that; two runs share one cache.

Verification

  • npm run check:dvc replays measured DVC 3.67.1 transcripts (exit 255 for a failed stage, 253 for a non-repository, the two different skip sentences, the --dot graph, status --json) through the shipped parsers.
  • npm run probe:dvc -- /path/to/python builds a throwaway project with its own local remote and drives the same code against a live DVC across 55 checks: first run executes, second run is a cache hit, a broken stage fails with its name, add reports the digest DVC recorded, push/pull/checkout report what actually moved, and the lineage of a run names its data, its code and its outputs. Re-run this after a DVC upgrade — a reworded sentence passes the offline harness and fails in the app.