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 : robustness , scable , generalised , code , zero hard coding

Visualize top k probable tokens from a single token_id input using Plotly. Create a loop to generate and visualize 30 words, updating the bar chart dynamically for each new token. Highlight top tokens with distinct colors and include labels, title, and legend.


reference code: plot should one by one :

import logging
from typing import Any, Dict, List, Optional, Tuple

import torch
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    PreTrainedModel,
    PreTrainedTokenizer,
)
import plotly.graph_objs as go
from plotly.subplots import make_subplots


# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class TokenVisualizer:
    """
    A class to visualize the top k probable token generations from a given token ID
    using a specified language model.

    Attributes:
        model_name (str): The name or path of the pre-trained language model.
        top_k (int): The number of top probable tokens to display.
    """

    def __init__(self, model_name: str = "gpt2", top_k: int = 10) -> None:
        """
        Initializes the TokenVisualizer with the specified model and top_k value.

        Args:
            model_name (str): The name or path of the pre-trained language model.
            top_k (int): The number of top probable tokens to display.
        """
        self.model_name: str = model_name
        self.top_k: int = top_k
        self.model: Optional[PreTrainedModel] = None
        self.tokenizer: Optional[PreTrainedTokenizer] = None
        self._load_model_and_tokenizer()

    def _load_model_and_tokenizer(self) -> None:
        """
        Loads the pre-trained model and tokenizer.
        """
        try:
            logger.info(f"Loading model '{self.model_name}'...")
            self.model = AutoModelForCausalLM.from_pretrained(
                self.model_name,
                torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
                device_map="auto" if torch.cuda.is_available() else None,
            )
            logger.info("Model loaded successfully.")

            logger.info(f"Loading tokenizer for model '{self.model_name}'...")
            self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
            if self.tokenizer.pad_token is None:
                self.tokenizer.pad_token = self.tokenizer.eos_token
            logger.info("Tokenizer loaded successfully.")
        except Exception as e:
            logger.error(f"Error loading model or tokenizer: {e}")
            raise

    def get_token_distribution(self, token_id: int) -> Tuple[List[str], List[float]]:
        """
        Retrieves the top k token probabilities and their corresponding tokens for a given token ID.

        Args:
            token_id (int): The input token ID.

        Returns:
            Tuple[List[str], List[float]]: A tuple containing a list of token strings and their probabilities.
        """
        if self.model is None or self.tokenizer is None:
            logger.error("Model or tokenizer not loaded.")
            raise ValueError("Model or tokenizer not loaded.")

        try:
            logger.info(f"Processing token ID: {token_id}")
            input_ids = torch.tensor([[token_id]]).to(self.model.device)
            with torch.no_grad():
                outputs = self.model(input_ids)
                logits = outputs.logits[:, -1, :]  # Get logits for the last token
                probabilities = torch.softmax(logits, dim=-1).squeeze()

            top_probs, top_ids = torch.topk(probabilities, self.top_k)
            tokens = [self.tokenizer.decode([token_id]) for token_id in top_ids.tolist()]
            probs = top_probs.cpu().tolist()

            logger.info(f"Top {self.top_k} tokens retrieved successfully.")
            return tokens, probs
        except Exception as e:
            logger.error(f"Error retrieving token distribution: {e}")
            raise

    def visualize_distribution(
        self, token_id: int, title: Optional[str] = None
    ) -> None:
        """
        Visualizes the token distribution as a bar chart using Plotly.

        Args:
            token_id (int): The input token ID.
            title (Optional[str]): The title of the plot. If None, a default title is used.
        """
        try:
            tokens, probs = self.get_token_distribution(token_id)
            token_texts = [token if token.strip() else "<UNK>" for token in tokens]

            plot_title = title or f"Top {self.top_k} Token Probabilities for Token ID {token_id}"
            fig = make_subplots(
                rows=1,
                cols=1,
                subplot_titles=(plot_title,),
            )

            bar = go.Bar(
                x=token_texts,
                y=probs,
                marker=dict(color='rgba(55, 128, 191, 0.7)'),
                name='Probability',
            )

            fig.add_trace(bar, row=1, col=1)

            fig.update_layout(
                title=plot_title,
                xaxis_title="Tokens",
                yaxis_title="Probability",
                legend_title="Legend",
                bargap=0.2,
                template="plotly_white",
            )

            fig.show()
            logger.info("Visualization created successfully.")
        except Exception as e:
            logger.error(f"Error during visualization: {e}")
            raise


def main() -> None:
    """
    Main function to execute the token visualization.
    """
    try:
        # Initialize the visualizer with desired model and top_k
        visualizer = TokenVisualizer(model_name="gpt2", top_k=100)

        # Example token ID input; replace with desired token ID
        example_token_id = visualizer.tokenizer.encode("Hello world", add_special_tokens=False)[-1]

        # Visualize the token distribution
        visualizer.visualize_distribution(token_id=example_token_id, title="Token Distribution Example")
    except Exception as e:
        logger.error(f"An error occurred in the main execution: {e}")


if __name__ == "__main__":
    main()