Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
21573dd
feat: add InternVLA-N1 System-2 backbone with the z_latents bridge
hungho77 Aug 14, 2026
520777d
feat: export InternVLA-N1 directly, without repackaging the checkpoint
hungho77 Aug 14, 2026
c766549
feat: vendor the InternVLA-N1 trajectory expert for ONNX export
hungho77 Aug 14, 2026
e25d971
feat: vendor the InternVLA-N1 memory block, and verify System 1 numer…
hungho77 Aug 14, 2026
20d1d15
feat: export InternVLA-N1 System 1 through the action component
hungho77 Aug 14, 2026
af59c5a
feat: add the InternVLA-N1 System-1 denoising scheduler
hungho77 Aug 14, 2026
f0e0d18
feat: fold the trajectory projections into the exported denoise step
hungho77 Aug 14, 2026
b82d4f9
feat: add the fused guidance-and-Euler kernel for the System-1 loop
hungho77 Aug 14, 2026
881aaf7
feat: complete the InternVLA-N1 System-1 runtime
hungho77 Aug 14, 2026
2d936cb
feat: add the asynchronous System-2 to System-1 handoff
hungho77 Aug 14, 2026
0d70421
docs: document InternVLA-N1 and register it in the model and test lists
hungho77 Aug 14, 2026
8e22d53
feat: run the InternVLA-N1 planner on its own thread
hungho77 Aug 14, 2026
7df92a8
fix: keep the registry-bound name for the emitted hidden states
hungho77 Aug 14, 2026
802d432
docs: record the measured InternVLA-N1 numbers
hungho77 Aug 14, 2026
1f640bd
docs: add the PyTorch baseline to the System-2 table
hungho77 Aug 14, 2026
9356610
fix: release waitIdle when the planner thread stops
hungho77 Aug 14, 2026
269f0ee
feat: run System 1 on a high-priority CUDA stream
hungho77 Aug 14, 2026
afaab6f
fix: state that the control stream only helps in-process
hungho77 Aug 14, 2026
6569e02
fix: set every dynamic input shape on the trajectory expert
hungho77 Aug 14, 2026
9f21348
fix: say so when a checkpoint has no System-1 weights
hungho77 Aug 14, 2026
ce962d6
fix: emit hidden states at model width, project on the host
hungho77 Aug 14, 2026
ebbf40a
fix: read the hidden-states buffer at its own dtype
hungho77 Aug 15, 2026
585b0f5
style: apply pre-commit, and export the folded denoise step
hungho77 Aug 15, 2026
cae35ea
style: pass every pre-commit hook
hungho77 Aug 15, 2026
55a596e
chore: ignore the project venv and local artifacts
hungho77 Aug 15, 2026
d4536f1
chore: drop the redundant gitignore entries
hungho77 Aug 15, 2026
8f9a560
feat: run both InternVLA-N1 systems in one process
hungho77 Aug 15, 2026
2513ad4
feat: carry the host-side weight sidecar into the engine directory
hungho77 Aug 15, 2026
5d364cf
perf: upload the conditioning once per plan, not once per tick
hungho77 Aug 15, 2026
e9f785a
docs: warn that the dual-system example's conditioning is not the rea…
hungho77 Aug 15, 2026
3c32187
perf: stop generating text the bridge throws away
hungho77 Aug 15, 2026
81582eb
feat: carry the latent queries as tokens and emit z_latents from the …
hungho77 Aug 15, 2026
5404147
fix: the dual-system example sampled at the wrong guidance scale
hungho77 Aug 15, 2026
93b2a9f
fix: default guidance to 1.0 -- what InternNav actually deploys
hungho77 Aug 15, 2026
3a835e3
refactor: count plans through the driver, not a parallel atomic
hungho77 Aug 15, 2026
458e7de
docs: add the InternVLA-N1 experimental-runtime README
hungho77 Aug 15, 2026
935534f
refactor: dump_bridge writes the z_latents, not the buffer around them
hungho77 Aug 15, 2026
9262c10
fix(nvfp4): apply the AWQ pre_quant_scale instead of dropping it
hungho77 Aug 15, 2026
b066543
docs: drop the FP16 fusion note from the InternVLA-N1 guide
hungho77 Aug 15, 2026
979147c
docs: cut the FP16/FP8 aside from the NVFP4 flag note
hungho77 Aug 15, 2026
cf282b7
feat(runtime): size the hidden-states buffer from the engine, not the…
hungho77 Aug 19, 2026
ee2a208
refactor: name the dump tool for what it emits
hungho77 Aug 19, 2026
9fccfef
feat(quantization): accept InternVLA-N1 checkpoints
hungho77 Aug 24, 2026
d2167d8
refactor(internvla_n1): consolidate the CLIs onto the dual-system pair
hungho77 Aug 24, 2026
3d37959
docs(internvla_n1): drop the removed CLI and record the control rate
hungho77 Aug 24, 2026
de7758b
docs(internvla_n1): document the resident-server protocol from Python
hungho77 Aug 24, 2026
f47e878
docs(internvla_n1): re-measure latency and correct the scheme recomme…
hungho77 Aug 24, 2026
c8c9916
docs: fix two stale references outside the model's own README
hungho77 Aug 24, 2026
0c779b7
Merge upstream main into feat/vln-internvla-n1
hungho77 Sep 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Release Notes

