Skip to content

Implement T2, T3, and part of T4 from API refactor plan - #413

Merged
aidanfnv merged 8 commits into
dev/jarcher/inference-runtime-apifrom
dev/aidanf/inference-runtime-api-T2-T3-T4
Aug 5, 2026
Merged

Implement T2, T3, and part of T4 from API refactor plan#413
aidanfnv merged 8 commits into
dev/jarcher/inference-runtime-apifrom
dev/aidanf/inference-runtime-api-T2-T3-T4

Conversation

@aidanfnv

@aidanfnv aidanfnv commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@copy-pr-bot

copy-pr-bot Bot commented Aug 4, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@@ -42,8 +42,8 @@ def close(self) -> None:
class InferenceRuntime(Protocol):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is not necessary related to the input system design in this PR, but I suggest we remove InferenceRuntime as it's only job is to spin up and tear down InferenceSession. We should just leave that to the Application.

@@ -56,10 +56,10 @@ def close(self) -> None:
class ModelAdapter(Protocol):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We should probably rename ModelAdapter to InferenceSessionSchema or something. It's just advertising the schemas for InferenceSession

initial_inputs = mapping.map_initial_inputs(
user_inputs=user_inputs,
model_inputs=model_inputs,
initial_inputs = mapping.map_global_inputs(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm wondering if this is how we want it to behave.

The reference loop advances stateful input converters before the session starts. I think this canonicalizes the full session horizon for global inputs before runtime/session creation? But InputCanonicalizer converters are explicitly stateful and must be fed windows in session order.

KeyboardToDriverCommand.convert() mutates held-key state while reading events at canonical.py, line 177. If a real demo copied this loop, future key events could affect the initial state. Maybe the global conditioning should bypass canonicalization, or use a separate non-live startup path?

Not too sure about this one. Maybe @ArielG-NV or @fangjunzhou-nv may have an opinion. Or just throw this comment at codex and see what it thinks.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Bypassed canonicalization for global conditioning in cced4c7

registration rather than an application change. `InferenceInput` is what an
`InferenceSession` actually receives.

`InferenceInput` describes the data the model or inference pipeline actually

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think the implementation and the docs may be disagreeing with each other a little here, maybe just tell codex to do another once-over on the docs before you merge.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed this after the fact in e1fa7d0

)


def check_mapping_compatibility(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The compatibility checking seems good, but not sure if it's wired into the primary adapter/mapping path yet?

This function looks useful, but I think ModelAdapter.default_input_mapping() returns only an InputMapping at interfaces.py line 80, and schema declaration is an optional refinement at.

Before demo migration, maybe the standard loop needs a clear way to get mapping schema(s) and run compatibility before loading checkpoints?

Not necessarily something that has to be fixed here, but we should keep a note of it when we get to demo migration maybe.

device_kind="keyboard",
priority=priority,
consumes=(
UserInputCapability(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks like this consumes key_down / key_up. I think the older realtime helper uses keydown / keyup at input.py line 77 (flashdreams/flashdreams/serving/realtime/input.py:77), and one runtime test uses keyboard.keydown at test_inference_runtime_api.py, line 44.

I'm wondering if we need to standardise the names yet, or leave that for later. I imagine the demos will need a minimal event catalog or something.

@ArielG-NV ArielG-NV left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Initial review; questions and suggestions

```python
sana_wm_model = InferenceInputSchema(
description="sana-wm",
global_fields=(

@ArielG-NV ArielG-NV Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

these fields should potentially have a semantic type as well?

example: a "negative prompt" may be treated differently than a positive prompt, the underlying model_arch needs support for the semantic type of each (since each are technically processed uniquely depending on the underlying model_arch)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Turns out that part of the doc is just wrong about what a semantic_type entails.
name="negative_prompt" and name="prompt" would provide the negative vs positive distinction.
I will be renaming semantic_type to input_modality, and have corrected the docs, see #421

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

name="negative_prompt" would distinguish a negative prompt from a positive name="prompt".
The docs describe semantic_type incorrectly, and included stuff like "path" which are not even supposed to be in that field.

I have changed "semantic type" to "input modality" and corrected the doc, see e1fa7d0 (accidentally committed that a bit prematurely).

sana_wm_model = InferenceInputSchema(
description="sana-wm",
global_fields=(
InputField(name="prompt", lifecycle="cache_init"),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why are we using new terminology for the frequency of an input?

I suppose lifescycle is fine

but cache_init should be something like "global_conditioning"?

@aidanfnv aidanfnv Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

For "lifecycle", there was some partial attempt at separating the timeframe/frequency of input, frequency of consumption, and scope of usage (global vs step) and sometimes those share a label, sometimes they don't, which is needlessly confusing. "cache_init" describes a one-time global conditioning input.

global_fields is already the inputs for global conditioning (I will rename to global_conditioning_fields), so we do not need to specify "global_conditioning" again, and what makes "cache_init" different from other one-time global conditioning inputs is irrelevant here.

Honestly, "lifecycle" is not really fine here, it really confused myself and any agent I used here. Since the global vs step distinction is already handled elsewhere, I will rename it to frequency_consumed, where this example would have the value "once".

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

See #421 for the change

InputField(
name="camera_trajectory_c2w",
semantic_type="c2w_sequence",
lifecycle="rollout_binding",

@ArielG-NV ArielG-NV Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what is a rollout_binding, why not something likeper_step or every_step?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Somehow in the process of implementing this, the global conditioning inputs got split into 5 "lifecycles", where rollout_binding represents "values bound after cache initialization but before AR steps, such as HY-WorldPlay action labels, camera tensors, and memory state".

That is not useful to specify, so rollout_binding is indeed a per-step global conditioning input. I will change this to per_step.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

See #421 for the change

InputField(name="scene_id", update_policy=SESSION_START_ONLY),
)
)
schema.unsupported_global_updates(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what is unsupported_global_updates ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

unsupported_global_updates() is a helper on InferenceInputSchema for mid-rollout global-conditioning update requests. It looks at the non-empty InferenceInput.global_conditioning payload passed to a step/update and returns the field names whose schema marks them SESSION_START_ONLY, meaning they can be supplied at session start but should not be swapped while the rollout is active.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It will be removed in #421

@aidanfnv
aidanfnv marked this pull request as ready for review August 5, 2026 16:58
@aidanfnv
aidanfnv merged commit ddae974 into dev/jarcher/inference-runtime-api Aug 5, 2026
3 checks passed
@aidanfnv
aidanfnv deleted the dev/aidanf/inference-runtime-api-T2-T3-T4 branch August 5, 2026 16:58
@aidanfnv
aidanfnv restored the dev/aidanf/inference-runtime-api-T2-T3-T4 branch August 5, 2026 16:58
@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR implements the runtime input refactor by separating raw user events, canonical device-independent modalities, and model-facing inference inputs.

  • Adds stateful device canonicalization, keyboard driving controls, and scripted replay modalities.
  • Adds declarative mapping schemas and source-to-model compatibility reporting.
  • Renames the model input API to global and per-step InferenceInput conditioning and updates protocols, tests, and design documentation.

Confidence Score: 4/5

The PR appears safe to merge, with a non-blocking device-priority issue where an idle keyboard can mask another active control source.

The new input layers are coherently implemented and tested, but the keyboard converter violates the canonicalizer’s documented idle-yield contract by always returning a neutral value.

Files Needing Attention: flashdreams/flashdreams/runtime/canonical.py

Important Files Changed

Filename Overview
flashdreams/flashdreams/runtime/canonical.py Adds device converter registration, priority selection, keyboard driving conversion, and scripted modalities; idle keyboard conversion can mask lower-priority devices.
flashdreams/flashdreams/runtime/inputs.py Introduces canonical and inference input envelopes, capability schemas, phase-aware fields, and global-update metadata.
flashdreams/flashdreams/runtime/mapping.py Defines canonical-to-inference mapping protocols and declarative compatibility reporting for single or composed mappings.
flashdreams/flashdreams/runtime/interfaces.py Updates adapter, runtime, and session protocols to consume the new canonical and inference input contracts.
flashdreams/tests/test_runtime_canonical.py Thoroughly covers conversion, state, priority, rebinding, and scripted replay, but omits an idle higher-priority keyboard competing with an active device.
flashdreams/tests/test_runtime_input_mapping.py Covers input capabilities, schema matching, composed mappings, optional degradation, and global-update behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    U[UserInputs<br/>raw events] --> C[InputCanonicalizer]
    C --> M[CanonicalInputs<br/>device-independent modalities]
    M --> I[InputMapping]
    G[Application-owned<br/>global conditioning] --> I
    I --> E[InferenceInput<br/>global + step]
    E --> S[InferenceSession]
Loading

Reviews (1): Last reviewed commit: "Align closer to diagrams" | Re-trigger Greptile

Comment on lines +204 to +212
return DRIVER_COMMAND.value(
{
"throttle": 1.0 if held("throttle") else 0.0,
"brake": 1.0 if held("brake") else 0.0,
"steer": steer,
"stop": held("stop"),
"reverse": held("reverse"),
}
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Idle keyboard masks active devices

If an idle keyboard converter has higher priority than another active driver_command converter, it still returns a neutral value instead of None, so InputCanonicalizer selects it and ignores the active device's steering, throttle, or braking input.

@aidanfnv
aidanfnv deleted the dev/aidanf/inference-runtime-api-T2-T3-T4 branch August 5, 2026 17:04
gtong-nv pushed a commit that referenced this pull request Aug 5, 2026
* WIP implementation of T2, T3, partial T4

* Fix issues found by Claude

* Rewrite based on discussion, port after merge

* doc update

* doc updates

* Update based on new diagrams

* Align closer to diagrams
aidanfnv added a commit to aidanfnv/flashdreams that referenced this pull request Aug 5, 2026
aidanfnv added a commit to aidanfnv/flashdreams that referenced this pull request Aug 5, 2026
aidanfnv added a commit to aidanfnv/flashdreams that referenced this pull request Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants