feat: chart generation throughput#696
Conversation
Replace sticky progress bars with a bounded ANSI/asciichart throughput panel that plots records per second per generation column. Default progress_bar to enabled and add a local demo config plus screenshot for PR review. Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
|
Fern preview: https://nvidia-preview-pr-696.docs.buildwithfern.com/nemo/datadesigner
|
Code Review: PR #696 — feat: chart generation throughputSummaryReplaces the existing sticky fill-bar progress display with a bounded ANSI throughput chart panel rendered via
FindingsCorrectness / Behavior
Design / Conventions
Tests
Performance
Security
VerdictApprove with minor changes. The rewrite is well-scoped, the rendering math is reasonable, and tests cover the new surface adequately. Before merge I'd ask for:
The remaining points (constant naming, label-escape hardening, lost wrap-test coverage) are nice-to-haves rather than blockers. |
Greptile SummaryThis PR replaces the previous fill/disappear terminal progress bars with a live ANSI throughput panel backed by
|
| Filename | Overview |
|---|---|
| packages/data-designer-engine/src/data_designer/engine/progress/terminal/throughput_panel.py | New 940-line ANSI panel: handler wrapping, redraw throttling (0.75 s), feedback-marker projection, and TTY fallback are all present; lock ordering (ProgressTracker → panel lock) is consistent with no reverse path. |
| packages/data-designer-engine/src/data_designer/engine/progress/reporter.py | AsyncProgressReporter with 0.75 s TTY throttle in _maybe_report and run_id-filtered event subscriptions; close() is called in a finally block ensuring unsubscription. |
| packages/data-designer-engine/src/data_designer/engine/dataset_builders/async_scheduler.py | Adds request_cancel(), _cancel_requested Event, and _run_loop reference; cancellation checks are placed at all loop continuation points; reporter.close() is guaranteed in a finally block. |
| packages/data-designer-config/src/data_designer/config/run_config.py | display_tui replaces progress_bar; deprecated shim handles constructor, property read/write, and model_copy correctly with setdefault semantics so explicit display_tui always wins. |
| packages/data-designer-engine/src/data_designer/engine/column_generators/generators/custom.py | Async bridge now polls is_run_cancellation_requested() every 0.1 s, cancels the future, and raises asyncio.CancelledError; RuntimeError during run_coroutine_threadsafe properly closes the coroutine to prevent ResourceWarning. |
| packages/data-designer-engine/src/data_designer/engine/models/usage_events.py | Module-level callback registry with itertools.count IDs, lock-protected snapshots before iteration, and silent per-callback exception handling; unsubscribe returns a closure that pops by ID. |
| packages/data-designer-engine/src/data_designer/engine/dataset_builders/dataset_builder.py | Extracts _await_async_scheduler_result to handle KeyboardInterrupt by calling request_cancel() and waiting for the scheduler to finish before re-raising. |
| packages/data-designer-engine/src/data_designer/engine/models/facade.py | Emits TokenUsageEvent after each successful generate call; also fixes a pre-existing bug where output_tokens alone (without input_tokens) was discarded from token usage stats. |
| packages/data-designer/src/data_designer/cli/commands/create.py | Adds --tui/--no-tui as a typer Option with None default, forwarded to GenerationController.run_create() which applies it via model_copy. |
| packages/data-designer-engine/src/data_designer/engine/progress/tracker.py | Thread-safe ProgressTracker; log-interval accounting is correct under concurrent completions (next_log_at is advanced before lock release). |
Reviews (10): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile
Throttle active TTY redraws, sample rates over larger windows, smooth and fit chart series, bound rate history, and harden panel tests. Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Render the progress legend as a stable table with live token-rate columns, attribute model usage to active generation columns across async bridge boundaries, and cancel the async scheduler cleanly on KeyboardInterrupt. Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Emit synthetic token usage in the credential-free progress panel demo so the live token-rate columns are visible, and accept output-only provider usage as a progress event. Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Replace the pipe-delimited progress legend with a native spaced layout, keep column alignment via computed widths, mute the header row, and refresh the PR screenshot. Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Show raw column names in the async progress panel legend because the table header already provides the column context, and refresh the PR screenshot. Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Label the progress legend's now and average record-rate columns as rec/s and refresh the screenshot. Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
…hput-panel # Conflicts: # packages/data-designer-config/tests/config/test_run_config.py # uv.lock
Code Review — PR #696: feat: chart generation throughputSummaryThis PR replaces the old Footprint: 32 files, +2188/-668. Engine, config, and CLI packages all touched. Layering direction (interface → engine → config) is preserved. FindingsBehaviour / correctness
Style / conventions
TestingCoverage is strong:
Gaps / nice-to-haves:
Performance
SecurityNothing new exposed. ANSI sanitisation in VerdictLooks good to merge with minor follow-ups:
Architectural direction is sound: the new |
…hput-panel # Conflicts: # packages/data-designer-engine/src/data_designer/engine/dataset_builders/async_scheduler.py # packages/data-designer-engine/src/data_designer/engine/models/facade.py # packages/data-designer-engine/tests/engine/dataset_builders/test_async_builder_integration.py
|
Nice work on this one, @eric-tramel - the new progress package is thoughtfully separated and the compatibility path is in good shape. SummaryThis PR replaces the old sticky progress bars with a terminal throughput panel, wires model/request-admission events into the live display, makes FindingsWarnings - Worth addressing
Suggestions - Take it or leave it
What Looks Good
VerdictNeeds changes - please bound the panel height for wide configs and refresh the stale progress-bar docs before merge. The lockfile cleanup is optional but would make the dependency diff cleaner. This review was generated by an AI assistant. |
johnnygreco
left a comment
There was a problem hiding this comment.
This is really cool @eric-tramel!
I just have some nits related to more explicit labeling and logging. Would be nice if we could get "Preparing samplers to generate 50 records across 5 columns" to print before we start logging above the TUI. And can we have more explicit logs and/or labeling to make super clear that we are showing you llm/model-generated columns in the TUI? Of course, it is obvious when you think about it, but I could see users being confused mid-generation to see progress bars for some but not all columns.
The other nit is with all the labels at the top of graph, which shows the y-axis label (rec/s) plus the total stats. How flexible is the layout? Can we have just records/s on the left and then justify the total stats on the right or something like this? As is, it took me a second to understand "now 1.4" in │Throughput rec/s | 351.6s | 150/150 | now 1.4 | 0 failed, for example.
|
@mikeknep – heads up about this new tui |
|
Nice iteration on the follow-up commits. I re-reviewed latest head SummaryThis PR replaces the old sticky progress bars with the new FindingsWarnings - Worth addressing
What Looks Good
Validation
VerdictNeeds changes - please bound dense TUI panels to the terminal height and refresh the stale progress UI docs before merge. This review was generated by an AI assistant. |
- harden terminal progress sizing, ownership, and sanitization - preserve request accounting and resumed-run throughput accuracy - propagate cancellation through bridged and salvage work Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
…hput-panel Signed-off-by: Eric W. Tramel <eric.tramel@gmail.com>
Summary
This PR replaces the old fill/disappear terminal progress bars with a bounded ANSI/asciichart throughput panel that is enabled by default through the canonical
RunConfig.display_tui=Truesetting.RunConfig.progress_barremains supported as a deprecated compatibility shim with a warning, and the CLI exposesdata-designer create --tui / --no-tuias a per-run override.Usage
Default CLI behavior
The TUI is enabled by default for
createruns when the process is attached to a terminal. In non-TTY environments, such as redirected output or many notebook contexts, the renderer falls back instead of trying to draw the live panel.Force the TUI for one CLI run
Use
--tuiwhen the saved or programmatic run config disables the panel but this terminal run should show it.Disable the TUI for one CLI run
Use
--no-tuifor logs-only runs, CI jobs, captured terminal output, or any case where the live panel would be noisy.Configure from Python
display_tuiis the canonical run config option. It defaults toTrue; set it explicitly when creating datasets from a Python program.Disable from Python
Deprecated compatibility shim
Existing callers that still set
progress_barget the same behavior throughdisplay_tui, plus aDeprecationWarning.Changes
Added
data_designer.engine.progress.trackerforProgressTrackerdata_designer.engine.progress.reporterforAsyncProgressReporterdata_designer.engine.progress.terminal.throughput_panelforTerminalThroughputPanelRunConfig.display_tui, defaulting toTrue, as the canonical run config switch for the terminal throughput panel.RunConfig.progress_barcompatibility shim that maps todisplay_tuiand emitsDeprecationWarningon constructor use, property reads, and property writes.asciichartpyas an engine dependency for terminal chart rendering.rpm,in tok/s,out tok/s, and red feedback markers.data-designer create --tui / --no-tuito force the create command's TUI setting for a single CLI run.Changed
run_config.display_tui; production code no longer readsrun_config.progress_bar.now rec/s,avg rec/s, and completion progress; token rates are shown in the model-alias table.AsyncTaskScheduleracceptsdisplay_tuifor async panel setup and passes its run id intoAsyncProgressReporter, so global token/admission events from other runs do not pollute the active panel.packages/data-designer-engine/tests/engine/progress/.Removed
data_designer.engine.dataset_builders.utils..scratch/only.Fixed
Attention Areas
throughput_panel.py- terminal rendering, chart/table layout, redraw throttling, feedback marker projection, and TTY fallback behavior.reporter.py- progress aggregation, token/admission event subscriptions, cleanup, and run-id filtering.async_scheduler.py- async progress setup, run correlation, cancellation behavior, anddisplay_tuiplumbing.create.py- CLI--tui / --no-tuioverride surface.run_config.py- canonicaldisplay_tuifield plus deprecatedprogress_barshim behavior.pyproject.toml- adds theasciichartpyruntime dependency.Validation
make check-all: passedmake test: 3,788 passed, 1 skipped (621 config; 2,165 engine; 1,002 interface)make check-license-headers: 577 files up to datefern check: 0 errorsorigin/mainmerged at4b9b11cfDescription updated with AI