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.yamlwithout 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.runruns a command to completion, so a longdvc reproreports nothing until it finishes. Streaming needs a host-side seam; this is a stated v1 limit. dvc pullwith 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:dvcreplays measured DVC 3.67.1 transcripts (exit 255 for a failed stage, 253 for a non-repository, the two different skip sentences, the--dotgraph,status --json) through the shipped parsers.npm run probe:dvc -- /path/to/pythonbuilds 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,addreports the digest DVC recorded,push/pull/checkoutreport 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.