hflow 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hflow-0.2.0 → hflow-0.2.2}/PKG-INFO +57 -42
- {hflow-0.2.0 → hflow-0.2.2}/README.md +52 -41
- {hflow-0.2.0 → hflow-0.2.2}/pyproject.toml +17 -2
- {hflow-0.2.0 → hflow-0.2.2}/pyproject.toml.orig +29 -2
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/__init__.py +52 -4
- hflow-0.2.2/src/hflow/_grouped_mcap_writer/__init__.py +19 -0
- hflow-0.2.0/src/hflow/mcap_writer.py → hflow-0.2.2/src/hflow/_grouped_mcap_writer/_writer.py +94 -58
- hflow-0.2.2/src/hflow/_pinned_asset.py +80 -0
- hflow-0.2.2/src/hflow/_video_measurement_toolchain.py +56 -0
- hflow-0.2.2/src/hflow/_video_measurements/__init__.py +54 -0
- hflow-0.2.2/src/hflow/_video_measurements/_camera_motion.py +319 -0
- hflow-0.2.2/src/hflow/_video_measurements/_frame_statistics.py +714 -0
- hflow-0.2.2/src/hflow/_video_measurements/_raw_frames.py +168 -0
- hflow-0.2.2/src/hflow/_video_measurements/_toolchain.py +30 -0
- hflow-0.2.2/src/hflow/app.py +2262 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/batching.py +7 -5
- hflow-0.2.2/src/hflow/behavior.py +73 -0
- hflow-0.2.2/src/hflow/catalog.py +902 -0
- hflow-0.2.2/src/hflow/checks.py +1556 -0
- hflow-0.2.2/src/hflow/cli.py +1256 -0
- hflow-0.2.2/src/hflow/curation.py +630 -0
- hflow-0.2.2/src/hflow/dataset.py +327 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/episode.py +23 -20
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/ffmpeg/__init__.py +1 -6
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/ffmpeg/_binary.py +16 -35
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/ffmpeg/_contact_sheet.py +26 -6
- hflow-0.2.2/src/hflow/format.py +197 -0
- hflow-0.2.2/src/hflow/ingest_ledger.py +192 -0
- hflow-0.2.2/src/hflow/manifest.py +147 -0
- hflow-0.2.2/src/hflow/mediapipe_hands.py +492 -0
- hflow-0.2.2/src/hflow/project.py +182 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/resample.py +96 -11
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/__init__.py +30 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_bundle.py +403 -41
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_client.py +131 -22
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_deploy.py +75 -22
- hflow-0.2.2/src/hflow/runtime/_endpoint.py +128 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_lifecycle.py +4 -1
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_templates.py +156 -161
- hflow-0.2.2/src/hflow/runtime/_topology.py +201 -0
- hflow-0.2.2/src/hflow/snapshot.py +689 -0
- hflow-0.2.2/src/hflow/stage_execution.py +481 -0
- hflow-0.2.2/src/hflow/stage_planning.py +269 -0
- hflow-0.2.2/src/hflow/steps.py +425 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/storage.py +39 -4
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/testing.py +36 -12
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/transform.py +255 -31
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/video.py +38 -0
- hflow-0.2.2/src/hflow/workspace.py +166 -0
- hflow-0.2.0/src/hflow/app.py +0 -1109
- hflow-0.2.0/src/hflow/catalog.py +0 -476
- hflow-0.2.0/src/hflow/checks.py +0 -400
- hflow-0.2.0/src/hflow/cli.py +0 -523
- hflow-0.2.0/src/hflow/curation.py +0 -385
- hflow-0.2.0/src/hflow/ffmpeg/_instrument.py +0 -239
- hflow-0.2.0/src/hflow/format.py +0 -106
- hflow-0.2.0/src/hflow/steps.py +0 -364
- {hflow-0.2.0 → hflow-0.2.2}/LICENSE +0 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/doctor.py +0 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/providers.py +0 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/py.typed +0 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/reader.py +0 -0
- {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_compose.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hflow
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Open source SDK for building Physical AI data pipelines
|
|
5
5
|
Keywords: airflow,data-pipeline,data-quality,dataset-curation,mcap,physical-ai,robotics
|
|
6
6
|
Author: Hebbian Robotics, Kingston Kuan, Brandon Ong
|
|
@@ -15,6 +15,8 @@ Requires-Dist: numpy>=2.4.6
|
|
|
15
15
|
Requires-Dist: zstandard>=0.25.0
|
|
16
16
|
Requires-Dist: pyarrow>=25.0.1 ; extra == 'arrow'
|
|
17
17
|
Requires-Dist: obstore>=0.10.0 ; extra == 'bucket'
|
|
18
|
+
Requires-Dist: mediapipe>=1.0.0 ; extra == 'mediapipe'
|
|
19
|
+
Requires-Dist: opencv-python-headless>=4.10 ; extra == 'motion'
|
|
18
20
|
Requires-Dist: openai>=3.0.0 ; extra == 'openai'
|
|
19
21
|
Requires-Python: >=3.11
|
|
20
22
|
Project-URL: Repository, https://github.com/Hebbian-Robotics/hflow
|
|
@@ -22,6 +24,8 @@ Project-URL: Documentation, https://github.com/Hebbian-Robotics/hflow/tree/main/
|
|
|
22
24
|
Project-URL: Issues, https://github.com/Hebbian-Robotics/hflow/issues
|
|
23
25
|
Provides-Extra: arrow
|
|
24
26
|
Provides-Extra: bucket
|
|
27
|
+
Provides-Extra: mediapipe
|
|
28
|
+
Provides-Extra: motion
|
|
25
29
|
Provides-Extra: openai
|
|
26
30
|
Description-Content-Type: text/markdown
|
|
27
31
|
|
|
@@ -35,7 +39,7 @@ Description-Content-Type: text/markdown
|
|
|
35
39
|
|
|
36
40
|
<h1 align="center">HFlow</h1>
|
|
37
41
|
|
|
38
|
-
<p align="center"><strong>Open source SDK for
|
|
42
|
+
<p align="center"><strong>Open source SDK for scalable multimodal data pipelines in robotics and physical AI</strong></p>
|
|
39
43
|
|
|
40
44
|
<p align="center">
|
|
41
45
|
<a href="https://www.ycombinator.com/companies/hebbian-robotics">
|
|
@@ -49,25 +53,27 @@ Description-Content-Type: text/markdown
|
|
|
49
53
|
</a>
|
|
50
54
|
</p>
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
Hebbian Robotics (YC S26) is building HFlow, an open source SDK for scalable
|
|
57
|
+
multimodal data pipelines in robotics and physical AI. It makes data tooling and
|
|
58
|
+
practices typically developed inside large robotics teams accessible to teams of
|
|
59
|
+
any size.
|
|
60
|
+
|
|
61
|
+
We believe processing data is a major bottleneck in robotics. A corpus can combine
|
|
62
|
+
video, state, actions, timestamps, and metadata from many recording systems. Teams
|
|
63
|
+
often feel the problem first in quality control: determining whether cameras froze,
|
|
64
|
+
streams drifted out of sync, required topics disappeared, or duplicate recordings
|
|
65
|
+
entered the corpus. As the corpus grows, fragmented scripts make it difficult to
|
|
66
|
+
know what ran, audit the results, or reproduce a dataset.
|
|
67
|
+
|
|
68
|
+
Teams can start with HFlow's built-in checks, write new transformations, checks,
|
|
69
|
+
labels, and enrichments, or connect processing code they already use. HFlow handles
|
|
70
|
+
the orchestration, storage, versioning, and curation around those steps.
|
|
55
71
|
|
|
56
72
|
HFlow stamps each processed episode with its provenance, renders the pipeline
|
|
57
73
|
as a graph, and records metadata and quality evidence in a queryable catalog.
|
|
58
74
|
You can trace how outputs were produced, monitor every stage, and
|
|
59
75
|
investigate a corpus without loading the underlying recordings.
|
|
60
76
|
|
|
61
|
-
The design is an open source implementation of Dyna Robotics'
|
|
62
|
-
["Training Dyna-2 at million-hour scale, repeatably"](https://www.dyna.co/research/dyna-2-infrastructure) article,
|
|
63
|
-
published August 2026. Dyna-2 was trained on more than one million hours of
|
|
64
|
-
egocentric video data, and the post describes the reusable infrastructure that
|
|
65
|
-
made processing and experimenting with that data repeatable. You can think of
|
|
66
|
-
HFlow as an independent, open-source implementation of those public ideas,
|
|
67
|
-
adapted for people who need the same foundation without Dyna's million-hour
|
|
68
|
-
production stack. It is not Dyna's private source code or an undisclosed
|
|
69
|
-
wire-compatible production system.
|
|
70
|
-
|
|
71
77
|
MCAP is HFlow's v1 input and output boundary because it efficiently stores
|
|
72
78
|
and serves synchronized video, state, action, and other time-series streams.
|
|
73
79
|
That format requirement does not define where the data comes from: human-worn
|
|
@@ -75,13 +81,13 @@ cameras, teleoperated robots, autonomous policies, and other collection systems
|
|
|
75
81
|
can all feed the pipeline once their data is represented as a supported MCAP
|
|
76
82
|
episode.
|
|
77
83
|
|
|
78
|
-
> **Status: pre-v1, with the core lifecycle working end to end.** HFlow is ready to try locally. See [what is implemented](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md#
|
|
84
|
+
> **Status: pre-v1, with the core lifecycle working end to end.** HFlow is ready to try locally. See [what is implemented](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md#implementation-status) and [open issues](https://github.com/Hebbian-Robotics/hflow/issues) for current details and remaining work.
|
|
79
85
|
|
|
80
|
-
**Help
|
|
86
|
+
**Help grow the open robotics community.** [Star the repository](https://github.com/Hebbian-Robotics/hflow), share it with your network, or [contribute](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md). Our goal is an open source community where anyone can participate in building the future of robotics. No robot hardware is required to contribute.
|
|
81
87
|
|
|
82
88
|
| | HFlow's boundary |
|
|
83
89
|
| --- | --- |
|
|
84
|
-
| **Input** | One multimodal episode per standard MCAP file |
|
|
90
|
+
| **Input** | One multimodal episode per standard MCAP file (`hflow doctor` says whether yours qualifies) |
|
|
85
91
|
| **Processing** | Your Python transforms, checks, labels, and enrichments |
|
|
86
92
|
| **Execution** | In-process for development; generated Airflow 3 DAGs for scheduled runs |
|
|
87
93
|
| **Durable output** | Canonical MCAP episodes, provenance, artifacts, and a Parquet catalog |
|
|
@@ -89,7 +95,7 @@ episode.
|
|
|
89
95
|
|
|
90
96
|
## What you get
|
|
91
97
|
|
|
92
|
-
Human and robot data move through
|
|
98
|
+
Human and robot data move through a four-stage lifecycle:
|
|
93
99
|
|
|
94
100
|
```
|
|
95
101
|
collection --> ingestion ---------------> curation ------> delivery
|
|
@@ -103,7 +109,7 @@ collection --> ingestion ---------------> curation ------> delivery
|
|
|
103
109
|
</p>
|
|
104
110
|
|
|
105
111
|
- **Your processing code stays yours.** Transformations, quality checks, labels, and enrichments are plain Python functions in your own environment. Existing code plugs in through small adapters instead of being rewritten for a proprietary framework.
|
|
106
|
-
- **Episodes are MCAP**, the container that ROS 2 records natively and [Foxglove](https://foxglove.dev/)/[Rerun](https://rerun.io/) open directly, written with
|
|
112
|
+
- **Episodes are MCAP**, the container that ROS 2 records natively and [Foxglove](https://foxglove.dev/)/[Rerun](https://rerun.io/) open directly, written with two tunings described in Dyna's article: in-band H.264 with GOP length matched to how the data is read, and **topic-group chunking** (camera streams and state streams never share a chunk, so a training sample costs one read per group instead of one per topic).
|
|
107
113
|
- **Processed episodes carry their provenance.** The file itself records the schema, pipeline, and tool versions that produced it, plus its source URI when available. Catalog records connect measurements and outcomes to step versions, making it easier to trace a bad result back to its origin.
|
|
108
114
|
- **The pipeline is visible as a graph.** HFlow renders Airflow DAGs so you can see how stages connect and monitor task status, logs, retries, and reruns.
|
|
109
115
|
- **Quality checks produce reusable evidence.** Accessors extract the inputs existing processing code expects (numpy arrays, MP4 paths, JPEG frames), and results land as queryable measurements rather than hardcoded verdicts. Different datasets can apply different thresholds without processing the media again.
|
|
@@ -121,6 +127,11 @@ same engine can be scaled as multiple isolated workspaces (for example, one
|
|
|
121
127
|
per team or customer) behind an external control plane. That is the intended
|
|
122
128
|
path to a future hosted version, but the hosted control plane is not
|
|
123
129
|
implemented in this repository and is not a pre-v1 release commitment.
|
|
130
|
+
[docs/HOSTING.md](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/HOSTING.md)
|
|
131
|
+
documents the data-plane contract that makes such a control plane an
|
|
132
|
+
addition rather than a rearchitecture: the workspace unit, the seams a
|
|
133
|
+
service drives (manifests, remote runtime addressing, credential injection),
|
|
134
|
+
the trust model, and the current limits.
|
|
124
135
|
|
|
125
136
|
## Community and hosted interest
|
|
126
137
|
|
|
@@ -149,7 +160,7 @@ To run the repository's bundled quickstart:
|
|
|
149
160
|
```bash
|
|
150
161
|
git clone https://github.com/Hebbian-Robotics/hflow.git
|
|
151
162
|
cd hflow
|
|
152
|
-
uv sync --locked
|
|
163
|
+
uv sync --locked
|
|
153
164
|
uv run python examples/quickstart.py
|
|
154
165
|
```
|
|
155
166
|
|
|
@@ -176,24 +187,28 @@ and other physical-AI recordings.
|
|
|
176
187
|
|
|
177
188
|
```python
|
|
178
189
|
import hflow
|
|
190
|
+
from hflow.checks import camera_frame_stats
|
|
179
191
|
from your_existing_qc import check_joint_smoothness # use your existing checks
|
|
180
192
|
|
|
181
|
-
app = hflow.App("kitchen-pipeline",
|
|
193
|
+
app = hflow.App("kitchen-pipeline") # data root: $HFLOW_DATA_ROOT, hflow.toml, else ./data
|
|
182
194
|
|
|
183
195
|
|
|
184
|
-
@app.check()
|
|
196
|
+
@app.check(version="1")
|
|
185
197
|
def joint_smoothness(ep: hflow.Episode) -> hflow.CheckResult:
|
|
186
198
|
joints = ep.channel("/joint_states").to_numpy() # our line: extract
|
|
187
199
|
result = check_joint_smoothness(joints, rate_hz=100) # your line: unchanged
|
|
188
200
|
return hflow.CheckResult(measurements=result) # our line: record
|
|
189
201
|
|
|
190
202
|
|
|
191
|
-
@app.check(critical=True)
|
|
203
|
+
@app.check(version="1", critical=True)
|
|
192
204
|
def camera_blackout(ep: hflow.Episode) -> hflow.CheckResult:
|
|
193
|
-
|
|
205
|
+
camera_topic = next(topic for topic in ep.cameras if "wrist_cam" in topic)
|
|
206
|
+
evidence = camera_frame_stats(ep, cameras=[camera_topic])
|
|
207
|
+
black_frame_percent = evidence.measurements[f"{camera_topic}/black_frame_pct"]
|
|
208
|
+
assert isinstance(black_frame_percent, float)
|
|
194
209
|
return hflow.CheckResult(
|
|
195
|
-
measurements={"black_pct":
|
|
196
|
-
verdict=
|
|
210
|
+
measurements={"black_pct": black_frame_percent},
|
|
211
|
+
verdict=black_frame_percent < 50.0, # percent; your threshold
|
|
197
212
|
)
|
|
198
213
|
|
|
199
214
|
|
|
@@ -202,6 +217,10 @@ if __name__ == "__main__":
|
|
|
202
217
|
# Or call app.run() here to start the Compose runtime, then use `hflow ingest`.
|
|
203
218
|
```
|
|
204
219
|
|
|
220
|
+
Every check, enrichment, and derived channel declares a version. HFlow stores
|
|
221
|
+
that value exactly as written: keep it for behavior-preserving refactors, and
|
|
222
|
+
bump it when old and new results should no longer be treated as comparable.
|
|
223
|
+
|
|
205
224
|
Curation comes afterwards, via `hflow.curate(data_root / "catalog", sql, output="manifest.parquet")`
|
|
206
225
|
or `hflow curate "<sql>"` on the command line, either way reporting coverage
|
|
207
226
|
denominators alongside the manifest:
|
|
@@ -209,7 +228,7 @@ denominators alongside the manifest:
|
|
|
209
228
|
```sql
|
|
210
229
|
SELECT episode_id, uri FROM episodes
|
|
211
230
|
WHERE task = 'fold_napkin'
|
|
212
|
-
AND status
|
|
231
|
+
AND status = 'ok'
|
|
213
232
|
AND black_pct < 1.0 -- percent, user-owned threshold
|
|
214
233
|
AND pipeline_version = 'a41c9f27b3d8' -- pin one reprocessing generation
|
|
215
234
|
```
|
|
@@ -220,7 +239,6 @@ WHERE task = 'fold_napkin'
|
|
|
220
239
|
2. **Evidence, not verdicts.** Checks record measurements with coverage; pass/fail policy belongs to the consumer, at curation time. Quality tags route episodes; they never delete data.
|
|
221
240
|
3. **Standard formats at every boundary.** MCAP episodes, Parquet catalogs, Airflow DAGs. Our code exists only where the format forces bridging or a pitfall is genuinely non-obvious.
|
|
222
241
|
4. **Your code stays your code.** Existing transforms, checks, and enrichments plug in through small adapters instead of being rewritten.
|
|
223
|
-
5. **Transparent provenance.** The docs mark every design element as *Dyna says* (from the blog) or *HFlow chooses* (our engineering judgment, with the evidence behind it).
|
|
224
242
|
|
|
225
243
|
## Non-goals
|
|
226
244
|
|
|
@@ -243,28 +261,25 @@ WHERE task = 'fold_napkin'
|
|
|
243
261
|
- [Frequently asked questions](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/FAQ.md): formats, infrastructure, scale, project scope, and current release status
|
|
244
262
|
- [How HFlow fits the robotics data stack](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/INTEGRATIONS.md): MCAP, Airflow, Foxglove, Rerun, DuckDB, object storage, and training formats
|
|
245
263
|
- [Runnable examples](https://github.com/Hebbian-Robotics/hflow/blob/main/examples/README.md): exact commands, prerequisites, expected output, and links to the relevant guides
|
|
246
|
-
- [Architecture and
|
|
264
|
+
- [Architecture and implementation status](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md): the implemented, simplified, deferred, and out-of-scope matrix
|
|
247
265
|
- [Call OpenAI vision from a step](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/how-to/call-openai-vision.md): a focused guide linked to a complete executable pipeline
|
|
248
266
|
- [Contributing](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md): development setup, validation commands, test gates, and pull-request expectations
|
|
249
267
|
- [Security policy](https://github.com/Hebbian-Robotics/hflow/blob/main/SECURITY.md): supported versions and private vulnerability reporting
|
|
250
268
|
|
|
251
269
|
## References
|
|
252
270
|
|
|
253
|
-
Primary source:
|
|
254
|
-
|
|
255
|
-
- Dyna Robotics, [Training Dyna-2 at million-hour scale, repeatably](https://www.dyna.co/research/dyna-2-infrastructure) (Aug 2026)
|
|
256
|
-
|
|
257
|
-
Formats and tooling this project builds on:
|
|
258
271
|
|
|
272
|
+
- Dyna Robotics, [Training Dyna-2 at million-hour scale, repeatably](https://www.dyna.co/research/dyna-2-infrastructure)
|
|
259
273
|
- [MCAP specification](https://mcap.dev/spec) and [Python libraries](https://mcap.dev/docs/python/) (Foxglove)
|
|
260
274
|
- [foxglove.CompressedVideo schema](https://docs.foxglove.dev/docs/sdk/schemas/compressed-video): in-band H.264/H.265/VP9/AV1 video in MCAP
|
|
261
|
-
- [Apache Airflow
|
|
262
|
-
- [DuckDB](https://duckdb.org/)
|
|
263
|
-
- [Foxglove](https://foxglove.dev/) and [Rerun](https://rerun.io/)
|
|
264
|
-
- [FFmpeg](https://ffmpeg.org/)
|
|
265
|
-
|
|
266
|
-
Parts of the durability and measurement design draw on production experience from [Pareto](https://github.com/Hebbian-Robotics/pareto), Hebbian Robotics' robotics data curation platform.
|
|
275
|
+
- [Apache Airflow](https://airflow.apache.org/)
|
|
276
|
+
- [DuckDB](https://duckdb.org/)
|
|
277
|
+
- [Foxglove](https://foxglove.dev/) and [Rerun](https://rerun.io/)
|
|
278
|
+
- [FFmpeg](https://ffmpeg.org/)
|
|
279
|
+
- [Pareto](https://github.com/Hebbian-Robotics/pareto), Hebbian Robotics' robotics data curation platform.
|
|
267
280
|
|
|
268
281
|
## License
|
|
269
282
|
|
|
270
|
-
[Apache-2.0](https://github.com/Hebbian-Robotics/hflow/blob/main/LICENSE)
|
|
283
|
+
[Apache-2.0](https://github.com/Hebbian-Robotics/hflow/blob/main/LICENSE).
|
|
284
|
+
The license covers the code, not the names: see the
|
|
285
|
+
[trademark policy](https://github.com/Hebbian-Robotics/hflow/blob/main/TRADEMARKS.md).
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
<h1 align="center">HFlow</h1>
|
|
10
10
|
|
|
11
|
-
<p align="center"><strong>Open source SDK for
|
|
11
|
+
<p align="center"><strong>Open source SDK for scalable multimodal data pipelines in robotics and physical AI</strong></p>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
14
|
<a href="https://www.ycombinator.com/companies/hebbian-robotics">
|
|
@@ -22,25 +22,27 @@
|
|
|
22
22
|
</a>
|
|
23
23
|
</p>
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
Hebbian Robotics (YC S26) is building HFlow, an open source SDK for scalable
|
|
26
|
+
multimodal data pipelines in robotics and physical AI. It makes data tooling and
|
|
27
|
+
practices typically developed inside large robotics teams accessible to teams of
|
|
28
|
+
any size.
|
|
29
|
+
|
|
30
|
+
We believe processing data is a major bottleneck in robotics. A corpus can combine
|
|
31
|
+
video, state, actions, timestamps, and metadata from many recording systems. Teams
|
|
32
|
+
often feel the problem first in quality control: determining whether cameras froze,
|
|
33
|
+
streams drifted out of sync, required topics disappeared, or duplicate recordings
|
|
34
|
+
entered the corpus. As the corpus grows, fragmented scripts make it difficult to
|
|
35
|
+
know what ran, audit the results, or reproduce a dataset.
|
|
36
|
+
|
|
37
|
+
Teams can start with HFlow's built-in checks, write new transformations, checks,
|
|
38
|
+
labels, and enrichments, or connect processing code they already use. HFlow handles
|
|
39
|
+
the orchestration, storage, versioning, and curation around those steps.
|
|
28
40
|
|
|
29
41
|
HFlow stamps each processed episode with its provenance, renders the pipeline
|
|
30
42
|
as a graph, and records metadata and quality evidence in a queryable catalog.
|
|
31
43
|
You can trace how outputs were produced, monitor every stage, and
|
|
32
44
|
investigate a corpus without loading the underlying recordings.
|
|
33
45
|
|
|
34
|
-
The design is an open source implementation of Dyna Robotics'
|
|
35
|
-
["Training Dyna-2 at million-hour scale, repeatably"](https://www.dyna.co/research/dyna-2-infrastructure) article,
|
|
36
|
-
published August 2026. Dyna-2 was trained on more than one million hours of
|
|
37
|
-
egocentric video data, and the post describes the reusable infrastructure that
|
|
38
|
-
made processing and experimenting with that data repeatable. You can think of
|
|
39
|
-
HFlow as an independent, open-source implementation of those public ideas,
|
|
40
|
-
adapted for people who need the same foundation without Dyna's million-hour
|
|
41
|
-
production stack. It is not Dyna's private source code or an undisclosed
|
|
42
|
-
wire-compatible production system.
|
|
43
|
-
|
|
44
46
|
MCAP is HFlow's v1 input and output boundary because it efficiently stores
|
|
45
47
|
and serves synchronized video, state, action, and other time-series streams.
|
|
46
48
|
That format requirement does not define where the data comes from: human-worn
|
|
@@ -48,13 +50,13 @@ cameras, teleoperated robots, autonomous policies, and other collection systems
|
|
|
48
50
|
can all feed the pipeline once their data is represented as a supported MCAP
|
|
49
51
|
episode.
|
|
50
52
|
|
|
51
|
-
> **Status: pre-v1, with the core lifecycle working end to end.** HFlow is ready to try locally. See [what is implemented](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md#
|
|
53
|
+
> **Status: pre-v1, with the core lifecycle working end to end.** HFlow is ready to try locally. See [what is implemented](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md#implementation-status) and [open issues](https://github.com/Hebbian-Robotics/hflow/issues) for current details and remaining work.
|
|
52
54
|
|
|
53
|
-
**Help
|
|
55
|
+
**Help grow the open robotics community.** [Star the repository](https://github.com/Hebbian-Robotics/hflow), share it with your network, or [contribute](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md). Our goal is an open source community where anyone can participate in building the future of robotics. No robot hardware is required to contribute.
|
|
54
56
|
|
|
55
57
|
| | HFlow's boundary |
|
|
56
58
|
| --- | --- |
|
|
57
|
-
| **Input** | One multimodal episode per standard MCAP file |
|
|
59
|
+
| **Input** | One multimodal episode per standard MCAP file (`hflow doctor` says whether yours qualifies) |
|
|
58
60
|
| **Processing** | Your Python transforms, checks, labels, and enrichments |
|
|
59
61
|
| **Execution** | In-process for development; generated Airflow 3 DAGs for scheduled runs |
|
|
60
62
|
| **Durable output** | Canonical MCAP episodes, provenance, artifacts, and a Parquet catalog |
|
|
@@ -62,7 +64,7 @@ episode.
|
|
|
62
64
|
|
|
63
65
|
## What you get
|
|
64
66
|
|
|
65
|
-
Human and robot data move through
|
|
67
|
+
Human and robot data move through a four-stage lifecycle:
|
|
66
68
|
|
|
67
69
|
```
|
|
68
70
|
collection --> ingestion ---------------> curation ------> delivery
|
|
@@ -76,7 +78,7 @@ collection --> ingestion ---------------> curation ------> delivery
|
|
|
76
78
|
</p>
|
|
77
79
|
|
|
78
80
|
- **Your processing code stays yours.** Transformations, quality checks, labels, and enrichments are plain Python functions in your own environment. Existing code plugs in through small adapters instead of being rewritten for a proprietary framework.
|
|
79
|
-
- **Episodes are MCAP**, the container that ROS 2 records natively and [Foxglove](https://foxglove.dev/)/[Rerun](https://rerun.io/) open directly, written with
|
|
81
|
+
- **Episodes are MCAP**, the container that ROS 2 records natively and [Foxglove](https://foxglove.dev/)/[Rerun](https://rerun.io/) open directly, written with two tunings described in Dyna's article: in-band H.264 with GOP length matched to how the data is read, and **topic-group chunking** (camera streams and state streams never share a chunk, so a training sample costs one read per group instead of one per topic).
|
|
80
82
|
- **Processed episodes carry their provenance.** The file itself records the schema, pipeline, and tool versions that produced it, plus its source URI when available. Catalog records connect measurements and outcomes to step versions, making it easier to trace a bad result back to its origin.
|
|
81
83
|
- **The pipeline is visible as a graph.** HFlow renders Airflow DAGs so you can see how stages connect and monitor task status, logs, retries, and reruns.
|
|
82
84
|
- **Quality checks produce reusable evidence.** Accessors extract the inputs existing processing code expects (numpy arrays, MP4 paths, JPEG frames), and results land as queryable measurements rather than hardcoded verdicts. Different datasets can apply different thresholds without processing the media again.
|
|
@@ -94,6 +96,11 @@ same engine can be scaled as multiple isolated workspaces (for example, one
|
|
|
94
96
|
per team or customer) behind an external control plane. That is the intended
|
|
95
97
|
path to a future hosted version, but the hosted control plane is not
|
|
96
98
|
implemented in this repository and is not a pre-v1 release commitment.
|
|
99
|
+
[docs/HOSTING.md](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/HOSTING.md)
|
|
100
|
+
documents the data-plane contract that makes such a control plane an
|
|
101
|
+
addition rather than a rearchitecture: the workspace unit, the seams a
|
|
102
|
+
service drives (manifests, remote runtime addressing, credential injection),
|
|
103
|
+
the trust model, and the current limits.
|
|
97
104
|
|
|
98
105
|
## Community and hosted interest
|
|
99
106
|
|
|
@@ -122,7 +129,7 @@ To run the repository's bundled quickstart:
|
|
|
122
129
|
```bash
|
|
123
130
|
git clone https://github.com/Hebbian-Robotics/hflow.git
|
|
124
131
|
cd hflow
|
|
125
|
-
uv sync --locked
|
|
132
|
+
uv sync --locked
|
|
126
133
|
uv run python examples/quickstart.py
|
|
127
134
|
```
|
|
128
135
|
|
|
@@ -149,24 +156,28 @@ and other physical-AI recordings.
|
|
|
149
156
|
|
|
150
157
|
```python
|
|
151
158
|
import hflow
|
|
159
|
+
from hflow.checks import camera_frame_stats
|
|
152
160
|
from your_existing_qc import check_joint_smoothness # use your existing checks
|
|
153
161
|
|
|
154
|
-
app = hflow.App("kitchen-pipeline",
|
|
162
|
+
app = hflow.App("kitchen-pipeline") # data root: $HFLOW_DATA_ROOT, hflow.toml, else ./data
|
|
155
163
|
|
|
156
164
|
|
|
157
|
-
@app.check()
|
|
165
|
+
@app.check(version="1")
|
|
158
166
|
def joint_smoothness(ep: hflow.Episode) -> hflow.CheckResult:
|
|
159
167
|
joints = ep.channel("/joint_states").to_numpy() # our line: extract
|
|
160
168
|
result = check_joint_smoothness(joints, rate_hz=100) # your line: unchanged
|
|
161
169
|
return hflow.CheckResult(measurements=result) # our line: record
|
|
162
170
|
|
|
163
171
|
|
|
164
|
-
@app.check(critical=True)
|
|
172
|
+
@app.check(version="1", critical=True)
|
|
165
173
|
def camera_blackout(ep: hflow.Episode) -> hflow.CheckResult:
|
|
166
|
-
|
|
174
|
+
camera_topic = next(topic for topic in ep.cameras if "wrist_cam" in topic)
|
|
175
|
+
evidence = camera_frame_stats(ep, cameras=[camera_topic])
|
|
176
|
+
black_frame_percent = evidence.measurements[f"{camera_topic}/black_frame_pct"]
|
|
177
|
+
assert isinstance(black_frame_percent, float)
|
|
167
178
|
return hflow.CheckResult(
|
|
168
|
-
measurements={"black_pct":
|
|
169
|
-
verdict=
|
|
179
|
+
measurements={"black_pct": black_frame_percent},
|
|
180
|
+
verdict=black_frame_percent < 50.0, # percent; your threshold
|
|
170
181
|
)
|
|
171
182
|
|
|
172
183
|
|
|
@@ -175,6 +186,10 @@ if __name__ == "__main__":
|
|
|
175
186
|
# Or call app.run() here to start the Compose runtime, then use `hflow ingest`.
|
|
176
187
|
```
|
|
177
188
|
|
|
189
|
+
Every check, enrichment, and derived channel declares a version. HFlow stores
|
|
190
|
+
that value exactly as written: keep it for behavior-preserving refactors, and
|
|
191
|
+
bump it when old and new results should no longer be treated as comparable.
|
|
192
|
+
|
|
178
193
|
Curation comes afterwards, via `hflow.curate(data_root / "catalog", sql, output="manifest.parquet")`
|
|
179
194
|
or `hflow curate "<sql>"` on the command line, either way reporting coverage
|
|
180
195
|
denominators alongside the manifest:
|
|
@@ -182,7 +197,7 @@ denominators alongside the manifest:
|
|
|
182
197
|
```sql
|
|
183
198
|
SELECT episode_id, uri FROM episodes
|
|
184
199
|
WHERE task = 'fold_napkin'
|
|
185
|
-
AND status
|
|
200
|
+
AND status = 'ok'
|
|
186
201
|
AND black_pct < 1.0 -- percent, user-owned threshold
|
|
187
202
|
AND pipeline_version = 'a41c9f27b3d8' -- pin one reprocessing generation
|
|
188
203
|
```
|
|
@@ -193,7 +208,6 @@ WHERE task = 'fold_napkin'
|
|
|
193
208
|
2. **Evidence, not verdicts.** Checks record measurements with coverage; pass/fail policy belongs to the consumer, at curation time. Quality tags route episodes; they never delete data.
|
|
194
209
|
3. **Standard formats at every boundary.** MCAP episodes, Parquet catalogs, Airflow DAGs. Our code exists only where the format forces bridging or a pitfall is genuinely non-obvious.
|
|
195
210
|
4. **Your code stays your code.** Existing transforms, checks, and enrichments plug in through small adapters instead of being rewritten.
|
|
196
|
-
5. **Transparent provenance.** The docs mark every design element as *Dyna says* (from the blog) or *HFlow chooses* (our engineering judgment, with the evidence behind it).
|
|
197
211
|
|
|
198
212
|
## Non-goals
|
|
199
213
|
|
|
@@ -216,28 +230,25 @@ WHERE task = 'fold_napkin'
|
|
|
216
230
|
- [Frequently asked questions](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/FAQ.md): formats, infrastructure, scale, project scope, and current release status
|
|
217
231
|
- [How HFlow fits the robotics data stack](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/INTEGRATIONS.md): MCAP, Airflow, Foxglove, Rerun, DuckDB, object storage, and training formats
|
|
218
232
|
- [Runnable examples](https://github.com/Hebbian-Robotics/hflow/blob/main/examples/README.md): exact commands, prerequisites, expected output, and links to the relevant guides
|
|
219
|
-
- [Architecture and
|
|
233
|
+
- [Architecture and implementation status](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md): the implemented, simplified, deferred, and out-of-scope matrix
|
|
220
234
|
- [Call OpenAI vision from a step](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/how-to/call-openai-vision.md): a focused guide linked to a complete executable pipeline
|
|
221
235
|
- [Contributing](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md): development setup, validation commands, test gates, and pull-request expectations
|
|
222
236
|
- [Security policy](https://github.com/Hebbian-Robotics/hflow/blob/main/SECURITY.md): supported versions and private vulnerability reporting
|
|
223
237
|
|
|
224
238
|
## References
|
|
225
239
|
|
|
226
|
-
Primary source:
|
|
227
|
-
|
|
228
|
-
- Dyna Robotics, [Training Dyna-2 at million-hour scale, repeatably](https://www.dyna.co/research/dyna-2-infrastructure) (Aug 2026)
|
|
229
|
-
|
|
230
|
-
Formats and tooling this project builds on:
|
|
231
240
|
|
|
241
|
+
- Dyna Robotics, [Training Dyna-2 at million-hour scale, repeatably](https://www.dyna.co/research/dyna-2-infrastructure)
|
|
232
242
|
- [MCAP specification](https://mcap.dev/spec) and [Python libraries](https://mcap.dev/docs/python/) (Foxglove)
|
|
233
243
|
- [foxglove.CompressedVideo schema](https://docs.foxglove.dev/docs/sdk/schemas/compressed-video): in-band H.264/H.265/VP9/AV1 video in MCAP
|
|
234
|
-
- [Apache Airflow
|
|
235
|
-
- [DuckDB](https://duckdb.org/)
|
|
236
|
-
- [Foxglove](https://foxglove.dev/) and [Rerun](https://rerun.io/)
|
|
237
|
-
- [FFmpeg](https://ffmpeg.org/)
|
|
238
|
-
|
|
239
|
-
Parts of the durability and measurement design draw on production experience from [Pareto](https://github.com/Hebbian-Robotics/pareto), Hebbian Robotics' robotics data curation platform.
|
|
244
|
+
- [Apache Airflow](https://airflow.apache.org/)
|
|
245
|
+
- [DuckDB](https://duckdb.org/)
|
|
246
|
+
- [Foxglove](https://foxglove.dev/) and [Rerun](https://rerun.io/)
|
|
247
|
+
- [FFmpeg](https://ffmpeg.org/)
|
|
248
|
+
- [Pareto](https://github.com/Hebbian-Robotics/pareto), Hebbian Robotics' robotics data curation platform.
|
|
240
249
|
|
|
241
250
|
## License
|
|
242
251
|
|
|
243
|
-
[Apache-2.0](https://github.com/Hebbian-Robotics/hflow/blob/main/LICENSE)
|
|
252
|
+
[Apache-2.0](https://github.com/Hebbian-Robotics/hflow/blob/main/LICENSE).
|
|
253
|
+
The license covers the code, not the names: see the
|
|
254
|
+
[trademark policy](https://github.com/Hebbian-Robotics/hflow/blob/main/TRADEMARKS.md).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "hflow"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
description = "Open source SDK for building Physical AI data pipelines"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -37,6 +37,8 @@ name = "Brandon Ong"
|
|
|
37
37
|
[project.optional-dependencies]
|
|
38
38
|
arrow = ["pyarrow>=25.0.1"]
|
|
39
39
|
bucket = ["obstore>=0.10.0"]
|
|
40
|
+
mediapipe = ["mediapipe>=1.0.0"]
|
|
41
|
+
motion = ["opencv-python-headless>=4.10"]
|
|
40
42
|
openai = ["openai>=3.0.0"]
|
|
41
43
|
|
|
42
44
|
[project.urls]
|
|
@@ -49,7 +51,11 @@ hflow = "hflow.cli:main"
|
|
|
49
51
|
|
|
50
52
|
[dependency-groups]
|
|
51
53
|
dev = [
|
|
54
|
+
"hflow-server",
|
|
55
|
+
"httpx2>=2.10",
|
|
52
56
|
"obstore>=0.10.0",
|
|
57
|
+
"opencv-python-headless>=4.10",
|
|
58
|
+
"pyarrow>=25.0.1",
|
|
53
59
|
"pytest>=9.1.1",
|
|
54
60
|
"pyyaml>=6.0.3",
|
|
55
61
|
"ruff>=0.16.2",
|
|
@@ -63,8 +69,17 @@ build-backend = "uv_build"
|
|
|
63
69
|
[tool.uv]
|
|
64
70
|
exclude-newer = "5 days"
|
|
65
71
|
|
|
72
|
+
[tool.uv.workspace]
|
|
73
|
+
members = ["packages/*"]
|
|
74
|
+
|
|
75
|
+
[tool.uv.sources.hflow-server]
|
|
76
|
+
workspace = true
|
|
77
|
+
|
|
66
78
|
[tool.pytest.ini_options]
|
|
67
|
-
testpaths = [
|
|
79
|
+
testpaths = [
|
|
80
|
+
"tests",
|
|
81
|
+
"packages/hflow-server/tests",
|
|
82
|
+
]
|
|
68
83
|
|
|
69
84
|
[tool.ruff]
|
|
70
85
|
line-length = 100
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "hflow"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
description = "Open source SDK for building Physical AI data pipelines"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -36,6 +36,19 @@ arrow = ["pyarrow>=25.0.1"]
|
|
|
36
36
|
# object_store crate as a single dependency-free wheel; local-path roots
|
|
37
37
|
# never import it.
|
|
38
38
|
bucket = ["obstore>=0.10.0"]
|
|
39
|
+
# Hand detection with MediaPipe's Hand Landmarker (hflow.mediapipe_hands).
|
|
40
|
+
# A MODEL, not a signal statistic, so it is opt-in twice over: outside the core
|
|
41
|
+
# install, and outside the dev group as well (unlike motion and bucket, which
|
|
42
|
+
# are mirrored into dev so the suite exercises them). It adds ~430 MB and its
|
|
43
|
+
# own OpenCV; a dev environment opts in with `--extra mediapipe`, exactly as
|
|
44
|
+
# the openai example does.
|
|
45
|
+
mediapipe = ["mediapipe>=1.0.0"]
|
|
46
|
+
# Camera-shake measurement: pyramidal Lucas-Kanade optical flow and a RANSAC
|
|
47
|
+
# similarity fit. No numpy-only equivalent preserves the instrument, and
|
|
48
|
+
# reimplementing them would make it a different, unvalidated one -- so the
|
|
49
|
+
# dependency is real, and confined to the one check that needs it. Headless
|
|
50
|
+
# because a data pipeline runs where there is no display.
|
|
51
|
+
motion = ["opencv-python-headless>=4.10"]
|
|
39
52
|
openai = ["openai>=3.0.0"]
|
|
40
53
|
|
|
41
54
|
[project.urls]
|
|
@@ -48,7 +61,15 @@ hflow = "hflow.cli:main"
|
|
|
48
61
|
|
|
49
62
|
[dependency-groups]
|
|
50
63
|
dev = [
|
|
64
|
+
"hflow-server", # the workspace API package, present in dev so the suite tests it
|
|
65
|
+
# Starlette's TestClient transport for the hflow-server suite. httpx2, not
|
|
66
|
+
# httpx: starlette 1.6 deprecates the httpx transport in its favour.
|
|
67
|
+
"httpx2>=2.10",
|
|
51
68
|
"obstore>=0.10.0", # the bucket extra, present in dev so the suite tests it
|
|
69
|
+
# the motion extra, present in dev so the suite tests it rather than
|
|
70
|
+
# skipping the one check that cannot be verified any other way
|
|
71
|
+
"opencv-python-headless>=4.10",
|
|
72
|
+
"pyarrow>=25.0.1", # the arrow extra, present in dev so the suite tests it
|
|
52
73
|
"pytest>=9.1.1",
|
|
53
74
|
"pyyaml>=6.0.3",
|
|
54
75
|
"ruff>=0.16.2",
|
|
@@ -65,8 +86,14 @@ build-backend = "uv_build"
|
|
|
65
86
|
# trusted first-party packages.
|
|
66
87
|
exclude-newer = "5 days"
|
|
67
88
|
|
|
89
|
+
[tool.uv.workspace]
|
|
90
|
+
members = ["packages/*"]
|
|
91
|
+
|
|
92
|
+
[tool.uv.sources]
|
|
93
|
+
hflow-server = { workspace = true }
|
|
94
|
+
|
|
68
95
|
[tool.pytest.ini_options]
|
|
69
|
-
testpaths = ["tests"]
|
|
96
|
+
testpaths = ["tests", "packages/hflow-server/tests"]
|
|
70
97
|
|
|
71
98
|
[tool.ruff]
|
|
72
99
|
line-length = 100
|