Following this instruction :
1. Strictly adhere to PEP-8 standards, ensuring code is clean, well-structured, and follows Python's style guide for readability.
2. Use appropriate modules like `typing` for type hints, ensuring code clarity, maintainability, and leveraging Python's standard libraries effectively.
3. Focus on time, space, robustness, scalability; write optimized, efficient code that can handle large datasets and scale seamlessly.
4. Implement comprehensive error handling, catching exceptions gracefully, providing meaningful error messages, and ensuring code robustness under unexpected conditions.
5. Ensure the developer agent writes advanced, maintainable Python code, balancing performance and readability while adhering to best practices.


TASK : update play buttom to visualization model tensor one by one 


import os
from typing import Dict

import torch
from torch import nn
from torch.nn import Module

import plotly.express as px
from plotly.graph_objs import Figure


def create_visualization_directory(directory: str) -> None:
    """
    Creates the visualization directory if it does not exist.

    Args:
        directory (str): Path to the directory.
    """
    try:
        os.makedirs(directory, exist_ok=True)
    except OSError as e:
        raise RuntimeError(f"Failed to create directory '{directory}': {e}") from e


def save_plot(fig: Figure, filepath: str) -> None:
    """
    Saves the Plotly figure to an HTML file.

    Args:
        fig (Figure): Plotly figure object.
        filepath (str): Path to save the HTML file.
    """
    try:
        fig.write_html(filepath, include_plotlyjs='cdn', full_html=False)
    except Exception as e:
        raise RuntimeError(f"Failed to save plot to '{filepath}': {e}") from e


def _prepare_data(param_tensor: torch.Tensor) -> torch.Tensor:
    """
    Prepares the tensor data by detaching and moving it to CPU.

    Args:
        param_tensor (torch.Tensor): The parameter tensor.

    Returns:
        torch.Tensor: Prepared tensor.
    """
    return param_tensor.detach().cpu()


def _get_plot_title(param_name: str, tensor_shape: torch.Size, dimensions: int) -> str:
    """
    Generates a plot title based on parameter name, shape, and dimensions.

    Args:
        param_name (str): Name of the parameter.
        tensor_shape (torch.Size): Shape of the tensor.
        dimensions (int): Number of dimensions.

    Returns:
        str: Generated title.
    """
    dimension_str = "D" if dimensions > 1 else "D"
    return f"{dimensions}D Plot for '{param_name}' | Shape: {tensor_shape}"


def _get_labels(dimensions: int) -> Dict[str, str]:
    """
    Generates labels for the plot axes based on the number of dimensions.

    Args:
        dimensions (int): Number of dimensions.

    Returns:
        Dict[str, str]: Axis labels.
    """
    labels = {}
    for i in range(1, dimensions + 1):
        labels_key = f"Dimension {i}"
        labels[f"Dim{i}"] = labels_key
    return labels


def _apply_layout(
    fig: Figure, title: str, labels: Dict[str, str], template: str = "plotly_dark"
) -> None:
    """
    Applies layout settings to the Plotly figure for a professional look.

    Args:
        fig (Figure): The Plotly figure to modify.
        title (str): Title of the plot.
        labels (Dict[str, str]): Axis labels.
        template (str, optional): Plotly template. Defaults to "plotly_dark".
    """
    fig.update_layout(
        title=title,
        title_x=0.5,
        template=template,
        legend_title_text="Legend",
        title_font=dict(size=20, family="Arial"),
        font=dict(size=14, family="Arial"),
        margin=dict(l=50, r=50, t=80, b=50),
    )
    fig.update_traces(marker=dict(opacity=0.7, line=dict(width=1, color='DarkSlateGrey')))


