/** * 3D Model Architecture Visualization * * Interactive 3D visualization of the transformer model architecture, * showing layers, attention heads, and data flow with real values. * Inspired by neural network architecture diagrams. * * @component */ "use client"; import { useRef, useState, useEffect, Suspense } from "react"; import { Canvas, useFrame, useThree } from "@react-three/fiber"; import { getApiUrl } from "@/lib/config"; import { OrbitControls, Text, Box, Plane, Line, Billboard, PerspectiveCamera, Environment, Float } from "@react-three/drei"; import * as THREE from "three"; import { Brain, Layers, Activity, Zap, Eye, GitBranch, Maximize2, Move3D, HelpCircle, X, Info } from "lucide-react"; // Layer component representing a transformer layer function TransformerLayer({ position, layerIndex, attentionValues, onClick, isActive }: { position: [number, number, number]; layerIndex: number; attentionValues?: number[][]; onClick?: () => void; isActive?: boolean; }) { const meshRef = useRef(null); const [hovered, setHovered] = useState(false); useFrame((state) => { if (meshRef.current) { // NO floating animation - layers stay at their exact positions // meshRef.current.position.y = position[1]; // Keep at exact position // Only pulse when active if (isActive) { const scale = 1 + Math.sin(state.clock.elapsedTime * 3) * 0.05; meshRef.current.scale.set(scale, scale, scale); } } }); return ( {/* Main layer box */} setHovered(true)} onPointerOut={() => setHovered(false)} > {/* Layer label */} Layer {layerIndex} {/* Debug: Show actual position */} Y: {position[1].toFixed(1)} {/* Attention heads visualization */} {Array.from({ length: 16 }).map((_, i) => ( ))} 16 Attention Heads {/* FFN visualization */} FFN (4096d) ); } // Attention flow visualization function AttentionFlow({ startPos, endPos, intensity = 1, color = "#3b82f6" }: { startPos: [number, number, number]; endPos: [number, number, number]; intensity?: number; color?: string; }) { const lineRef = useRef(null); useFrame((state) => { // Animate the flow const time = state.clock.elapsedTime; // You could add particle effects here }); const points = [ new THREE.Vector3(...startPos), new THREE.Vector3(...endPos) ]; return ( ); } // Token embedding visualization function TokenEmbedding({ position }: { position: [number, number, number] }) { const meshRef = useRef(null); useFrame((state) => { if (meshRef.current) { meshRef.current.rotation.y = state.clock.elapsedTime * 0.5; } }); return ( Token Embeddings 51,200 × 1,024 ); } // Output layer visualization function OutputLayer({ position, modelInfo }: { position: [number, number, number]; modelInfo: { layers: number; heads: number; vocabSize: number; hiddenSize: number; totalParams: number } }) { const meshRef = useRef(null); const [probabilities, setProbabilities] = useState([]); // Debug log position useEffect(() => { console.log(`OutputLayer rendered at position: [${position[0]}, ${position[1]}, ${position[2]}]`); }, [position]); useEffect(() => { // Simulate probability distribution const probs = Array.from({ length: modelInfo.heads }, () => Math.random()); setProbabilities(probs); }, []); useFrame((state) => { if (meshRef.current) { meshRef.current.rotation.y = state.clock.elapsedTime * 0.3; } }); return ( Output Probabilities 51,200 tokens {/* Probability bars */} {probabilities.slice(0, 10).map((prob, i) => ( ))} ); } // Main 3D scene function Scene({ modelInfo }: { modelInfo: { layers: number; heads: number; vocabSize: number; hiddenSize: number; totalParams: number } }) { const [selectedLayer, setSelectedLayer] = useState(null); const { camera } = useThree(); // Model configuration from fetched data const numLayers = modelInfo.layers; const layerSpacing = 3.5; // Much larger spacing for clear separation // Calculate positions const outputYPosition = numLayers * layerSpacing + 5; const inputYPosition = -5; // Log to verify we're creating 20 layers useEffect(() => { console.log(`Creating ${numLayers} transformer layers`); console.log(`Layer spacing: ${layerSpacing}`); console.log(`Layer positions: `, Array.from({ length: numLayers }, (_, i) => i * layerSpacing)); console.log(`Last layer (19) position: ${(numLayers - 1) * layerSpacing}`); console.log(`Output position calculated: ${outputYPosition}`); console.log(`Input position: ${inputYPosition}`); }, []); return ( <> {/* Lighting */} {/* Token Embeddings (Input Layer) */} {/* Transformer Layers (0-19) */} {Array.from({ length: numLayers }).map((_, i) => { const yPosition = i * layerSpacing; return ( setSelectedLayer(i)} isActive={selectedLayer === i} /> ); })} {/* Output Layer (After Layer 19) */} {/* Attention flows between layers */} {Array.from({ length: numLayers - 1 }).map((_, i) => ( ))} {/* Flow from input to first layer */} {/* Flow from last layer to output */} {/* Grid for reference */} {/* Layer info display */} {selectedLayer !== null && ( Layer {selectedLayer} Details • 16 attention heads • 1024 hidden dimensions • 4096 FFN dimensions • Y Position: {(selectedLayer * layerSpacing).toFixed(1)} )} {/* Debug: Show output actual position */} Output Y: {outputYPosition.toFixed(1)} {/* Debug: Show highest layer position */} Layer 19 Y: {((numLayers - 1) * layerSpacing).toFixed(1)} ); } export default function ModelArchitecture3D() { const [viewMode, setViewMode] = useState<"perspective" | "top" | "side">("perspective"); const [showLabels, setShowLabels] = useState(true); const [autoRotate, setAutoRotate] = useState(false); // Start without auto-rotate for better control const [showExplanation, setShowExplanation] = useState(false); // Fetch real model data const [modelInfo, setModelInfo] = useState({ layers: 20, heads: 16, vocabSize: 51200, hiddenSize: 1024, totalParams: 356712448 }); useEffect(() => { fetch(`${getApiUrl()}/model/info`) .then(res => res.json()) .then(data => { setModelInfo({ layers: data.layers, heads: data.heads, vocabSize: data.vocabSize, hiddenSize: data.hiddenSize, totalParams: data.totalParams }); }) .catch(err => console.log('Using default model info')); }, []); // Generate contextual explanation for current visualization const generateExplanation = () => { return { title: "Transformer Architecture Visualization", description: `Interactive 3D view of a ${modelInfo.layers}-layer transformer model with ${modelInfo.heads} attention heads per layer.`, details: [ { heading: "What is a Transformer?", content: `Transformers are the foundation of modern LLMs. They process text by passing it through multiple layers, each applying attention mechanisms to understand relationships between words. This model has ${modelInfo.layers} layers stacked vertically.` }, { heading: "Reading the 3D Structure", content: `Bottom (green): Input embeddings convert text to vectors. Middle (blue): ${modelInfo.layers} transformer layers process information. Top (orange): Output layer predicts next tokens. The vertical flow shows how data moves through the network.` }, { heading: "Attention Heads (Small Blocks)", content: `Each layer contains ${modelInfo.heads} attention heads (colored blocks). These heads learn different aspects of language: grammar, semantics, context, etc. They work in parallel, each focusing on different patterns.` }, { heading: "Feed-Forward Networks (Purple)", content: `The purple blocks are FFN components with 4096 dimensions. After attention, these networks transform the data further, adding non-linearity and learning complex patterns.` }, { heading: "Information Flow", content: `Data flows upward from input to output. Each layer refines the understanding, building from simple patterns (early layers) to complex concepts (later layers). The lines show this sequential processing.` }, { heading: "Model Scale", content: `This architecture represents ~${Math.round(modelInfo.totalParams / 1e6)}M parameters. With ${modelInfo.vocabSize.toLocaleString()} token vocabulary, ${modelInfo.hiddenSize} hidden dimensions, and ${modelInfo.layers} layers, it can generate coherent code by learning patterns from training data.` } ] }; }; const explanation = generateExplanation(); return (
{/* Header */}

