科学・技術
ロボティクスデータインフラストラクチャのためのYouTubeシステムデザイン
YouTube System Design for Robotics Data Infrastructure (hebbianrobotics.com)
要約
ロボティクスデータプラットフォームを構築する際、当初はYouTubeのような汎用的なサービスを想定していませんでした。しかし、大規模メディアファイルのアップロード、バックグラウンド処理、メタデータインデックス作成、ストリーミングといった要件はYouTubeのシステムデザインと類似していました。この記事では、ロボットデータセットの「エピソード」という複雑なデータ単位を扱いながら、アップロード、処理、保存、インデックス作成、再生というパイプラインを、YouTubeと同様のアーキテクチャパターンを用いて構築した経験を解説しています。
全文翻訳
ロボティクス向けデータプラットフォームを構築し始めた当初、私たちはYouTubeのことを考えていませんでした。ロボティクスチームは、LeRobotデータセットをアップロードし、デモンストレーションを検索し、同期されたカメラフィードとロボットの状態を検査し、トレーニング用にキュレーションされたエピソードをエクスポートできるようにしたいと考えていました。それはロボティクスにおけるかなり専門的な問題のように思えました。そこで私たちはParetoを構築しました。
インフラストラクチャ作業に進むにつれて、要件は馴染みのあるものに感じられるようになりました。大規模メディアファイルを確実にアップロードし、オリジナルを保持し、バックグラウンドで処理し、サムネイルとプレビュービデオを生成し、メタデータをインデックス化し、データセット全体をダウンロードせずにブラウザにストリーミングする必要がありました。「YouTubeを設計する」は古典的なシステムデザインの演習です。YouTubeは圧倒的であり、私たちほとんど誰もグローバルなコンシューマービデオプラットフォームをその規模で構築する必要はないため、少し無意味に感じられるかもしれません。数千人のユーザーが単一のビデオをプラットフォームにアップロードするという状況を、単一のロボットデータセットが数千のビデオをアップロードするという状況にリフレームすると、類似点がより明確になります。
ByteByteGoはこの演習をアップロードと再生にスコープします。オリジナルファイルはブロブストレージに格納され、バックグラウンドワーカーがトランスコードし、完了フローがメタデータを更新し、CDNが完成版を配信します。それが上記の簡略化された形状です。
ロボットデータの1エピソード
古典的なビデオプラットフォームは、1つの支配的なオブジェクトから始まります。ビデオ、おそらくオーディオと字幕付きです。ロボット学習データセットは、より複雑なデータ単位を持っています。ロボットデータの1エピソードは、マルチモーダルレコードです。複数のカメラフィード(手首、トップ、胸など)と、ジョイント位置、アクション、力覚データ、タイムスタンプ、タスク説明、その他のセンサーデータストリームを含むことができます。カメラはデータセットの大部分を占めるかもしれませんが、それらは単独では有用ではありません。データは、その瞬間にロボットが何を検知し、何を行っていたかとの関連性が保たれている場合にのみ意味を持ちます。
Paretoはエピソード全体を検索するため、「オレンジ色のブロック」を検索する人は、周囲の軌跡をスクラブし、カメラを比較し、デモンストレーションがトレーニングセットに属するかどうかを決定できます。LeRobot v3はこれを具体化します。エピソードはParquetデータファイルとMP4シャードを共有できるため、エピソードを読むということは、構造化された行範囲と、各カメラのビデオ内のタイムスタンプ範囲の両方を解決することを意味します。データパスを書き出したとき、それは馴染みのあるものに見えました:アップロード -> 処理 -> 保存 -> インデックス -> 再生。
Paretoはオープンソースなので、システムを検査して自分で実行できます。
1. 信頼性の高いアップロード
マルチメディアに関しては、面倒な大規模アップロードの技術に入ります。接続は失敗し、プロセスは再起動し、最後のファイルが中断されたためにデータセット全体を再試行するのはコストがかかります。ビデオプラットフォームは、これを再開可能なアップロードと、処理準備完了への明示的な移行で対処します。Paretoでは、ソースファイルを変換およびインデックス化するものとは別に、受け取り続けます。ソースファイルはバージョン管理されたストレージパスの下に保存され、完了したバッチはチェックポイントされ、最終的なマニフェストが最後に書き込まれます。下流のジョブは、ディレクトリが完了したかどうかを推測するのではなく、そのマニフェストを完了マーカーとして使用します。これにより、生成されたすべての出力を、それを生成した正確なソースファイルとバッチにトレースすることもできます。元のデータセットを保持することは、将来の処理が変更されても、ユーザーにデータを再アップロードするように依頼する必要がないことも意味します。
2. 処理はパイプラインになる
ビデオをストリーミングするあらゆるサイトで、アップロードは複数のバージョンに処理される必要があります。異なる解像度とコーデック、サムネイル、プレビュー、キャプション、その他のアセットです。オリジナルは、より大きなバックグラウンドパイプラインへの1つの入力です。ロボットデータの場合、サンプリングされたフレーム、サムネイル、プレビュービデオ、ダウンサンプリングされた状態とアクションシリーズ、ベクトル埋め込み、検索インデックス、およびRerun録画を生成します。それぞれが異なる目的を果たします。検索、ブラウジング、同期再生、分析、またはエクスポートです。ブラウザは、元のアップロードを配信せずにYouTubeが再生を開始できるのと同様に、完全なデータセットを開かずに検索結果を表示できます。
3. 長時間ジョブの実行
Paretoは、Temporalを使用して、パイプライン内のさまざまなジョブを耐久性のあるワークフローとして実行します。ホストされているサービスがありますが、オープンソースでセルフホストも可能です。ワーカーは、機能と作業の形状によって分離されています。GPU埋め込みワーカー間で独立したエピソード範囲をシャードし、その後、シャード出力をマージしてグローバルワークを一度実行する最終化ステップでファンインします。事前ロードされたウォームモデルを必要としない他のジョブは、弾力的なGPUまたはCPUプール全体で実行できる独立したチャンクに分割されます。これにより、あるジョブクラスのバーストが、別の種類の作業が必要とする容量を消費するのを防ぎます。
生成されたすべての出力がデータセットが有用になる前に準備ができている必要はありません。軽量で回復可能な計算の多くを遅延オンデマンドパスに移行し、クリティカルパスをデータ検索可能および表示可能にすることに集中させました。これにより、初回使用までの時間が短縮され、まだ誰も求めていない成果物へのサイクル消費が回避されます。テキストクエリも同様のポイントを別の形で示しています。画像埋め込みは高スループットのバッチジョブでありGPUに属しますが、ライブテキスト検索には最近傍検索の前に1つの小さな埋め込みが必要です。RustとONNXを使用してテキスト埋め込み用のCPU SigLIP 2サーバーを開発しました。これにより、GPUは取り込みに集中でき、オンラインパスのプロビジョニングが容易になります。
4. ファイル、メタデータ、インデックスの分離
YouTubeは、ビデオメタデータ、検索インデックス、メディアを1つのデータベースに配置しません。Paretoも同様の分割に従います。ソースデータセットと派生データは、URIアドレス指定可能なオブジェクトストレージに格納されます。Postgresはメタデータを保持します。LanceDBは検索用のマルチモーダルベクトルを格納します。サーバー自体はステートレスです。テキストクエリは埋め込まれ、ベクトルに対して検索され、エピソードとして返されます。
5. ビューアが必要とするものだけをストリーミングする
有用なビデオプラットフォームでは、最初の数秒を視聴する前にファイル全体をダウンロードする必要はありません。シークをサポートし、プレーヤーが必要とするバイト範囲を提供します。これは、ロボットデータセットに複数のカメラフィードと構造化信号が含まれている場合、さらに重要になります。ParetoのブラウザUIは、プレビューを使用し、あらゆる操作のために元のデータセットを開くのではなく、プレーヤーが必要とするバイトのみを要求します。複数のカメラは1つの同期されたトランスポートを共有し、ユーザーは対応する状態とアクションを表示しながらスクラブできます。プレビュー品質は自動的に選択されるか、カメラグリッド全体で固定できます。
インターフェースは馴染みのあるように見えます。タイムライン、プレビュー、シークです。しかし、その仕事は異なります。これは受動的な視聴ではありません。ユーザーは、エピソードが取得された理由を理解し、証拠を検査し、動作を比較し、注釈を付け、モデルに影響を与えるべきかどうかを決定する必要があります。
規模で開始せずに規模のために設計する
キャリアの初期、私はJane Streetでソフトウェアエンジニアとしてスタートしました。毎秒数百万メッセージの処理をサポートするインフラストラクチャを構築する中で、規模についての考えと規模での運用を切り離すことを学びました。初期段階では、有用な決定は構造的なものです。耐久性のある状態がどこに存在するか、作業が再試行可能かどうか、容量の追加がシステムの再設計を必要とするかどうかです。いわゆる「家畜、ペットではない」という考えを聞いたことがあるかもしれません。手動で管理し、スケールアップし続ける少数の大きなノードを持つのではなく、いつでもスケールアウトするために迅速に起動およびシャットダウンできる、小さくて同一のノードを持つ方が良い場合が多いです。耐久性のある状態は処理マシン外に存在し、APIレプリカとワーカーは交換可能です。メディアワーカーは消滅し、そのジョブは再配信され、回復プロジェクトにならずに交換できます。これにより、水平スケーリングが可能になります。今日1つのワーカーを実行し、後でもっと実行できますが、実行モデルは変更されません。
残念ながら、GPU容量は常にこれを容易にするわけではありません。プロバイダーが十分なクォータを提供できない場合、GPU搭載の家畜の群れを増やすのはより困難です。しかし、「スケーラブル」は不必要な複雑さの言い訳になる可能性があります。Paretoの直接CLIは、インデックス作成、検索、およびエクスポートを実行できます。