Skip to content

Feature/mvp inference - #9

Draft
dougbrn wants to merge 7 commits into
devfrom
feature/mvp-inference
Draft

dougbrn wants to merge 7 commits into
devfrom
feature/mvp-inference

Conversation

@dougbrn

@dougbrn dougbrn commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

Change Description

MVP of the initial design: column spec + inference only. Training is deferred to a follow-up. Design: docs/design/initial-design.md (design PR).

Includes docs/design/mvp-design.md, a trimmed design covering only what this PR ships; the full design (including training) is on the design/initial-design branch.

Solution Description

  • Adds lsdb>=0.11 and torch>=2.4 as core dependencies.
  • ColumnSpec / Flat / Nested: maps numeric flat and nested catalog columns to tensors. resolve() validates against catalog meta (nested sub-column types via NestedDtype.column_dtypes) without computing data, reporting every problem at once. This replaces the hand-built column preview from hyrax#1062.
  • Nested columns are zero-padded to the batch maximum with <key>_mask and <key>_lengths, vectorized, with optional max_length and head/tail truncation. Empty or null nested rows have length 0. Missing values raise.
  • predict(catalog, model, spec, outputs) / ModelDeployment: a Dask WorkerPlugin builds the model once per worker from a ModelSpec (factory + state-dict path, or an in-memory module), in eval() mode on a device resolved on the worker (default "cpu", "auto" opt-in). Returns a lazy lsdb.Catalog with correct meta. Requires a dask.distributed Client.
  • Alignment by construction: each partition is processed in order with task-local state only (no shared mutable dataset), and predictions are attached by position, never joined on _healpix_29. Row counts are checked per batch.
  • Example: docs/examples/predict_on_catalog.py.

Tests: spec validation (including a no-compute guard), collation against a per-row reference, alignment after a filter that empties partitions plus reordering, duplicate _healpix_29 values, one model build per worker, meta dtypes matching computed data, and failure modes. A deliberately reversed batch order makes the alignment tests fail.

Deferred from the fuller branches: transforms, pad_to/pad_value, null filling, dict outputs, no-client mode, and all of training.

Note: CI only triggers on main, so this PR gets no CI until dev is added to the workflow triggers (design doc §12).

🤖 Generated with Claude Code

dougbrn and others added 5 commits October 15, 2026 13:35
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ColumnSpec maps flat and nested numeric catalog columns to tensors.
resolve() validates against catalog meta (nested sub-column dtypes come
from NestedDtype.column_dtypes) without computing data, and reports
every problem at once. Nested columns are zero-padded to the batch
maximum with a mask and lengths, vectorized via nest.len() and
nest.to_flat(), with optional max_length truncation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ModelDeployment registers a WorkerPlugin that builds the model once
per Dask worker from a ModelSpec (factory + state dict path, or an
in-memory module), in eval mode on a device resolved on the worker.
predict() maps each partition in order with task-local state and
attaches predictions by position, so output stays aligned with input
even for duplicate _healpix_29 values. OutputSpec builds the output
meta and checks every batch's output shape and row count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Trimmed design covering only what this branch ships (column spec and
inference), with deferred items pointing to the full design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dougbrn
dougbrn changed the base branch from main to dev October 15, 2026 20:43
@codecov

codecov Bot commented Oct 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.94017% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 95.99%. Comparing base (c9ed114) to head (e391572).

Files with missing lines Patch % Lines
src/lsdb_ml/spec.py 95.78% 8 Missing ⚠️
src/lsdb_ml/inference/plugin.py 92.18% 5 Missing ⚠️
src/lsdb_ml/device.py 86.36% 3 Missing ⚠️
src/lsdb_ml/inference/outputs.py 96.07% 2 Missing ⚠️
src/lsdb_ml/collate.py 97.77% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##               dev       #9      +/-   ##
===========================================
- Coverage   100.00%   95.99%   -4.01%     
===========================================
  Files            2       10       +8     
  Lines            7      474     +467     
===========================================
+ Hits             7      455     +448     
- Misses           0       19      +19     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread docs/design/mvp-design.md Outdated
- output keys don't collide.

Every problem is reported in one `SpecError`.
- **Nested representation: zero padding with a mask.** Each batch is padded to its longest

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Padding here seems questionable, it's not padded globally, but per batch.

Comment thread docs/design/mvp-design.md Outdated
dougbrn and others added 2 commits October 16, 2026 14:37
Inputs are now plain catalog column names: flat columns by name and
nested sub-columns by LSDB's dotted names ('lc.flux'). Flat vs nested
and dtypes are read from catalog meta, checked before any data is
read, and dry-run on the empty meta frame. Batches are keyed by those
names; each nested column contributes a shared '<column>._mask' and
'<column>._lengths'. The model receives the batch dict, or a
forward(model, batch) adapter for positional models. Data preparation
is left to ordinary LSDB operations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both accept a single value for every nested input or a mapping keyed
by nested column name, for multi-modal catalogs with several light
curve and spectrum columns. Keys are column names rather than dotted
sub-column names because sub-columns share one mask; unknown keys,
dotted keys and invalid values are reported with the other input
problems before any data is read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant