Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4750dbd
feat: chart generation throughput
eric-tramel May 21, 2026
3047c42
fix: smooth throughput panel updates
eric-tramel May 21, 2026
61125a0
fix: align progress panel metrics
eric-tramel May 21, 2026
1cf84d5
fix: show token rates in progress demo
eric-tramel May 21, 2026
33cf915
fix: render progress legend without ascii separators
eric-tramel May 21, 2026
3679ad3
fix: avoid repeated column label in progress legend
eric-tramel May 21, 2026
b54d02a
fix: include units in progress rate headers
eric-tramel May 21, 2026
a065f06
fix: place progress completion beside row bars
eric-tramel May 21, 2026
75dcb5e
fix: split model usage from column progress
eric-tramel May 21, 2026
461f261
feat: add live multi-model traffic demo
eric-tramel May 21, 2026
f6a6d2e
fix: keep throughput chart height stable
eric-tramel May 21, 2026
de1c2d7
feat: mark request feedback in throughput chart
eric-tramel May 21, 2026
0525f6e
chore: remove example scripts from pr
eric-tramel May 21, 2026
29db063
test: remove redundant progress bar default check
eric-tramel May 21, 2026
be29f69
refactor: organize engine progress visualization
eric-tramel May 21, 2026
a24edaa
feat: add create progress override flags
eric-tramel May 22, 2026
a867a66
fix: rename create progress flags to tui
eric-tramel May 22, 2026
7a539c0
fix: make display_tui the canonical run config flag
eric-tramel May 22, 2026
6de88bc
Merge remote-tracking branch 'origin/main' into codex/progress-throug…
eric-tramel May 22, 2026
1de5cc4
test: make throughput redraw assertion logger-level independent
eric-tramel May 22, 2026
05cba08
Merge remote-tracking branch 'origin/main' into codex/progress-throug…
eric-tramel May 26, 2026
747fe2b
fix: preserve completed throughput samples
eric-tramel May 26, 2026
a5bdad2
fix: address progress tui review feedback
eric-tramel May 26, 2026
a9206d4
Merge branch 'main' into codex/progress-throughput-panel
eric-tramel May 26, 2026
0ee0dcb
fix: flex throughput chart for dense tables
eric-tramel May 26, 2026
e2f03b7
Merge branch 'main' into codex/progress-throughput-panel
eric-tramel May 26, 2026
22241b5
Merge branch 'main' into codex/progress-throughput-panel
eric-tramel May 27, 2026
c9b1687
merge main and address review feedback
eric-tramel Jul 6, 2026
640f97a
test: drain async bridge cancellation
eric-tramel Jul 6, 2026
201c36b
Merge remote-tracking branch 'origin/main' into codex/progress-throug…
eric-tramel Jul 6, 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
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="nemotron_parse_ocr")
return results

Expand Down
2 changes: 1 addition & 1 deletion docs/assets/recipes/vlm_long_doc/03-text-qa-sdg.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="text_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="page_classification")
return results

Expand Down
2 changes: 1 addition & 1 deletion docs/assets/recipes/vlm_long_doc/05-visual-qa-sdg.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="visual_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="single_page_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="multi_page_windowed_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="whole_document_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def create_dataset(
model_providers=model_providers,
)
data_designer.set_run_config(
dd.RunConfig(disable_early_shutdown=True, progress_bar=True),
dd.RunConfig(disable_early_shutdown=True, display_tui=True),
)
results = data_designer.create(config_builder, num_records=num_records, dataset_name="frontier_judge")
return results
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,22 @@ The performance numbers are satisfying, but raw throughput is only part of the p

### **Progress you can see**

Because rows complete out of order and row groups checkpoint independently, results start appearing on disk within seconds. The new progress bars — sticky ANSI bars that redraw in-place at the bottom of the terminal — update on every task completion rather than waiting for a full column to finish. Log messages from the scheduler and throttle layer render above the bars, so you see both the high-level progress and the per-event detail. A 10-minute generation run no longer means staring at nothing until the end.
Because rows complete out of order and row groups checkpoint independently, results start appearing on disk within seconds. The terminal throughput panel stays bounded to the viewport and redraws at a throttled interval instead of on every task completion. Its chart tracks records per second for active cell-by-cell generation columns, the column table shows current and average rates plus completion, and the model table reports request and token traffic by model alias. Seed and batch-level columns finish as whole tasks, so they do not appear as per-record curves. Scheduler and request-admission logs render above the panel, preserving both high-level progress and per-event detail.

```
column 'topic' ████████████████████████████████████░░░░ 89% | 890/1000 | 148.3 rec/s | eta 1s | 0 failed
column 'summary' ██████████████████████████░░░░░░░░░░░░░░ 65% | 650/1000 | 108.3 rec/s | eta 3s | 2 failed
column 'trivia' █████████████████████████████░░░░░░░░░░░ 72% | 720/1000 | 120.0 rec/s | eta 2s | 0 failed
column 'analysis' ██████████████░░░░░░░░░░░░░░░░░░░░░░░░░░ 35% | 350/1000 | 87.5 rec/s | eta 7s | 1 failed
╭─────────────────────────────────────────────────────────────────────────────╮
│Throughput rec/s | 12.4s | 154/200 | now 18.2 | 0 failed │
│ 20.0 ┤ ╭──── │
│ 10.0 ┤ ╭──────────╯ │
│ 0.0 ┼──────────────╯ │
├─────────────────────────────────────────────────────────────────────────────┤
│ column now rec/s avg rec/s done │
│● column 'summary' 10.1 8.4 82/100 82% ━━━━━━━━━━━━━━━ │
│● column 'analysis' 8.1 6.7 72/100 72% ━━━━━━━━━━━━━ │
│ │
│ model alias model name rpm in tok/s out tok/s │
│ writer nvidia/nemotron 6.0 42.1 11.3 │
╰─────────────────────────────────────────────────────────────────────────────╯
```

When tracing is enabled (`DATA_DESIGNER_ASYNC_TRACE=1` or `RunConfig(async_trace=True)`), the scheduler also records a `TaskTrace` for every task: when it was dispatched, when it acquired a semaphore slot, when it completed, and its status. These traces are available on the result object after the run, so you can reconstruct the scheduler's timeline and understand where time was spent.
Expand Down Expand Up @@ -214,7 +223,7 @@ The async engine is now Data Designer's execution engine. Your existing pipeline

This was a ground-up rebuild of the execution layer, delivered across six PRs over four weeks.

