Skip to content

feat: add trace visualization to display_sample_record (#396) #438

Merged
nabinchha merged 9 commits into
mainfrom
nmulepati/feat/396-trace-visualization
Mar 23, 2026
Merged

feat: add trace visualization to display_sample_record (#396) #438
nabinchha merged 9 commits into
mainfrom
nmulepati/feat/396-trace-visualization

Conversation

@nabinchha

@nabinchha nabinchha commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

📋 Summary

Adds LLM conversation trace visualization to display_sample_record, allowing users to inspect the full chain-of-thought, tool calls, and tool results for
LLM-generated columns. Supports both terminal (Rich) and Jupyter notebook (HTML) rendering.

🔄 Changes

✨ Added

🔧 Changed

  • visualization.py: consolidated notebook detection to use shared is_notebook_environment(), added trace rendering for all LLM column types, moved record index
    display to top, normalized padding defaults

🔍 Attention Areas

⚠️ Reviewers: Please pay special attention to the following:

In ipynb notebook

Screenshot 2026-03-18 at 2 22 53 PM

In console

Uploading Screenshot 2026-03-18 at 2.35.35 PM.png…


🤖 Generated with AI

Render LLM conversation traces (produced by `with_trace != TraceType.NONE`)
as readable conversation flows in `display_sample_record()`. Two backends:
Rich terminal panels (styled by role) and Jupyter HTML block diagrams.

- New module `trace_renderer.py` with `TraceMessage` TypedDict and
  `TraceRenderer` class (`render_rich`, `render_notebook_html`)
- `include_traces` parameter on both mixin and standalone function
  (defaults to True, opt out with `include_traces=False`)
- Traces shown after Generated Columns table, before images
- Unit tests for various trace shapes and integration tests

Made-with: Cursor
Extract is_notebook_environment() utility to replace scattered
get_ipython() try/except blocks. Improve Rich trace readability
with better colors, separators, text folding, and dedented content.
Match HTML trace font to Rich monospace output. Move index label
to top of display and reduce inter-table spacing.

Made-with: Cursor
@nabinchha nabinchha requested a review from a team as a code owner March 18, 2026 20:20
@greptile-apps

greptile-apps Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds LLM conversation trace visualization to display_sample_record, introducing a new TraceRenderer class that renders chain-of-thought, tool calls, and tool results in both Rich terminal and Jupyter HTML formats. The implementation is well-structured with good test coverage, and the two P0/P1 concerns from prior rounds (double-escaping of func_name and the trace_renderer NameError guard) have been correctly resolved.

One remaining issue:

  • is_notebook_environment() in misc.py compares shell.__class__.__name__ against "google.colab._shell", which is a module path — not a class name. In Google Colab the class name is "Shell", so the Colab branch never matches and is_notebook_environment() silently returns False on Colab, causing users to see Rich terminal output instead of the intended HTML rendering.

Other notable changes:

  • include_traces=True parameter added to display_sample_record and WithRecordSamplerMixin with clean pass-through wiring
  • Record index label moved to the top of the output (both terminal and notebook paths)
  • Padding defaults normalized across table renders ((1, 0, 1, 0) → default)
  • _display_notebook_html helper extracted to avoid repeating IPython.display import logic

Confidence Score: 4/5

  • Safe to merge after fixing the __class__.__name__ vs module path mismatch in the Colab detection branch.
  • The core rendering logic and HTML escaping are correct, all prior review concerns are addressed, and the test suite is thorough. The only remaining concrete bug is the Google Colab environment detection always returning False (module path compared against class name), which is a targeted one-line fix.
  • packages/data-designer-config/src/data_designer/config/utils/misc.py — the is_notebook_environment() Colab branch

Important Files Changed

Filename Overview
packages/data-designer-config/src/data_designer/config/utils/misc.py Adds is_notebook_environment() helper; the Google Colab detection branch compares __class__.__name__ against a module path string ("google.colab._shell") instead of the class name ("Shell"), so Colab is never detected.
packages/data-designer-config/src/data_designer/config/utils/trace_renderer.py New module implementing Rich and HTML rendering for LLM trace conversations. HTML escaping is handled correctly throughout (double-escape fix from prior review applied), TypedDict schema is well-typed, edge cases like empty traces and malformed JSON are handled.
packages/data-designer-config/src/data_designer/config/utils/visualization.py Integrates trace rendering into display_sample_record; the NameError guard fix from prior review is applied, Rich vs HTML rendering paths are logically correct, and the record-index display is moved to the top as intended.
packages/data-designer-config/tests/config/utils/test_trace_renderer.py Comprehensive 338-line test suite covering Rich rendering, HTML rendering, edge cases (empty traces, malformed JSON, missing IPython), and integration with display_sample_record including include_traces=False and save_path scenarios.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant display_sample_record
    participant is_notebook_environment
    participant TraceRenderer
    participant IPython

    Caller->>display_sample_record: record, config_builder, include_traces=True
    display_sample_record->>is_notebook_environment: check environment
    is_notebook_environment-->>display_sample_record: in_notebook (bool)

    display_sample_record->>display_sample_record: build render_list (Rich panels)

    alt include_traces=True
        loop each LLM column → side_effect trace columns
            display_sample_record->>display_sample_record: collect traces_to_display_later
            alt not in_notebook OR save_path set
                display_sample_record->>TraceRenderer: render_rich(traces, col_name)
                TraceRenderer-->>display_sample_record: Rich Panel
                display_sample_record->>display_sample_record: append to render_list
            end
        end
    end

    display_sample_record->>display_sample_record: print Rich render_list to console/file

    alt in_notebook AND include_traces AND traces exist
        loop each (col_name, trace_data)
            display_sample_record->>TraceRenderer: render_notebook_html(traces, col_name)
            TraceRenderer->>IPython: display(HTML(container))
        end
    end
Loading

Comments Outside Diff (1)

  1. packages/data-designer-config/src/data_designer/config/utils/misc.py, line 13 (link)

    P1 Google Colab detection always fails

    shell.__class__.__name__ returns the class name (e.g. "Shell"), not the full module path. Comparing it against "google.colab._shell" — which is a module path, not a class name — will never match in a Colab runtime. As a result, is_notebook_environment() always returns False on Colab, and users will silently get Rich terminal output instead of HTML rendering.

    The canonical approach is to check the class's module:

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: packages/data-designer-config/src/data_designer/config/utils/misc.py
    Line: 13
    
    Comment:
    **Google Colab detection always fails**
    
    `shell.__class__.__name__` returns the class **name** (e.g. `"Shell"`), not the full module path. Comparing it against `"google.colab._shell"` — which is a module path, not a class name — will never match in a Colab runtime. As a result, `is_notebook_environment()` always returns `False` on Colab, and users will silently get Rich terminal output instead of HTML rendering.
    
    The canonical approach is to check the class's module:
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: packages/data-designer-config/src/data_designer/config/utils/misc.py
Line: 13

Comment:
**Google Colab detection always fails**

`shell.__class__.__name__` returns the class **name** (e.g. `"Shell"`), not the full module path. Comparing it against `"google.colab._shell"` — which is a module path, not a class name — will never match in a Colab runtime. As a result, `is_notebook_environment()` always returns `False` on Colab, and users will silently get Rich terminal output instead of HTML rendering.

The canonical approach is to check the class's module:

```suggestion
        return shell is not None and (
            shell.__class__.__name__ == "ZMQInteractiveShell"
            or shell.__class__.__module__ == "google.colab._shell"
        )
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (6): Last reviewed commit: "Merge branch 'main' into nmulepati/feat/..." | Re-trigger Greptile

Comment thread packages/data-designer-config/src/data_designer/config/utils/trace_renderer.py Outdated
Comment thread packages/data-designer-config/src/data_designer/config/utils/misc.py Outdated
- Remove double html.escape() on func_name in render_notebook_html;
  _build_html_block already escapes the title
- Guard notebook trace display with include_traces to prevent potential
  NameError if trace_renderer is not instantiated
- Improve is_notebook_environment() to check shell class name
  (ZMQInteractiveShell / google.colab._shell) instead of just
  get_ipython() existence, avoiding false positives in IPython terminals

Made-with: Cursor

@johnnygreco johnnygreco left a comment

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.

Review comments on trace visualization PR.

Comment thread packages/data-designer-config/src/data_designer/config/utils/trace_renderer.py Outdated
Comment thread packages/data-designer-config/src/data_designer/config/utils/visualization.py Outdated
Comment thread packages/data-designer-config/src/data_designer/config/utils/visualization.py Outdated
Comment thread packages/data-designer-config/tests/config/utils/test_trace_renderer.py Outdated
Comment thread packages/data-designer-config/src/data_designer/config/utils/trace_renderer.py Outdated

@johnnygreco johnnygreco left a comment

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.

A few more review comments.

Comment thread packages/data-designer-config/src/data_designer/config/utils/visualization.py Outdated
Comment thread packages/data-designer-config/src/data_designer/config/utils/trace_renderer.py Outdated

@johnnygreco johnnygreco left a comment

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.

One more.

- Fix turn count: count assistant messages with tool calls instead of
  individual tool-call IDs so parallel calls report 1 turn, not N
- Include Rich trace panels in render_list when save_path is set, even
  in notebook mode, so saved HTML files contain trace data
- Move _LLM_COLUMN_TYPES to module level
- Revert pad_console_element default padding to (1, 0, 1, 0)
- Initialize trace_renderer unconditionally to prevent potential NameError
- Consolidate IPython.display imports into _display_notebook_html helper
- Restrict bg_color to RoleHtmlColor Literal type
- Precise type annotation for sections list in render_rich
- Remove unnecessary # noqa: F821 suppression
- Move test imports to module level, remove __import__ pattern

Made-with: Cursor
@nabinchha nabinchha merged commit 63c294e into main Mar 23, 2026
47 checks passed
@nabinchha nabinchha deleted the nmulepati/feat/396-trace-visualization branch March 23, 2026 22:57
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.

2 participants