## Unreleased
- Added InternVLA-N1-DualVLN vision-language navigation support: direct export of the Qwen2.5-VL planner with the z_latents bridge folded into the graph, and an experimental System-1 runtime for the flow-matching trajectory head

## 0.10.1
- Added experimental Dual NVIDIA DGX Spark support with TP=2 tensor-parallel inference over MPI and NCCL
- Redesigned the experimental OpenAI-compatible server for faster cold launches and lower memory usage
Expand Down
2 changes: 2 additions & 0 deletions cpp/runtime/config/llmEngineConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ void parseCoreFields(Json const& configJson, LLMEngineConfig& cfg)
cfg.numKVHeads = getRequired<int32_t>(configJson, "num_key_value_heads");
cfg.headDim = getRequired<int32_t>(configJson, "head_dim");
cfg.hiddenSize = getRequired<int32_t>(configJson, "hidden_size");
cfg.outputHiddenSize = configJson.value("output_hidden_size", cfg.hiddenSize);

// Top-level: kv_cache_dtype. Required — all current exports write this.
parseRequiredStateDtype(configJson, "kv_cache_dtype", cfg.kvCacheDtype);
Expand All @@ -531,6 +532,7 @@ void parseCoreFields(Json const& configJson, LLMEngineConfig& cfg)
requirePositive(cfg.numKVHeads, "num_key_value_heads");
requirePositive(cfg.headDim, "head_dim");
requirePositive(cfg.hiddenSize, "hidden_size");
requirePositive(cfg.outputHiddenSize, "output_hidden_size");
requirePositive(cfg.maxSupportedBatchSize, "max_batch_size");
requirePositive(cfg.maxSupportedInputLength, "max_input_len");
requirePositive(cfg.maxKVCacheCapacity, "max_kv_cache_capacity");
Expand Down
11 changes: 10 additions & 1 deletion cpp/runtime/config/llmEngineConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,16 @@ struct Gemma4MTPKVSharingEntry
struct LLMEngineConfig
{
// --- Core model dimensions ---
int32_t hiddenSize{}; //!< Model hidden dimension
int32_t hiddenSize{}; //!< Model hidden dimension

//! Width of the engine's `hidden_states` output, when it differs from
//! `hiddenSize`. A model may project the hidden states before emitting them --
//! InternVLA-N1 folds its norm + cond_projector into the graph and emits a
//! 768-wide bridge tensor -- and the runtime must then allocate and copy that
//! width rather than the model width. Parsed from the optional
//! `output_hidden_size` key; defaults to `hiddenSize`, so every model that
//! emits hidden states at model width is unaffected.
int32_t outputHiddenSize{};
int32_t outputVocabSize{}; //!< Actual output vocab (reduced if vocab reduction active)
int32_t numAttentionLayers{}; //!< Number of attention layers needing KV cache
int32_t numKVHeads{}; //!< Number of key-value heads
Expand Down
4 changes: 2 additions & 2 deletions cpp/runtime/llmRankRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1276,8 +1276,8 @@ bool LLMRankRuntime::handleRequest(LLMGenerationRequest const& request, LLMGener
int32_t const prefillSequenceLength
= *std::max_element(context.effectivePrefillLengths.begin(), context.effectivePrefillLengths.end());
mPipelineIO->streamingPrefill.populateFromPrefill(mPipelineIO->inputsEmbeds, mPipelineIO->outputHiddenStates,
activeBatchSize, prefillSequenceLength, mDeployment.base.hiddenSize, mMaxRuntimeBatchSize,
mDeployment.base.maxSupportedInputLength, stream);
activeBatchSize, prefillSequenceLength, mDeployment.base.hiddenSize, mDeployment.base.outputHiddenSize,
mMaxRuntimeBatchSize, mDeployment.base.maxSupportedInputLength, stream);
mLastPrefillLength = prefillSequenceLength;
mLastInputTokenIds = context.rawBatchedInputIds;
mHiddenStatesRegistry[0] = &mPipelineIO->streamingPrefill.inputEmbeds;
Expand Down
20 changes: 11 additions & 9 deletions cpp/runtime/state/pipelineIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,26 @@ void bindBackboneTensorMap(
} // namespace

void StreamingPrefillBuffers::populateFromPrefill(Tensor const& liveInputEmbeds, Tensor const& liveEngineHiddenStates,
int32_t batch, int32_t prefillLen, int32_t hiddenSize, int32_t maxBatch, int32_t maxSeq, cudaStream_t stream)
int32_t batch, int32_t prefillLen, int32_t hiddenSize, int32_t outputHiddenSize, int32_t maxBatch, int32_t maxSeq,
cudaStream_t stream)
{
auto const dtype = nvinfer1::DataType::kHALF;
if (inputEmbeds.isEmpty())
{
inputEmbeds = Tensor(
{maxBatch, maxSeq, hiddenSize}, DeviceType::kGPU, dtype, "PipelineIO::streamingPrefill.inputEmbeds");
engineHiddenStates = Tensor(
{maxBatch, maxSeq, hiddenSize}, DeviceType::kGPU, dtype, "PipelineIO::streamingPrefill.engineHiddenStates");
engineHiddenStates = Tensor({maxBatch, maxSeq, outputHiddenSize}, DeviceType::kGPU, dtype,
"PipelineIO::streamingPrefill.engineHiddenStates");
}
check::check(inputEmbeds.reshape({batch, prefillLen, hiddenSize}), "Tensor reshape failed");
check::check(engineHiddenStates.reshape({batch, prefillLen, hiddenSize}), "Tensor reshape failed");
check::check(engineHiddenStates.reshape({batch, prefillLen, outputHiddenSize}), "Tensor reshape failed");

size_t const bytes = static_cast<size_t>(batch) * prefillLen * hiddenSize * sizeof(__half);
size_t const embedBytes = static_cast<size_t>(batch) * prefillLen * hiddenSize * sizeof(__half);
size_t const hiddenBytes = static_cast<size_t>(batch) * prefillLen * outputHiddenSize * sizeof(__half);
CUDA_CHECK(cudaMemcpyAsync(
inputEmbeds.rawPointer(), liveInputEmbeds.rawPointer(), bytes, cudaMemcpyDeviceToDevice, stream));
CUDA_CHECK(cudaMemcpyAsync(
engineHiddenStates.rawPointer(), liveEngineHiddenStates.rawPointer(), bytes, cudaMemcpyDeviceToDevice, stream));
inputEmbeds.rawPointer(), liveInputEmbeds.rawPointer(), embedBytes, cudaMemcpyDeviceToDevice, stream));
CUDA_CHECK(cudaMemcpyAsync(engineHiddenStates.rawPointer(), liveEngineHiddenStates.rawPointer(), hiddenBytes,
cudaMemcpyDeviceToDevice, stream));
}

