""" Token Journey Visualizer - Transformation Inspector """ import gradio as gr import numpy as np from utils import extract_single_transformation, get_token_choices MODEL_NAME = "TinyLlama/TinyLlama-1.1B-Chat-v1.0" cached_data = {} def format_vector(vector, title): """Format vector as HTML table (first 50 + ... + last 50).""" first_vals = vector[:50] last_vals = vector[-50:] sample = np.concatenate([first_vals, last_vals]) html = f"

{title}

" html += "
" html += "" html += "" # First 50 dimensions for idx in range(50): val = sample[idx] color = "gray" html += f"" # Separator html += "" # Last 50 dimensions for idx in range(50, 100): val = sample[idx] color = "gray" html += f"" html += "" html += "
{val:.4f}...{val:.4f}
" return html def format_matrix(matrix, title): """Format matrix as HTML table (first 50x50 + ... + last 50x50).""" first_first = matrix[:50, :50] first_last = matrix[:50, -50:] last_first = matrix[-50:, :50] last_last = matrix[-50:, -50:] sample_first = np.concatenate([first_first, first_last], axis=1) sample_last = np.concatenate([last_first, last_last], axis=1) sample = np.concatenate([sample_first, sample_last], axis=0) html = f"

{title}

" html += "
" html += "" # First 50 rows for row in range(50): html += "" # First 50 columns for col in range(50): val = sample[row, col] color = "gray" html += f"" # Column separator html += "" # Last 50 columns for col in range(50, 100): val = sample[row, col] color = "gray" html += f"" html += "" # Row separator html += "" for _ in range(50): html += "" html += "" for _ in range(50): html += "" html += "" # Last 50 rows for row in range(50, 100): html += "" # First 50 columns for col in range(50): val = sample[row, col] color = "gray" html += f"" # Column separator html += "" # Last 50 columns for col in range(50, 100): val = sample[row, col] color = "gray" html += f"" html += "" html += "
{val:.4f}...{val:.4f}
{val:.4f}...{val:.4f}
" return html def process_text(text): """Tokenize text.""" if not text.strip(): return gr.Dropdown(choices=[]) try: choices, indices = get_token_choices(text, MODEL_NAME) cached_data['text'] = text print(f"✅ Tokenized: {len(choices)} tokens") return gr.update(choices=choices, value=choices[0] if choices else None) except Exception as e: print(f"❌ Error in process_text: {e}") import traceback traceback.print_exc() return gr.update(choices=[], value=None) def visualize_transformation(token_choice, layer): """Show transformation as numbers.""" print(f"Visualize called: token={token_choice}, layer={layer}") if not token_choice: print("⚠️ No token selected") return "⚠️ Select a token first", "", "" if 'text' not in cached_data: print("⚠️ No text in cache") return "⚠️ Process text first", "", "" try: token_index = int(token_choice.split(":")[0]) result = extract_single_transformation( text=cached_data['text'], token_index=token_index, component="q_proj", layer=layer, model_name=MODEL_NAME ) input_html = format_vector(result['input_vector'], "Input Vector (100 dims)") matrix_html = format_matrix(result['weight_matrix'], "W_q Matrix (100×100)") output_html = format_vector(result['output_vector'], "Output Vector (100 dims)") return input_html, matrix_html, output_html except Exception as e: return f"Error: {e}", "", "" with gr.Blocks() as demo: gr.Markdown("# Token Transformation Inspector") with gr.Row(): text_input = gr.Textbox(label="Text", value="The cat sat on the mat") process_btn = gr.Button("Process") with gr.Row(): token_dropdown = gr.Dropdown(label="Token", choices=[]) layer_slider = gr.Slider(0, 21, value=0, step=1, label="Layer") visualize_btn = gr.Button("Visualize") input_display = gr.HTML() matrix_display = gr.HTML() output_display = gr.HTML() process_btn.click(process_text, text_input, token_dropdown) visualize_btn.click(visualize_transformation, [token_dropdown, layer_slider], [input_display, matrix_display, output_display]) if __name__ == "__main__": demo.launch()