3D Model Architecture

Interactive 3D visualization of the transformer architecture

{/* Controls */}
{/* Main Content Area with Side Panel */}
{/* 3D Canvas */}
{/* Camera much further back for full view */} {/* Help Toggle Button */} {/* Instructions */}
Click layers to inspect
Drag to rotate • Scroll to zoom
{modelInfo.layers} layers × {modelInfo.heads} heads = {modelInfo.layers * modelInfo.heads} attention patterns
Architecture Stack:
↑ Output Probabilities (51,200 tokens)
↑ Layers 0-19 (20 transformer blocks)
↑ Input Embeddings (51,200 × 1,024)
{/* Legend */}
Components
Token Embeddings
Attention Layers
Feed-Forward
Output Layer
{/* Explanation Side Panel */}
{/* Panel Header */}

Understanding the Architecture

{/* Panel Content */}
{/* Main Description */}

{explanation.title}

{explanation.description}

{/* Explanation Sections */}
{explanation.details.map((section, idx) => (
{section.heading}

{section.content}

))}
{/* Visual Guide */}

Layer Components

Input: Token embeddings (51,200 × 1,024)
Attention: {modelInfo.layers} layers × {modelInfo.heads} heads
FFN: 4096 dimensional processing
Output: Probability over 51,200 tokens
{/* Model Statistics */}

Model Statistics

Total Layers: 20
Attention Heads: 16 per layer
Hidden Dimensions: 1,024
FFN Dimensions: 4,096
Vocabulary Size: 51,200 tokens
Parameters: ~350M
{/* Interaction Guide */}

💡 Interactive Features

  • • Click layers to see details
  • • Drag to rotate the model
  • • Scroll to zoom in/out
  • • Enable auto-rotate for 360° view
  • • Each layer processes all tokens in parallel
); }