"use client"; import { motion } from "framer-motion"; import { COLORS, VizFrame } from "./common"; export function AttentionMatrix({ tokens = ["the", "drone", "sees", "a", "gate"], width = 720, height = 460, }: { tokens?: string[]; width?: number; height?: number; }) { const N = tokens.length; // Synthetic attention weights (softmax-like) — emphasise diagonal + selected pairs const raw: number[][] = []; for (let i = 0; i < N; i++) { const row: number[] = []; for (let j = 0; j < N; j++) { const diag = Math.exp(-Math.abs(i - j) * 1.3); const pair = (i === 1 && j === 4) || (i === 4 && j === 1) ? 1.6 : 0; row.push(diag + pair + Math.random() * 0.05); } raw.push(row); } const A = raw.map((row) => { const m = Math.max(...row); const exp = row.map((v) => Math.exp(v - m)); const s = exp.reduce((a, b) => a + b, 0); return exp.map((v) => v / s); }); const cell = 50; const grid = N * cell; const offsetX = (width - grid) / 2; const offsetY = (height - grid) / 2 + 20; return ( {tokens.map((t, j) => ( {t} ))} {tokens.map((t, i) => ( {t} ))} {A.map((row, i) => row.map((v, j) => ( )), )} {/* Numeric labels */} {A.map((row, i) => row.map((v, j) => ( 0.4 ? COLORS.surface : COLORS.ink} > {v.toFixed(2)} )), )} ); }