void bindRopeTensors(TensorMap& map, PipelineIO& io, SharedResources& res, LLMEngineConfig const& cfg)
Expand Down Expand Up @@ -457,7 +459,7 @@ PipelineIO PipelineIO::createForLLM(LLMEngineConfig const& cfg, cudaStream_t str
// streaming consumers (Qwen3-Omni Talker) read it; if the engine emits
// hidden_states but no consumer is set, the buffer is harmless write-target;
// if the engine has no hidden_states output the binding is silently skipped.
io.outputHiddenStates = Tensor({cfg.maxSupportedBatchSize, maxSeqLen, cfg.hiddenSize}, DeviceType::kGPU,
io.outputHiddenStates = Tensor({cfg.maxSupportedBatchSize, maxSeqLen, cfg.outputHiddenSize}, DeviceType::kGPU,
nvinfer1::DataType::kHALF, "PipelineIO::outputHiddenStates");

if (cfg.ropeConfig.type == RopeType::kMRope)
Expand Down
19 changes: 13 additions & 6 deletions cpp/runtime/state/pipelineIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,20 @@ struct StreamingPrefillBuffers
Tensor inputEmbeds; //!< Prefill-time layer-0 input embeddings.
Tensor engineHiddenStates; //!< Prefill-time engine hidden_states output.

//! Allocate on first call (sized to the worst case `{maxBatch, maxSeq, hiddenSize}`),
//! reshape to the current request's `{batch, prefillLen, hiddenSize}`, and copy
//! from the live PipelineIO buffers on `stream`. Subsequent calls reuse the same
//! allocation. Must be invoked after prefill and before the first decode step on
//! the same stream so the copies precede any overwrite of `outputHiddenStates`.
//! Allocate on first call (sized to the worst case `{maxBatch, maxSeq, dim}`),
//! reshape to the current request's `{batch, prefillLen, dim}`, and copy from the
//! live PipelineIO buffers on `stream`. Subsequent calls reuse the same allocation.
//! Must be invoked after prefill and before the first decode step on the same
//! stream so the copies precede any overwrite of `outputHiddenStates`.
//!
//! The two tensors are sized independently: input embeddings are always model
//! width, but a model may project its hidden states before emitting them, in
//! which case `outputHiddenSize` is the narrower emitted width. Copying the
//! model width out of a narrower engine output would read past the valid data
//! and hand the consumer a plausible-looking buffer whose tail is garbage.
void populateFromPrefill(Tensor const& liveInputEmbeds, Tensor const& liveEngineHiddenStates, int32_t batch,
int32_t prefillLen, int32_t hiddenSize, int32_t maxBatch, int32_t maxSeq, cudaStream_t stream);
int32_t prefillLen, int32_t hiddenSize, int32_t outputHiddenSize, int32_t maxBatch, int32_t maxSeq,
cudaStream_t stream);
};

//! All tensors flowing through the inference pipeline.
Expand Down
9 changes: 7 additions & 2 deletions docs/source/user_guide/examples/vla/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ runtime:
|---|---|---|---|
| [Alpamayo-R1](alpamayo.md) | camera frames, instruction, past trajectory | future acceleration/curvature trajectory | `action_inference` |
| [Cosmos3-Edge policy](cosmos3.md) | observation image or frame list, instruction | robot action chunk | `cosmos3_policy_inference` |
| [InternVLA-N1-DualVLN](internvla_n1.md) | navigation frames, instruction | future waypoint trajectory | `internvla_n1_dual_system_inference` |

Both workflows export on CPU, build all required TensorRT engines on the target,
and invoke one end-to-end runtime executable.
These workflows export on CPU, build all required TensorRT engines on the target,
and invoke one end-to-end runtime executable. InternVLA-N1 is the exception in one
respect: its two systems run at different rates, so System 2 plans on a background
thread while System 1 keeps sampling from the newest plan, rather than running the
whole graph in one pass.

```{toctree}
:maxdepth: 1
:hidden:

alpamayo.md
cosmos3.md
internvla_n1.md
```
Loading