Buckets:
| <meta charset="utf-8" /><meta name="hf:doc:metadata" content="{"title":"Debug Your Processor Pipeline","local":"debug-your-processor-pipeline","sections":[{"title":"Understanding Hooks","local":"understanding-hooks","sections":[{"title":"What is a Hook?","local":"what-is-a-hook","sections":[],"depth":3},{"title":"Before vs After Hooks","local":"before-vs-after-hooks","sections":[],"depth":3},{"title":"Implementing a NaN Detection Hook","local":"implementing-a-nan-detection-hook","sections":[],"depth":3},{"title":"How Hooks Work Internally","local":"how-hooks-work-internally","sections":[],"depth":3},{"title":"Execution Flow","local":"execution-flow","sections":[],"depth":3},{"title":"Multiple Hooks","local":"multiple-hooks","sections":[],"depth":3}],"depth":2},{"title":"Step-Through Debugging","local":"step-through-debugging","sections":[{"title":"How Step-Through Works","local":"how-step-through-works","sections":[],"depth":3},{"title":"Interactive Debugging with Breakpoints","local":"interactive-debugging-with-breakpoints","sections":[],"depth":3}],"depth":2},{"title":"Validating Feature Contracts","local":"validating-feature-contracts","sections":[{"title":"Understanding Feature Contracts","local":"understanding-feature-contracts","sections":[],"depth":3},{"title":"Verifying Expected Features","local":"verifying-expected-features","sections":[],"depth":3}],"depth":2},{"title":"Summary","local":"summary","sections":[],"depth":2}],"depth":1}"> | |
| <link href="/docs/lerobot/pr_3313/en/_app/immutable/assets/0.e3b0c442.css" rel="modulepreload"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/entry/start.d3f1c0f3.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/scheduler.eb244325.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/singletons.1f33814c.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/index.3c23fb4b.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/paths.17f05d75.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/entry/app.04bb7687.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/preload-helper.b00aacbc.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/index.3fe63ad3.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/nodes/0.07fbe93e.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/each.e59479a4.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/nodes/12.e407fa96.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/CopyLLMTxtMenu.d0c64540.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/MermaidChart.svelte_svelte_type_style_lang.6453902c.js"> | |
| <link rel="modulepreload" href="/docs/lerobot/pr_3313/en/_app/immutable/chunks/CodeBlock.48dd2cc2.js"><!-- HEAD_svelte-u9bgzb_START --><meta name="hf:doc:metadata" content="{"title":"Debug Your Processor Pipeline","local":"debug-your-processor-pipeline","sections":[{"title":"Understanding Hooks","local":"understanding-hooks","sections":[{"title":"What is a Hook?","local":"what-is-a-hook","sections":[],"depth":3},{"title":"Before vs After Hooks","local":"before-vs-after-hooks","sections":[],"depth":3},{"title":"Implementing a NaN Detection Hook","local":"implementing-a-nan-detection-hook","sections":[],"depth":3},{"title":"How Hooks Work Internally","local":"how-hooks-work-internally","sections":[],"depth":3},{"title":"Execution Flow","local":"execution-flow","sections":[],"depth":3},{"title":"Multiple Hooks","local":"multiple-hooks","sections":[],"depth":3}],"depth":2},{"title":"Step-Through Debugging","local":"step-through-debugging","sections":[{"title":"How Step-Through Works","local":"how-step-through-works","sections":[],"depth":3},{"title":"Interactive Debugging with Breakpoints","local":"interactive-debugging-with-breakpoints","sections":[],"depth":3}],"depth":2},{"title":"Validating Feature Contracts","local":"validating-feature-contracts","sections":[{"title":"Understanding Feature Contracts","local":"understanding-feature-contracts","sections":[],"depth":3},{"title":"Verifying Expected Features","local":"verifying-expected-features","sections":[],"depth":3}],"depth":2},{"title":"Summary","local":"summary","sections":[],"depth":2}],"depth":1}"><!-- HEAD_svelte-u9bgzb_END --> <p></p> <div class="items-center shrink-0 min-w-[100px] max-sm:min-w-[50px] justify-end ml-auto flex" style="float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"><div class="inline-flex rounded-md max-sm:rounded-sm"><button class="inline-flex items-center gap-1 h-7 max-sm:h-7 px-2 max-sm:px-1.5 text-sm font-medium text-gray-800 border border-r-0 rounded-l-md max-sm:rounded-l-sm border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-live="polite"><span class="inline-flex items-center justify-center rounded-md p-0.5 max-sm:p-0 hover:text-gray-800 dark:hover:text-gray-200"><svg class="sm:size-3.5 size-3" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg></span> <span>Copy page</span></button> <button class="inline-flex items-center justify-center w-6 max-sm:w-5 h-7 max-sm:h-7 disabled:pointer-events-none text-sm text-gray-500 hover:text-gray-700 dark:hover:text-white rounded-r-md max-sm:rounded-r-sm border border-l transition border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-haspopup="menu" aria-expanded="false" aria-label="Open copy menu"><svg class="transition-transform text-gray-400 overflow-visible sm:size-3.5 size-3 rotate-0" width="1em" height="1em" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L6 6L11 1" stroke="currentColor"></path></svg></button></div> </div> <h1 class="relative group"><a id="debug-your-processor-pipeline" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#debug-your-processor-pipeline"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Debug Your Processor Pipeline</span></h1> <p data-svelte-h="svelte-1q65nk3">Processor pipelines can be complex, especially when chaining multiple transformation steps. | |
| Unlike simple function calls, pipelines lack natural observability, you can’t easily see what happens | |
| between each step or where things go wrong. | |
| This guide provides debugging tools and techniques specifically designed to address these challenges | |
| and help you understand data flow through your pipelines.</p> <p data-svelte-h="svelte-u8e3wb">We’ll explore three complementary debugging approaches: <strong>hooks</strong> for runtime monitoring, <strong>step-through debugging</strong> for detailed inspection, and <strong>feature validation</strong> for catching structural mismatches. Each serves a different purpose and together they provide complete visibility into your pipeline’s behavior.</p> <h2 class="relative group"><a id="understanding-hooks" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#understanding-hooks"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Understanding Hooks</span></h2> <p data-svelte-h="svelte-1d4nxx9">Hooks are functions that get called at specific points during pipeline execution. | |
| They provide a way to inspect, monitor, or modify data without changing your pipeline code. | |
| Think of them as “event listeners” for your pipeline.</p> <h3 class="relative group"><a id="what-is-a-hook" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#what-is-a-hook"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>What is a Hook?</span></h3> <p data-svelte-h="svelte-1tl8qwt">A hook is a callback function that gets automatically invoked at specific moments during pipeline execution. | |
| The concept comes from event-driven programming, imagine you could “hook into” the pipeline’s execution flow to observe or react to what’s happening.</p> <p data-svelte-h="svelte-g73lwr">Think of hooks like inserting checkpoints into your pipeline. Every time the pipeline reaches one of these checkpoints, it pauses briefly to call your hook function, giving you a chance to inspect the current state, log information, and validate data.</p> <p data-svelte-h="svelte-74gmv5">A hook is simply a function that accepts two parameters:</p> <ul data-svelte-h="svelte-6outgx"><li><code>step_idx: int</code> - The index of the current processing step (0, 1, 2, etc.)</li> <li><code>transition: EnvTransition</code> - The data transition at that point in the pipeline</li></ul> <p data-svelte-h="svelte-mbtl9h">The beauty of hooks is their non-invasive nature: you can add monitoring, validation, or debugging logic without changing a single line of your pipeline code. The pipeline remains clean and focused on its core logic, while hooks handle the cross-cutting concerns like logging, monitoring, and debugging.</p> <h3 class="relative group"><a id="before-vs-after-hooks" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#before-vs-after-hooks"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Before vs After Hooks</span></h3> <p data-svelte-h="svelte-1fbouur">The pipeline supports two types of hooks:</p> <ul data-svelte-h="svelte-xsrxoj"><li><strong>Before hooks</strong> (<code>register_before_step_hook</code>) - Called before each step executes</li> <li><strong>After hooks</strong> (<code>register_after_step_hook</code>) - Called after each step completes</li></ul> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">def</span> <span class="hljs-title function_">before_hook</span>(<span class="hljs-params">step_idx: <span class="hljs-built_in">int</span>, transition: EnvTransition</span>): | |
| <span class="hljs-string">"""Called before step processes the transition."""</span> | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"About to execute step <span class="hljs-subst">{step_idx}</span>"</span>) | |
| <span class="hljs-comment"># Useful for: logging, validation, setup</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">after_hook</span>(<span class="hljs-params">step_idx: <span class="hljs-built_in">int</span>, transition: EnvTransition</span>): | |
| <span class="hljs-string">"""Called after step has processed the transition."""</span> | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Completed step <span class="hljs-subst">{step_idx}</span>"</span>) | |
| <span class="hljs-comment"># Useful for: monitoring results, cleanup, debugging</span> | |
| processor.register_before_step_hook(before_hook) | |
| processor.register_after_step_hook(after_hook)<!-- HTML_TAG_END --></pre></div> <h3 class="relative group"><a id="implementing-a-nan-detection-hook" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#implementing-a-nan-detection-hook"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Implementing a NaN Detection Hook</span></h3> <p data-svelte-h="svelte-1ks2c33">Here’s a practical example of a hook that detects NaN values:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">def</span> <span class="hljs-title function_">check_nans</span>(<span class="hljs-params">step_idx: <span class="hljs-built_in">int</span>, transition: EnvTransition</span>): | |
| <span class="hljs-string">"""Check for NaN values in observations."""</span> | |
| obs = transition.get(TransitionKey.OBSERVATION) | |
| <span class="hljs-keyword">if</span> obs: | |
| <span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> obs.items(): | |
| <span class="hljs-keyword">if</span> <span class="hljs-built_in">isinstance</span>(value, torch.Tensor) <span class="hljs-keyword">and</span> torch.isnan(value).<span class="hljs-built_in">any</span>(): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"NaN detected in <span class="hljs-subst">{key}</span> at step <span class="hljs-subst">{step_idx}</span>"</span>) | |
| <span class="hljs-comment"># Register the hook to run after each step</span> | |
| processor.register_after_step_hook(check_nans) | |
| <span class="hljs-comment"># Process your data - the hook will be called automatically</span> | |
| output = processor(input_data) | |
| <span class="hljs-comment"># Remove the hook when done debugging</span> | |
| processor.unregister_after_step_hook(check_nans)<!-- HTML_TAG_END --></pre></div> <h3 class="relative group"><a id="how-hooks-work-internally" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#how-hooks-work-internally"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>How Hooks Work Internally</span></h3> <p data-svelte-h="svelte-7f17pf">Understanding the internal mechanism helps you use hooks more effectively. The pipeline maintains two separate lists: one for before-step hooks and another for after-step hooks. When you register a hook, it’s simply appended to the appropriate list.</p> <p data-svelte-h="svelte-1nvp99m">During execution, the pipeline follows a strict sequence: for each processing step, it first calls all before-hooks in registration order, then executes the actual step transformation, and finally calls all after-hooks in registration order. This creates a predictable, sandwich-like structure around each step.</p> <p data-svelte-h="svelte-bpn8qt">The key insight is that hooks don’t change the core pipeline logic—they’re purely additive. The pipeline’s <code>_forward</code> method orchestrates this dance between hooks and processing steps, ensuring that your debugging or monitoring code runs at exactly the right moments without interfering with the main data flow.</p> <p data-svelte-h="svelte-1h7hqy">Here’s a simplified view of how the pipeline executes hooks:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">class</span> <span class="hljs-title class_">DataProcessorPipeline</span>: | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>): | |
| self.steps = [...] | |
| self.before_step_hooks = [] <span class="hljs-comment"># List of before hooks</span> | |
| self.after_step_hooks = [] <span class="hljs-comment"># List of after hooks</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">_forward</span>(<span class="hljs-params">self, transition</span>): | |
| <span class="hljs-string">"""Internal method that processes the transition through all steps."""</span> | |
| <span class="hljs-keyword">for</span> step_idx, processor_step <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(self.steps): | |
| <span class="hljs-comment"># 1. Call all BEFORE hooks</span> | |
| <span class="hljs-keyword">for</span> hook <span class="hljs-keyword">in</span> self.before_step_hooks: | |
| hook(step_idx, transition) | |
| <span class="hljs-comment"># 2. Execute the actual processing step</span> | |
| transition = processor_step(transition) | |
| <span class="hljs-comment"># 3. Call all AFTER hooks</span> | |
| <span class="hljs-keyword">for</span> hook <span class="hljs-keyword">in</span> self.after_step_hooks: | |
| hook(step_idx, transition) | |
| <span class="hljs-keyword">return</span> transition | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">register_before_step_hook</span>(<span class="hljs-params">self, hook_fn</span>): | |
| self.before_step_hooks.append(hook_fn) | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">register_after_step_hook</span>(<span class="hljs-params">self, hook_fn</span>): | |
| self.after_step_hooks.append(hook_fn)<!-- HTML_TAG_END --></pre></div> <h3 class="relative group"><a id="execution-flow" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#execution-flow"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Execution Flow</span></h3> <p data-svelte-h="svelte-ufigjs">The execution flow looks like this:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-built_in">Input</span> → <span class="hljs-built_in">Before</span> <span class="hljs-variable">Hook</span> → <span class="hljs-variable">Step</span> <span class="hljs-number">0</span> → <span class="hljs-built_in">After</span> <span class="hljs-variable">Hook</span> → <span class="hljs-built_in">Before</span> <span class="hljs-variable">Hook</span> → <span class="hljs-variable">Step</span> <span class="hljs-number">1</span> → <span class="hljs-built_in">After</span> <span class="hljs-variable">Hook</span> → <span class="hljs-operator">...</span> → <span class="hljs-variable">Output</span><!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-c4zafn">For example, with 3 steps and both hook types:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">def</span> <span class="hljs-title function_">timing_before</span>(<span class="hljs-params">step_idx, transition</span>): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"⏱️ Starting step <span class="hljs-subst">{step_idx}</span>"</span>) | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">validation_after</span>(<span class="hljs-params">step_idx, transition</span>): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"✅ Completed step <span class="hljs-subst">{step_idx}</span>"</span>) | |
| processor.register_before_step_hook(timing_before) | |
| processor.register_after_step_hook(validation_after) | |
| <span class="hljs-comment"># This will output:</span> | |
| <span class="hljs-comment"># ⏱️ Starting step 0</span> | |
| <span class="hljs-comment"># ✅ Completed step 0</span> | |
| <span class="hljs-comment"># ⏱️ Starting step 1</span> | |
| <span class="hljs-comment"># ✅ Completed step 1</span> | |
| <span class="hljs-comment"># ⏱️ Starting step 2</span> | |
| <span class="hljs-comment"># ✅ Completed step 2</span><!-- HTML_TAG_END --></pre></div> <h3 class="relative group"><a id="multiple-hooks" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#multiple-hooks"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Multiple Hooks</span></h3> <p data-svelte-h="svelte-oullvg">You can register multiple hooks of the same type - they execute in the order registered:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">def</span> <span class="hljs-title function_">log_shapes</span>(<span class="hljs-params">step_idx: <span class="hljs-built_in">int</span>, transition: EnvTransition</span>): | |
| obs = transition.get(TransitionKey.OBSERVATION) | |
| <span class="hljs-keyword">if</span> obs: | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Step <span class="hljs-subst">{step_idx}</span> observation shapes:"</span>) | |
| <span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> obs.items(): | |
| <span class="hljs-keyword">if</span> <span class="hljs-built_in">isinstance</span>(value, torch.Tensor): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f" <span class="hljs-subst">{key}</span>: <span class="hljs-subst">{value.shape}</span>"</span>) | |
| processor.register_after_step_hook(check_nans) <span class="hljs-comment"># Executes first</span> | |
| processor.register_after_step_hook(log_shapes) <span class="hljs-comment"># Executes second</span> | |
| <span class="hljs-comment"># Both hooks will be called after each step in registration order</span> | |
| output = processor(input_data)<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1kb9xte">While hooks are excellent for monitoring specific issues (like NaN detection) or gathering metrics during normal pipeline execution, sometimes you need to dive deeper. When you want to understand exactly what happens at each step or debug complex transformation logic, step-through debugging provides the detailed inspection you need.</p> <h2 class="relative group"><a id="step-through-debugging" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-through-debugging"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step-Through Debugging</span></h2> <p data-svelte-h="svelte-1ovynfp">Step-through debugging is like having a slow-motion replay for your pipeline. Instead of watching your data get transformed in one quick blur from input to output, you can pause and examine what happens after each individual step.</p> <p data-svelte-h="svelte-oaf05p">This approach is particularly valuable when you’re trying to understand a complex pipeline, debug unexpected behavior, or verify that each transformation is working as expected. Unlike hooks, which are great for automated monitoring, step-through debugging gives you manual, interactive control over the inspection process.</p> <p data-svelte-h="svelte-v29wbq">The <code>step_through()</code> method is a generator that yields the transition state after each processing step, allowing you to inspect intermediate results. Think of it as creating a series of snapshots of your data as it flows through the pipeline—each snapshot shows you exactly what your data looks like after one more transformation has been applied.</p> <h3 class="relative group"><a id="how-step-through-works" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#how-step-through-works"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>How Step-Through Works</span></h3> <p data-svelte-h="svelte-1r8d1yr">The <code>step_through()</code> method fundamentally changes how the pipeline executes. Instead of running all steps in sequence and only returning the final result, it transforms the pipeline into an iterator that yields intermediate results.</p> <p data-svelte-h="svelte-10upnqa">Here’s what happens internally: the method starts by converting your input data into the pipeline’s internal transition format, then yields this initial state. Next, it applies the first processing step and yields the result. Then it applies the second step to that result and yields again, and so on. Each <code>yield</code> gives you a complete snapshot of the transition at that point.</p> <p data-svelte-h="svelte-14bs306">This generator pattern is powerful because it’s lazy—the pipeline only computes the next step when you ask for it. This means you can stop at any point, inspect the current state thoroughly, and decide whether to continue. You’re not forced to run the entire pipeline just to debug one problematic step.</p> <p data-svelte-h="svelte-1lcc4zd">Instead of running the entire pipeline and only seeing the final result, <code>step_through()</code> pauses after each step and gives you the intermediate transition:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-comment"># This creates a generator that yields intermediate states</span> | |
| <span class="hljs-keyword">for</span> i, intermediate_result <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(processor.step_through(input_data)): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"=== After step <span class="hljs-subst">{i}</span> ==="</span>) | |
| <span class="hljs-comment"># Inspect the observation at this stage</span> | |
| obs = intermediate_result.get(TransitionKey.OBSERVATION) | |
| <span class="hljs-keyword">if</span> obs: | |
| <span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> obs.items(): | |
| <span class="hljs-keyword">if</span> <span class="hljs-built_in">isinstance</span>(value, torch.Tensor): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{key}</span>: shape=<span class="hljs-subst">{value.shape}</span>, dtype=<span class="hljs-subst">{value.dtype}</span>"</span>)<!-- HTML_TAG_END --></pre></div> <h3 class="relative group"><a id="interactive-debugging-with-breakpoints" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#interactive-debugging-with-breakpoints"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Interactive Debugging with Breakpoints</span></h3> <p data-svelte-h="svelte-1j32u21">You can add breakpoints in the step-through loop to interactively debug:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-comment"># Step through the pipeline with debugging</span> | |
| <span class="hljs-keyword">for</span> i, intermediate <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(processor.step_through(data)): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Step <span class="hljs-subst">{i}</span>: <span class="hljs-subst">{processor.steps[i].__class__.__name__}</span>"</span>) | |
| <span class="hljs-comment"># Set a breakpoint to inspect the current state</span> | |
| <span class="hljs-built_in">breakpoint</span>() <span class="hljs-comment"># Debugger will pause here</span> | |
| <span class="hljs-comment"># You can now inspect 'intermediate' in the debugger:</span> | |
| <span class="hljs-comment"># - Check tensor shapes and values</span> | |
| <span class="hljs-comment"># - Verify expected transformations</span> | |
| <span class="hljs-comment"># - Look for unexpected changes</span><!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-c4rq6s">During the debugger session, you can:</p> <ul data-svelte-h="svelte-5yml2w"><li>Examine <code>intermediate[TransitionKey.OBSERVATION]</code> to see observation data</li> <li>Check <code>intermediate[TransitionKey.ACTION]</code> for action transformations</li> <li>Inspect any part of the transition to understand what each step does</li></ul> <p data-svelte-h="svelte-9kdrli">Step-through debugging is perfect for understanding the <em>data</em> transformations, but what about the <em>structure</em> of that data? While hooks and step-through help you debug runtime behavior, you also need to ensure your pipeline produces data in the format expected by downstream components. This is where feature contract validation comes in.</p> <h2 class="relative group"><a id="validating-feature-contracts" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#validating-feature-contracts"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Validating Feature Contracts</span></h2> <p data-svelte-h="svelte-1i8k9ls">Feature contracts define what data structure your pipeline expects as input and produces as output. | |
| Validating these contracts helps catch mismatches early.</p> <h3 class="relative group"><a id="understanding-feature-contracts" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#understanding-feature-contracts"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Understanding Feature Contracts</span></h3> <p data-svelte-h="svelte-1tmoeus">Each processor step has a <code>transform_features()</code> method that describes how it changes the data structure:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-comment"># Get the expected output features from your pipeline</span> | |
| initial_features = { | |
| PipelineFeatureType.OBSERVATION: { | |
| <span class="hljs-string">"observation.state"</span>: PolicyFeature(<span class="hljs-built_in">type</span>=FeatureType.STATE, shape=(<span class="hljs-number">7</span>,)), | |
| <span class="hljs-string">"observation.image"</span>: PolicyFeature(<span class="hljs-built_in">type</span>=FeatureType.IMAGE, shape=(<span class="hljs-number">3</span>, <span class="hljs-number">224</span>, <span class="hljs-number">224</span>)) | |
| }, | |
| PipelineFeatureType.ACTION: { | |
| <span class="hljs-string">"action"</span>: PolicyFeature(<span class="hljs-built_in">type</span>=FeatureType.ACTION, shape=(<span class="hljs-number">4</span>,)) | |
| } | |
| } | |
| <span class="hljs-comment"># Check what your pipeline will output</span> | |
| output_features = processor.transform_features(initial_features) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">"Input features:"</span>) | |
| <span class="hljs-keyword">for</span> feature_type, features <span class="hljs-keyword">in</span> initial_features.items(): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f" <span class="hljs-subst">{feature_type}</span>:"</span>) | |
| <span class="hljs-keyword">for</span> key, feature <span class="hljs-keyword">in</span> features.items(): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f" <span class="hljs-subst">{key}</span>: <span class="hljs-subst">{feature.<span class="hljs-built_in">type</span>.value}</span>, shape=<span class="hljs-subst">{feature.shape}</span>"</span>) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">"\nOutput features:"</span>) | |
| <span class="hljs-keyword">for</span> feature_type, features <span class="hljs-keyword">in</span> output_features.items(): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f" <span class="hljs-subst">{feature_type}</span>:"</span>) | |
| <span class="hljs-keyword">for</span> key, feature <span class="hljs-keyword">in</span> features.items(): | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f" <span class="hljs-subst">{key}</span>: <span class="hljs-subst">{feature.<span class="hljs-built_in">type</span>.value}</span>, shape=<span class="hljs-subst">{feature.shape}</span>"</span>)<!-- HTML_TAG_END --></pre></div> <h3 class="relative group"><a id="verifying-expected-features" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#verifying-expected-features"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Verifying Expected Features</span></h3> <p data-svelte-h="svelte-1n7eymf">Check that your pipeline produces the features you expect:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-comment"># Define what features you expect the pipeline to produce</span> | |
| expected_keys = [<span class="hljs-string">"observation.state"</span>, <span class="hljs-string">"observation.image"</span>, <span class="hljs-string">"action"</span>] | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">"Validating feature contract..."</span>) | |
| <span class="hljs-keyword">for</span> expected_key <span class="hljs-keyword">in</span> expected_keys: | |
| found = <span class="hljs-literal">False</span> | |
| <span class="hljs-keyword">for</span> feature_type, features <span class="hljs-keyword">in</span> output_features.items(): | |
| <span class="hljs-keyword">if</span> expected_key <span class="hljs-keyword">in</span> features: | |
| feature = features[expected_key] | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"✅ <span class="hljs-subst">{expected_key}</span>: <span class="hljs-subst">{feature.<span class="hljs-built_in">type</span>.value}</span>, shape=<span class="hljs-subst">{feature.shape}</span>"</span>) | |
| found = <span class="hljs-literal">True</span> | |
| <span class="hljs-keyword">break</span> | |
| <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> found: | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"❌ Missing expected feature: <span class="hljs-subst">{expected_key}</span>"</span>)<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-duvvy">This validation helps ensure your pipeline will work correctly with downstream components that expect specific data structures.</p> <h2 class="relative group"><a id="summary" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#summary"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Summary</span></h2> <p data-svelte-h="svelte-1klespr">Now that you understand the three debugging approaches, you can tackle any pipeline issue systematically:</p> <ol data-svelte-h="svelte-14jg3j9"><li><strong>Hooks</strong> - For runtime monitoring and validation without modifying pipeline code</li> <li><strong>Step-through</strong> - For inspecting intermediate states and understanding transformations</li> <li><strong>Feature validation</strong> - For ensuring data structure contracts are met</li></ol> <p data-svelte-h="svelte-1s8mdv6"><strong>When to use each approach:</strong></p> <ul data-svelte-h="svelte-6ucjs5"><li>Start with <strong>step-through debugging</strong> when you need to understand what your pipeline does or when something unexpected happens</li> <li>Add <strong>hooks</strong> for continuous monitoring during development and production to catch issues automatically</li> <li>Use <strong>feature validation</strong> before deployment to ensure your pipeline works with downstream components</li></ul> <p data-svelte-h="svelte-dgojim">These three tools work together to give you the complete observability that complex pipelines naturally lack. With hooks watching for issues, step-through helping you understand behavior, and feature validation ensuring compatibility, you’ll be able to debug any pipeline confidently and efficiently.</p> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/lerobot/blob/main/docs/source/debug_processor_pipeline.mdx" target="_blank"><svg class="mr-1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M31,16l-7,7l-1.41-1.41L28.17,16l-5.58-5.59L24,9l7,7z"></path><path d="M1,16l7-7l1.41,1.41L3.83,16l5.58,5.59L8,23l-7-7z"></path><path d="M12.419,25.484L17.639,6.552l1.932,0.518L14.351,26.002z"></path></svg> <span data-svelte-h="svelte-zjs2n5"><span class="underline">Update</span> on GitHub</span></a> <p></p> | |
| <script> | |
| { | |
| __sveltekit_9kza6s = { | |
| assets: "/docs/lerobot/pr_3313/en", | |
| base: "/docs/lerobot/pr_3313/en", | |
| env: {} | |
| }; | |
| const element = document.currentScript.parentElement; | |
| const data = [null,null]; | |
| Promise.all([ | |
| import("/docs/lerobot/pr_3313/en/_app/immutable/entry/start.d3f1c0f3.js"), | |
| import("/docs/lerobot/pr_3313/en/_app/immutable/entry/app.04bb7687.js") | |
| ]).then(([kit, app]) => { | |
| kit.start(app, element, { | |
| node_ids: [0, 12], | |
| data, | |
| form: null, | |
| error: null | |
| }); | |
| }); | |
| } | |
| </script> | |
Xet Storage Details
- Size:
- 61.4 kB
- Xet hash:
- 518d14ef0d27ba4e43d03d150c131f68a80259cc3c855ab7f383c35cf55347d7
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.