It started with the data structures: `ExecutionGraph`, `CompletionTracker`, and task models ([#356](https://github.com/NVIDIA-NeMo/DataDesigner/pull/356)). Next came the generator migration ([#378](https://github.com/NVIDIA-NeMo/DataDesigner/pull/378)), where we added symmetric `generate()`/`agenerate()` bridging so every generator works in both modes without rewriting. The core scheduler and buffer manager followed in [#404](https://github.com/NVIDIA-NeMo/DataDesigner/pull/404), then integration into `DatasetBuilder` with callbacks and trace export ([#429](https://github.com/NVIDIA-NeMo/DataDesigner/pull/429)). The `ThrottledModelClient` and dual-semaphore scheduler landed in [#449](https://github.com/NVIDIA-NeMo/DataDesigner/pull/449), wiring AIMD concurrency control into every outbound model request. A final polish pass ([#456](https://github.com/NVIDIA-NeMo/DataDesigner/pull/456)) added async preview, unified lifecycle callbacks, and sticky ANSI progress bars.
It started with the data structures: `ExecutionGraph`, `CompletionTracker`, and task models ([#356](https://github.com/NVIDIA-NeMo/DataDesigner/pull/356)). Next came the generator migration ([#378](https://github.com/NVIDIA-NeMo/DataDesigner/pull/378)), where we added symmetric `generate()`/`agenerate()` bridging so every generator works in both modes without rewriting. The core scheduler and buffer manager followed in [#404](https://github.com/NVIDIA-NeMo/DataDesigner/pull/404), then integration into `DatasetBuilder` with callbacks and trace export ([#429](https://github.com/NVIDIA-NeMo/DataDesigner/pull/429)). The `ThrottledModelClient` and dual-semaphore scheduler landed in [#449](https://github.com/NVIDIA-NeMo/DataDesigner/pull/449), wiring AIMD concurrency control into every outbound model request. A final polish pass ([#456](https://github.com/NVIDIA-NeMo/DataDesigner/pull/456)) added async preview and unified lifecycle callbacks. Its original sticky progress bars have since been replaced by the bounded throughput panel shown above.

The symmetric bridging was critical for adoption. Every `ColumnGenerator` has both a `generate()` and an `agenerate()` method. Implement one, and the base class synthesizes the other:

Expand All @@ -239,15 +248,15 @@ Generator authors implement whichever method is natural — sync for CPU-bound w

## **Try It**

Use the progress bars for real-time feedback:
Use the throughput panel for real-time feedback:

```py
from data_designer.config.run_config import RunConfig
from data_designer.interface import DataDesigner

dd = DataDesigner()
dd.set_run_config(RunConfig(
progress_bar=True,
display_tui=True,
))
result = dd.create(
config_builder=config,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def create_dataset(
model_providers=model_providers,
)
data_designer.set_run_config(
dd.RunConfig(disable_early_shutdown=True, progress_bar=True),
dd.RunConfig(disable_early_shutdown=True, display_tui=True),
)
results = data_designer.create(config_builder, num_records=num_records, dataset_name="frontier_judge")
return results
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="multi_page_windowed_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="nemotron_parse_ocr")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="page_classification")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="single_page_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="text_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="visual_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ def create_dataset(
artifact_path=artifact_path,
model_providers=model_providers,
)
data_designer.set_run_config(dd.RunConfig(progress_bar=True, disable_early_shutdown=True))
data_designer.set_run_config(dd.RunConfig(display_tui=True, disable_early_shutdown=True))
results = data_designer.create(config_builder, num_records=num_records, dataset_name="whole_document_qa")
return results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
from __future__ import annotations

import warnings
from collections.abc import Mapping
from typing import Any

from pydantic import Field, model_validator
from typing_extensions import Self

from data_designer.config.base import ConfigBase
from data_designer.config.utils.type_helpers import StrEnum
from data_designer.config.utils.warning_helpers import warn_at_caller


class JinjaRenderingEngine(StrEnum):
Expand All @@ -24,6 +26,7 @@ class JinjaRenderingEngine(StrEnum):
"RunConfig.throttle and ThrottleConfig are deprecated. Use RunConfig.request_admission with "
"RequestAdmissionTuningConfig for supported advanced request-admission tuning."
)
_PROGRESS_BAR_DEPRECATION_MESSAGE = "RunConfig.progress_bar is deprecated. Use RunConfig.display_tui instead."


class RequestAdmissionTuningConfig(ConfigBase):
Expand Down Expand Up @@ -144,9 +147,9 @@ class RunConfig(ConfigBase):
single conversation when generation tasks call `ModelFacade.generate(...)`. Must be >= 0.
Default is 0.
async_trace: If True, collect per-task tracing data. Default is False.
progress_bar: If True, display sticky ANSI progress bars instead of periodic log lines
during generation. Requires a TTY; falls back to log lines in non-TTY environments.
Default is False.
display_tui: If True, display the terminal throughput TUI instead of periodic
log lines during generation. Requires a TTY; falls back to log lines in
non-TTY environments. Default is True.
progress_interval: How often (in seconds) the async progress reporter emits a
consolidated log block. Must be > 0. Default is 5.0.
preserve_dropped_columns: If True, write columns removed by drop processors to
Expand Down Expand Up @@ -182,7 +185,7 @@ class RunConfig(ConfigBase):
max_conversation_restarts: int = Field(default=5, ge=0)
max_conversation_correction_steps: int = Field(default=0, ge=0)
async_trace: bool = False
progress_bar: bool = False
display_tui: bool = True
progress_interval: float = Field(default=5.0, gt=0.0)
preserve_dropped_columns: bool = Field(
default=True,
Expand All @@ -201,9 +204,21 @@ class RunConfig(ConfigBase):

@model_validator(mode="before")
@classmethod
def translate_deprecated_throttle_config(cls, data: Any) -> Any:
if isinstance(data, dict) and "throttle" in data:
normalized = dict(data)
def translate_deprecated_fields(cls, data: Any) -> Any:
if not isinstance(data, dict):
return data

normalized = dict(data)

if "progress_bar" in normalized:
progress_bar = normalized.pop("progress_bar")
normalized.setdefault("display_tui", progress_bar)
warn_at_caller(
_PROGRESS_BAR_DEPRECATION_MESSAGE,
DeprecationWarning,
)

if "throttle" in normalized:
throttle = normalized.pop("throttle")
if normalized.get("request_admission") is not None:
raise ValueError(
Expand All @@ -215,13 +230,43 @@ def translate_deprecated_throttle_config(cls, data: Any) -> Any:
throttle if isinstance(throttle, ThrottleConfig) else ThrottleConfig.model_validate(throttle)
)
normalized["request_admission"] = throttle_config.to_request_admission_tuning()
warnings.warn(
warn_at_caller(
_THROTTLE_DEPRECATION_MESSAGE,
DeprecationWarning,
stacklevel=2,
)
return normalized
return data
return normalized

@property
def progress_bar(self) -> bool:
warnings.warn(
_PROGRESS_BAR_DEPRECATION_MESSAGE,
DeprecationWarning,
stacklevel=2,
)
return self.display_tui

@progress_bar.setter
def progress_bar(self, value: bool) -> None:
warnings.warn(
_PROGRESS_BAR_DEPRECATION_MESSAGE,
DeprecationWarning,
stacklevel=2,
)
self.display_tui = value

def model_copy(self, *, update: Mapping[str, Any] | None = None, deep: bool = False) -> Self:
if update is not None and "progress_bar" in update:
normalized_update = dict(update)
progress_bar = normalized_update.pop("progress_bar")
normalized_update.setdefault("display_tui", progress_bar)
warnings.warn(
_PROGRESS_BAR_DEPRECATION_MESSAGE,
DeprecationWarning,
stacklevel=2,
)
update = normalized_update
return super().model_copy(update=update, deep=deep)

@model_validator(mode="after")
def normalize_shutdown_settings(self) -> Self:
Expand Down
Loading
Loading