def plot_1d(param_name: str, param_tensor: torch.Tensor, output_dir: str) -> None:
    """
    Creates and saves a box plot for a 1D tensor.

    Args:
        param_name (str): Name of the parameter.
        param_tensor (torch.Tensor): 1D tensor.
        output_dir (str): Directory to save the plot.
    """
    try:
        data = {
            'Values': _prepare_data(param_tensor).numpy()
        }
        title = _get_plot_title(param_name, param_tensor.shape, dimensions=1)
        fig = px.box(
            data,
            y='Values',
            title=title,
            labels={'Values': 'Parameter Values'},
            color_discrete_sequence=px.colors.qualitative.Pastel
        )
        _apply_layout(fig, title, labels={'Values': 'Parameter Values'})
        filepath = os.path.join(output_dir, f"{param_name}_box_plot.html")
        save_plot(fig, filepath)
    except Exception as e:
        print(f"Error plotting 1D parameter '{param_name}': {e}")


def plot_2d(param_name: str, param_tensor: torch.Tensor, output_dir: str) -> None:
    """
    Creates and saves a scatter plot for a 2D tensor.

    Args:
        param_name (str): Name of the parameter.
        param_tensor (torch.Tensor): 2D tensor.
        output_dir (str): Directory to save the plot.
    """
    if param_tensor.shape[0] < 2:
        print(f"Cannot plot 2D parameter '{param_name}': requires at least two elements in the first dimension.")
        return

    try:
        reshaped = _prepare_data(param_tensor).numpy()
        data = {
            'Dim1': reshaped[:, 0],
            'Dim2': reshaped[:, 1]
        }
        title = _get_plot_title(param_name, param_tensor.shape, dimensions=2)
        fig = px.scatter(
            data,
            x='Dim1',
            y='Dim2',
            title=title,
            labels={'Dim1': 'Dimension 1', 'Dim2': 'Dimension 2'},
            color_discrete_sequence=px.colors.qualitative.T10
        )
        _apply_layout(fig, title, labels={'Dim1': 'Dimension 1', 'Dim2': 'Dimension 2'})
        filepath = os.path.join(output_dir, f"{param_name}_scatter_plot.html")
        save_plot(fig, filepath)
    except Exception as e:
        print(f"Error plotting 2D parameter '{param_name}': {e}")


def plot_3d(param_name: str, param_tensor: torch.Tensor, output_dir: str) -> None:
    """
    Creates and saves a 3D scatter plot for a 3D tensor.

    Args:
        param_name (str): Name of the parameter.
        param_tensor (torch.Tensor): 3D tensor.
        output_dir (str): Directory to save the plot.
    """
    try:
        reshaped = _prepare_data(param_tensor).reshape(-1, 3).numpy()
        data = {
            'Dim1': reshaped[:, 0],
            'Dim2': reshaped[:, 1],
            'Dim3': reshaped[:, 2]
        }
        title = _get_plot_title(param_name, param_tensor.shape, dimensions=3)
        fig = px.scatter_3d(
            data,
            x='Dim1',
            y='Dim2',
            z='Dim3',
            title=title,
            labels={
                'Dim1': 'Dimension 1',
                'Dim2': 'Dimension 2',
                'Dim3': 'Dimension 3'
            },
            color='Dim3',
            color_continuous_scale='Viridis'
        )
        _apply_layout(fig, title, labels={
            'Dim1': 'Dimension 1',
            'Dim2': 'Dimension 2',
            'Dim3': 'Dimension 3'
        })
        filepath = os.path.join(output_dir, f"{param_name}_3d_scatter_plot.html")
        save_plot(fig, filepath)
    except Exception as e:
        print(f"Error plotting 3D parameter '{param_name}': {e}")


