Skip to content

rldb/lance: one leaf per recording, sampled over its task segments - #722

Draft
RyanPCo wants to merge 1 commit into
ryanco/rldb-multifrom
ryanco/lance-segments
Draft

RyanPCo wants to merge 1 commit into
ryanco/rldb-multifrom
ryanco/lance-segments

Conversation

@RyanPCo

@RyanPCo RyanPCo commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Leaves are keyed by recording_id. A recording is cut into segments, one per
tasks row plus (with include_taskless_frames) the untasked gaps; filter lambdas
run per segment, so a recording with several tasks or aliases is one leaf
instead of duplicate catalog rows where the last one won. Pins and excludes
take a recording_id or an old clip episode_hash, which narrows or subtracts
that clip's time range. pinned_episode_subset renders a pinned clip alone.

https://claude.ai/code/session_01HjCQBqQCr2igFEMR7yUovw

RyanPCo commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@RyanPCo
RyanPCo force-pushed the ryanco/lance-segments branch from 6373ee6 to e87595e Compare October 22, 2026 14:06
@RyanPCo
RyanPCo changed the base branch from aanchal/mcap-validator to ryanco/rldb-multi October 22, 2026 14:07
@RyanPCo
RyanPCo force-pushed the ryanco/lance-segments branch from e87595e to 68b01e7 Compare October 23, 2026 19:28
@RyanPCo
RyanPCo force-pushed the ryanco/rldb-multi branch 2 times, most recently from 032dbab to 8902fdb Compare October 23, 2026 19:36
@RyanPCo
RyanPCo force-pushed the ryanco/lance-segments branch from 68b01e7 to 8023eba Compare October 23, 2026 19:36
@RyanPCo
RyanPCo force-pushed the ryanco/lance-segments branch from 8023eba to 499170f Compare October 23, 2026 20:03
@RyanPCo
RyanPCo force-pushed the ryanco/lance-segments branch from 499170f to 012b637 Compare October 30, 2026 18:27

@RyanPCo RyanPCo left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Automated adversarial review (read-only; findings were checked by a second skeptical pass before posting): 1 high, 1 low, 3 nit.

filters = _ensure_dataset_filter(filters)
cat = self.catalog()
keep = cat[[filters.matches(row) for row in cat.to_dict("records")]]
recs = self.recordings()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

high (correctness): recs is now the bare recordings table, which has no episode_hash column. LanceStreamingResolver._leaf still calls _chunks_of(t, row.recording_id, kwargs["num_frames"], row.episode_hash), so every streaming resolve raises AttributeError. Pass kwargs["name"] (or row.recording_id) there, and add a non-env-gated unit test that resolves the fixture tables with LanceStreamingResolver.

_, _, tbl = self._open(name)
return tbl.to_table(columns=columns).to_pandas()

def dataset_keys(self, hashes) -> dict[str, str]:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

low (duplication): aliases.lance is read three times per resolve (_ranges for pins, _ranges for excludes, the clips groupby) and once more in dataset_keys. dataset_keys and _ranges also each carry their own copy of the 'a hash is a recording_id or an aliased clip' rule. Suggest reading the table once (e.g. a cached _aliases() frame with all four columns) and building dataset_keys, _ranges and clips from it.

Comment thread egomimic/rldb/lance/dataset.py Outdated
n,
)
anchors = _intervals(mask & eligible)
task_text = [

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

nit (naming): The local task_text is a list of every task's text, but the leaf gets task_text=task_text[0]. Please rename the local to task_texts so it is visible that a multi-task recording's task_text is only its first task.

Comment thread egomimic/rldb/lance/dataset.py Outdated
seg["episode_hash"] = row.recording_id
return segs

def _clocks(self, steps, rows: dict, ranges: dict) -> dict[str, "_Clock"]:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

nit (simplification): _clocks never uses self. Make it a @staticmethod, as the _timestamps it replaces was, or a module-level helper next to _Clock.

Comment thread egomimic/rldb/multi.py
pins = filters.episode_hashes if isinstance(filters, DatasetFilter) else ()
dropped = sorted(set(pins) - set(resolved))
# Lance keys leaves by recording_id; a pin may name the recording or an old clip.
keys = getattr(resolver, "dataset_keys", lambda ps: {p: p for p in ps})(pins)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

nit (simplification): getattr(resolver, "dataset_keys", lambda ps: {p: p for p in ps}) grows the resolver interface by convention, and #726 does the same for manifest. Consider adding dataset_keys (identity) and manifest (None) to the zarr EpisodeResolver base and calling them directly.

Leaves are keyed by recording_id. A recording is cut into segments, one per
tasks row plus (with include_taskless_frames) the untasked gaps; filter lambdas
run per segment, so a recording with several tasks or aliases is one leaf
instead of duplicate catalog rows where the last one won. Pins and excludes
take a recording_id or an old clip episode_hash, which narrows or subtracts
that clip's time range. pinned_episode_subset renders a pinned clip alone.

Claude-Session: https://claude.ai/code/session_01Kt1E8T2x8kdV9akAvbJyVd
@RyanPCo
RyanPCo force-pushed the ryanco/lance-segments branch from 012b637 to 0e76b20 Compare October 30, 2026 23:05
@RyanPCo

RyanPCo commented Oct 30, 2026

Copy link
Copy Markdown
Contributor Author

Review findings: status after the fixup pass. The fixes are squashed into this PR's commits, and the whole stack was force-pushed.

Fixed

  • aliases.lance read several times per resolve: A cached _aliases property (4 columns) serves dataset_keys, _ranges and clips: one read per resolver. The hash-or-recording_id rule is still written in two places.
  • task_text list vs task_text=task_text[0]: Renamed the local to task_texts and added a comment that task_text is the first task's.
  • _clocks does not use self: Now a @staticmethod.
  • LanceStreamingResolver crashes: recordings rows lack episode_hash: _leaf passes kwargs['name'] to _chunks_of. Added a unit test (not env-gated) that resolves the fixture tables with a chunk table. rldb/lance: stream frames from MP4 byte ranges, drop chunk tables #730 later removes chunk tables, and this path with them.

Not fixed

  • Duck-typed getattr(resolver, 'dataset_keys', lambda ...): _from_resolver is documented to accept any object with resolve(), and tests pass such objects. Adding base methods would not remove the getattr fallback, so I left it.

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