Skip to main content

Data Visualization and Rendering

To visualize data in Flyte Decks, you can use the Renderable protocol and built-in renderers to convert Python objects into HTML. This is primarily achieved by annotating task return types with specific renderer classes.

Visualizing Data with Annotated Types

The most common way to use renderers is by wrapping your return type in typing.Annotated and providing a renderer instance as metadata. The Flyte TypeEngine detects any object implementing the Renderable protocol and uses it to generate the HTML for the Flyte Deck.

import pandas as pd
from typing import Annotated
from flyte.types._renderer import TopFrameRenderer, MarkdownRenderer
from flytekit import task

@task
def get_styled_dataframe() -> Annotated[pd.DataFrame, TopFrameRenderer(max_rows=5)]:
return pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})

@task
def get_markdown_report() -> Annotated[str, MarkdownRenderer()]:
return "# Analysis Report\n\n- Item 1\n- Item 2"

Built-in Renderers

The SDK provides several specialized renderers in flyte.types._renderer:

DataFrame Rendering

The TopFrameRenderer converts a pandas DataFrame into an HTML table. By default, it limits the output to 10 rows and 100 columns to prevent large Decks from slowing down the UI.

from flyte.types._renderer import TopFrameRenderer

# Customize the preview size
renderer = TopFrameRenderer(max_rows=20, max_cols=10)
html = renderer.to_html(df)

Markdown and Source Code

Use MarkdownRenderer to render strings as formatted HTML and SourceCodeRenderer for syntax-highlighted Python code.

from flyte.types._renderer import MarkdownRenderer, SourceCodeRenderer

# Render Markdown
md_renderer = MarkdownRenderer()
md_html = md_renderer.to_html("# Title\nContent")

# Render Python Source
code_renderer = SourceCodeRenderer(title="My Script")
code_html = code_renderer.to_html("def hello():\n print('world')")

Environment Dependencies

The PythonDependencyRenderer generates a comprehensive report of the installed Python packages in the task's environment. It includes a searchable table and a "Copy as requirements.txt" button.

from flyte.types._renderer import PythonDependencyRenderer

# This renderer does not require a python_value input to to_html()
# as it inspects the current environment via pip.
renderer = PythonDependencyRenderer()
dependency_html = renderer.to_html()

Creating and Registering Custom Renderers

You can create custom visualizations by implementing the Renderable protocol, which requires a to_html method.

from typing import Any
from flyte.io._dataframe.dataframe import DataFrameTransformerEngine

class CustomStatusRenderer:
def to_html(self, status_code: int) -> str:
color = "green" if status_code == 200 else "red"
return f"<div style='color: {color}'>Status: {status_code}</div>"

# Register the renderer globally for a specific type
DataFrameTransformerEngine.register_renderer(int, CustomStatusRenderer())

Troubleshooting

  • Arrow Tables: The ArrowRenderer currently returns the string representation of a pyarrow.Table (via df.to_string()) rather than a formatted HTML table. If you need a rich HTML table for Arrow data, consider converting it to a pandas DataFrame first.
  • Dependency Failures: PythonDependencyRenderer executes pip list and pip freeze using subprocess. In highly restricted environments or custom containers where pip is not in the path or sys.executable is restricted, this renderer will return an error message string instead of the package table.
  • Renderer Precedence: If a type is Annotated with multiple renderers, the TypeEngine will use the first one it encounters that implements the Renderable protocol. If no renderer is provided in Annotated, Flyte falls back to the default to_html implementation of the type's transformer.