def plot_4d(param_name: str, param_tensor: torch.Tensor, output_dir: str) -> None:
    """
    Creates and saves a 3D scatter plot with color representing the 4th dimension for a 4D tensor.

    Args:
        param_name (str): Name of the parameter.
        param_tensor (torch.Tensor): 4D tensor.
        output_dir (str): Directory to save the plot.
    """
    try:
        reshaped = _prepare_data(param_tensor).reshape(-1, 4).numpy()
        data = {
            'Dim1': reshaped[:, 0],
            'Dim2': reshaped[:, 1],
            'Dim3': reshaped[:, 2],
            'Dim4': reshaped[:, 3]
        }
        title = _get_plot_title(param_name, param_tensor.shape, dimensions=4)
        fig = px.scatter_3d(
            data,
            x='Dim1',
            y='Dim2',
            z='Dim3',
            color='Dim4',
            title=title,
            labels={
                'Dim1': 'Dimension 1',
                'Dim2': 'Dimension 2',
                'Dim3': 'Dimension 3',
                'Dim4': 'Dimension 4'
            },
            color_continuous_scale='Plasma'
        )
        _apply_layout(fig, title, labels={
            'Dim1': 'Dimension 1',
            'Dim2': 'Dimension 2',
            'Dim3': 'Dimension 3',
            'Dim4': 'Dimension 4'
        })
        filepath = os.path.join(output_dir, f"{param_name}_4d_scatter_plot.html")
        save_plot(fig, filepath)
    except Exception as e:
        print(f"Error plotting 4D parameter '{param_name}': {e}")


def plot_5d(param_name: str, param_tensor: torch.Tensor, output_dir: str) -> None:
    """
    Creates and saves a 3D scatter plot with color and size representing the 4th and 5th dimensions for a 5D tensor.

    Args:
        param_name (str): Name of the parameter.
        param_tensor (torch.Tensor): 5D tensor.
        output_dir (str): Directory to save the plot.
    """
    try:
        reshaped = _prepare_data(param_tensor).reshape(-1, 5).numpy()
        data = {
            'Dim1': reshaped[:, 0],
            'Dim2': reshaped[:, 1],
            'Dim3': reshaped[:, 2],
            'Dim4': reshaped[:, 3],
            'Dim5': reshaped[:, 4]
        }
        title = _get_plot_title(param_name, param_tensor.shape, dimensions=5)
        fig = px.scatter_3d(
            data,
            x='Dim1',
            y='Dim2',
            z='Dim3',
            color='Dim4',
            size='Dim5',
            title=title,
            labels={
                'Dim1': 'Dimension 1',
                'Dim2': 'Dimension 2',
                'Dim3': 'Dimension 3',
                'Dim4': 'Dimension 4',
                'Dim5': 'Dimension 5'
            },
            color_continuous_scale='Cividis',
            size_max=18
        )
        _apply_layout(fig, title, labels={
            'Dim1': 'Dimension 1',
            'Dim2': 'Dimension 2',
            'Dim3': 'Dimension 3',
            'Dim4': 'Dimension 4',
            'Dim5': 'Dimension 5'
        })
        filepath = os.path.join(output_dir, f"{param_name}_5d_scatter_plot.html")
        save_plot(fig, filepath)
    except Exception as e:
        print(f"Error plotting 5D parameter '{param_name}': {e}")


def visualize_model_parameters(model: Module, output_dir: str = "model_parameter_plots") -> None:
    """
    Visualizes parameters of a PyTorch model based on their dimensionality.

    Args:
        model (Module): The PyTorch model.
        output_dir (str, optional): Directory to save the plots. Defaults to "model_parameter_plots".
    """
    create_visualization_directory(output_dir)

    plot_dispatcher = {
        1: plot_1d,
        2: plot_2d,
        3: plot_3d,
        4: plot_4d,
        5: plot_5d
    }

    for name, param in model.named_parameters():
        if not param.requires_grad:
            continue  # Skip non-trainable parameters

        ndim = param.ndimension()

        plot_func = plot_dispatcher.get(ndim)
        if plot_func:
            plot_func(name, param, output_dir)
        else:
            print(f"Skipping parameter '{name}' with unsupported dimensions: {ndim}D")


# Example Usage
if __name__ == "__main__":
    from transformers import AutoModelForCausalLM

    # Instantiate the model
    try:
        model = AutoModelForCausalLM.from_pretrained("gpt2")
        visualize_model_parameters(model, output_dir="model_parameter_plots")
    except Exception as e:
        print(f"Failed to visualize model parameters: {e}")