Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
update author parts, add input label training embed and data packing embed
Browse files
app/src/components/Hero.astro
CHANGED
|
@@ -405,7 +405,7 @@ const pdfFilename = `${slugify(pdfBase)}.pdf`;
|
|
| 405 |
display: flex;
|
| 406 |
flex-direction: column;
|
| 407 |
gap: 8px;
|
| 408 |
-
max-width:
|
| 409 |
}
|
| 410 |
.meta-container-cell h3 {
|
| 411 |
margin: 0;
|
|
|
|
| 405 |
display: flex;
|
| 406 |
flex-direction: column;
|
| 407 |
gap: 8px;
|
| 408 |
+
max-width: 400px;
|
| 409 |
}
|
| 410 |
.meta-container-cell h3 {
|
| 411 |
margin: 0;
|
app/src/content/embeds/aws-bandwidth-bottleneck.html
CHANGED
|
@@ -62,7 +62,7 @@
|
|
| 62 |
}
|
| 63 |
|
| 64 |
.aws-topology-container.fixed-height {
|
| 65 |
-
height:
|
| 66 |
}
|
| 67 |
|
| 68 |
.aws-topology-container svg {
|
|
@@ -74,6 +74,12 @@
|
|
| 74 |
transition: opacity 0.2s ease;
|
| 75 |
}
|
| 76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
.aws-topology-controls {
|
| 78 |
position: absolute;
|
| 79 |
bottom: 10px;
|
|
@@ -115,6 +121,13 @@
|
|
| 115 |
flex-shrink: 0;
|
| 116 |
}
|
| 117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
.aws-topology-legend {
|
| 119 |
position: absolute;
|
| 120 |
bottom: 10px;
|
|
@@ -1183,12 +1196,15 @@
|
|
| 1183 |
// ============================================================================
|
| 1184 |
// DRAW SINGLE SYSTEM (variable number of ensembles)
|
| 1185 |
// ============================================================================
|
| 1186 |
-
function drawSystem(renderer, systemIndex, systemCenterX, cpuY, nvswitchY, ensembleCount = 1, drawEfaCrossLinks = false) {
|
|
|
|
|
|
|
|
|
|
| 1187 |
// Calculate ensemble width (4 groups)
|
| 1188 |
const ensembleWidth = CONFIG.groupCount * CONFIG.gaps.horizontal;
|
| 1189 |
|
| 1190 |
-
// Calculate system bounding box
|
| 1191 |
-
const systemWidth =
|
| 1192 |
const systemHeight = CONFIG.sizes.cpu + CONFIG.gaps.cpuToPcie + CONFIG.sizes.pcie.height +
|
| 1193 |
CONFIG.gaps.pcieToGpu + CONFIG.sizes.gpu.height +
|
| 1194 |
CONFIG.gaps.gpuToNvswitch + CONFIG.sizes.nvswitch.height;
|
|
@@ -1227,11 +1243,11 @@
|
|
| 1227 |
}
|
| 1228 |
|
| 1229 |
// Draw each ensemble in the system
|
| 1230 |
-
for (let ensIndex = 0; ensIndex <
|
| 1231 |
const ensembleGlobalIndex = systemIndex * CONFIG.ensembleCount + ensIndex;
|
| 1232 |
|
| 1233 |
// Position ensemble within system
|
| 1234 |
-
const ensembleOffsetX = (ensIndex - (
|
| 1235 |
const ensembleCenterX = systemCenterX + ensembleOffsetX;
|
| 1236 |
|
| 1237 |
drawEnsemble(renderer, ensembleGlobalIndex, ensembleCenterX, cpuY, nvswitchY);
|
|
@@ -1239,8 +1255,8 @@
|
|
| 1239 |
|
| 1240 |
// Draw NUMA node borders (one per ensemble) if 2 ensembles
|
| 1241 |
if (ensembleCount === 2) {
|
| 1242 |
-
for (let ensIndex = 0; ensIndex <
|
| 1243 |
-
const ensembleOffsetX = (ensIndex - (
|
| 1244 |
const ensembleCenterX = systemCenterX + ensembleOffsetX;
|
| 1245 |
|
| 1246 |
// Calculate NUMA node bounding box (same as system but for single ensemble)
|
|
@@ -1285,8 +1301,8 @@
|
|
| 1285 |
const offset = getLinkOffset(bw.width);
|
| 1286 |
|
| 1287 |
// Connect all GPUs in the system to all NVSwitches in the system
|
| 1288 |
-
const totalGpusInSystem =
|
| 1289 |
-
const totalNVSwitchesInSystem =
|
| 1290 |
|
| 1291 |
for (let gpuIndex = 0; gpuIndex < totalGpusInSystem; gpuIndex++) {
|
| 1292 |
const gpuGlobalIndex = systemIndex * CONFIG.ensembleCount * CONFIG.groupCount + gpuIndex;
|
|
@@ -1298,8 +1314,8 @@
|
|
| 1298 |
}
|
| 1299 |
}
|
| 1300 |
|
| 1301 |
-
// Draw CPU-to-CPU link between ensembles (only if 2 ensembles)
|
| 1302 |
-
if (
|
| 1303 |
const cpu0Id = systemIndex * CONFIG.ensembleCount === 0 ? 'cpu' : `cpu-${systemIndex * CONFIG.ensembleCount}`;
|
| 1304 |
const cpu1Id = `cpu-${systemIndex * CONFIG.ensembleCount + 1}`;
|
| 1305 |
|
|
@@ -1310,8 +1326,8 @@
|
|
| 1310 |
|
| 1311 |
renderer.drawLink(cpu0Id, cpu1Id, color, bw.width, 'right', 'left', offset, 0, 1, 0, 1, 'cpu', '16GB/s');
|
| 1312 |
|
| 1313 |
-
// Draw EFA-to-EFA link between ensembles (only if explicitly requested)
|
| 1314 |
-
if (drawEfaCrossLinks) {
|
| 1315 |
const efaExt0Id = systemIndex * CONFIG.ensembleCount * CONFIG.groupCount === 0 ? 'efa-external' : `efa-external-${systemIndex * CONFIG.ensembleCount * CONFIG.groupCount}`;
|
| 1316 |
const efaExt1Id = `efa-external-${systemIndex * CONFIG.ensembleCount * CONFIG.groupCount + CONFIG.groupCount}`;
|
| 1317 |
|
|
@@ -1498,7 +1514,7 @@
|
|
| 1498 |
|
| 1499 |
// Only draw EFA cross-links for intranode EFA path
|
| 1500 |
const drawEfaCrossLinks = currentActivePathId === 'gpu-gpu-efa-intranode';
|
| 1501 |
-
drawSystem(renderer, sysIndex, centerX, cpuY, nvswitchY, ensembleCount, drawEfaCrossLinks);
|
| 1502 |
}
|
| 1503 |
|
| 1504 |
// Draw EFA cross-link between systems (for internode)
|
|
@@ -1563,10 +1579,35 @@
|
|
| 1563 |
currentSystemCount = systemCount;
|
| 1564 |
}
|
| 1565 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1566 |
// ============================================================================
|
| 1567 |
// HIGHLIGHT HELPERS
|
| 1568 |
// ============================================================================
|
| 1569 |
-
function highlightPath(path, pathLabel = '') {
|
| 1570 |
const svg = getElement('aws-topology-container').querySelector('svg');
|
| 1571 |
if (!svg) return;
|
| 1572 |
|
|
@@ -1587,6 +1628,20 @@
|
|
| 1587 |
});
|
| 1588 |
});
|
| 1589 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1590 |
// Highlight path nodes
|
| 1591 |
path.nodes.forEach(nodeId => {
|
| 1592 |
let nodeEl = svg.querySelector(`g[id="${nodeId}"]`);
|
|
@@ -1630,6 +1685,23 @@
|
|
| 1630 |
});
|
| 1631 |
});
|
| 1632 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1633 |
// Calculate and show bottleneck (minimum bandwidth in the path)
|
| 1634 |
let minBandwidth = Infinity;
|
| 1635 |
let minBandwidthValue = null;
|
|
@@ -1678,6 +1750,7 @@
|
|
| 1678 |
const bottleneckEl = getElement('aws-topology-bottleneck');
|
| 1679 |
const bottleneckValueEl = bottleneckEl.querySelector('.bottleneck-value');
|
| 1680 |
const bottleneckPathEl = bottleneckEl.querySelector('.bottleneck-path');
|
|
|
|
| 1681 |
const realBandwidthsEl = bottleneckEl.querySelector('.real-bandwidths');
|
| 1682 |
|
| 1683 |
// Check if real bandwidths are enabled
|
|
@@ -1685,11 +1758,28 @@
|
|
| 1685 |
const showRealBandwidths = embedConfig.showRealBandwidths;
|
| 1686 |
|
| 1687 |
if (showRealBandwidths) {
|
| 1688 |
-
// When real bandwidths are shown, display
|
| 1689 |
-
|
| 1690 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1691 |
} else {
|
| 1692 |
// Normal bottleneck display
|
|
|
|
| 1693 |
if (minBandwidthValue) {
|
| 1694 |
const value = minBandwidthValue.replace('GB/s', '');
|
| 1695 |
// For EFA (12.5GB/s), add ×4 to indicate 4 links
|
|
@@ -1710,10 +1800,11 @@
|
|
| 1710 |
const svg = getElement('aws-topology-container').querySelector('svg');
|
| 1711 |
if (!svg) return;
|
| 1712 |
|
|
|
|
| 1713 |
svg.querySelectorAll('g[data-node-type], g[data-link-type]').forEach(el => {
|
| 1714 |
el.style.opacity = '1';
|
| 1715 |
// Reset line opacity
|
| 1716 |
-
el.querySelectorAll('line').forEach(line => {
|
| 1717 |
line.style.opacity = '1';
|
| 1718 |
});
|
| 1719 |
// Reset circle opacity
|
|
@@ -1726,6 +1817,20 @@
|
|
| 1726 |
});
|
| 1727 |
});
|
| 1728 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1729 |
// Reset legend opacity
|
| 1730 |
const legendContainer = getElement('aws-topology-legend');
|
| 1731 |
if (legendContainer) {
|
|
@@ -1736,17 +1841,21 @@
|
|
| 1736 |
|
| 1737 |
// Hide bottleneck (unless real bandwidths are enabled)
|
| 1738 |
const bottleneckEl = getElement('aws-topology-bottleneck');
|
|
|
|
| 1739 |
const embedConfig = readEmbedConfig();
|
| 1740 |
const showRealBandwidths = embedConfig.showRealBandwidths;
|
| 1741 |
|
| 1742 |
if (!showRealBandwidths) {
|
|
|
|
| 1743 |
bottleneckEl.classList.remove('visible');
|
| 1744 |
} else {
|
| 1745 |
-
// When real bandwidths are enabled,
|
|
|
|
|
|
|
|
|
|
| 1746 |
const realBandwidthsEl = bottleneckEl.querySelector('.real-bandwidths');
|
| 1747 |
if (realBandwidthsEl) {
|
| 1748 |
-
realBandwidthsEl.style.display = '
|
| 1749 |
-
setupRealBandwidthsDisplay();
|
| 1750 |
}
|
| 1751 |
}
|
| 1752 |
}
|
|
@@ -1900,12 +2009,18 @@
|
|
| 1900 |
// Setup real bandwidths display if enabled
|
| 1901 |
if (embedConfig.showRealBandwidths) {
|
| 1902 |
const bottleneckEl = getElement('aws-topology-bottleneck');
|
|
|
|
| 1903 |
const realBandwidthsEl = bottleneckEl.querySelector('.real-bandwidths');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1904 |
if (realBandwidthsEl) {
|
| 1905 |
-
realBandwidthsEl.style.display = '
|
| 1906 |
-
setupRealBandwidthsDisplay();
|
| 1907 |
}
|
| 1908 |
-
|
|
|
|
| 1909 |
}
|
| 1910 |
|
| 1911 |
drawTopology();
|
|
@@ -2035,10 +2150,12 @@
|
|
| 2035 |
|
| 2036 |
// Wait for fade out to complete, then redraw
|
| 2037 |
setTimeout(() => {
|
|
|
|
|
|
|
| 2038 |
drawTopology(path.requiredEnsembles, path.requiredSystems);
|
| 2039 |
|
| 2040 |
// Highlight BEFORE fade in (while still invisible)
|
| 2041 |
-
highlightPath(path, path.label);
|
| 2042 |
|
| 2043 |
// Then fade in with highlight already applied
|
| 2044 |
requestAnimationFrame(() => {
|
|
@@ -2046,14 +2163,20 @@
|
|
| 2046 |
});
|
| 2047 |
}, 150); // Wait for CSS transition to complete
|
| 2048 |
} else {
|
|
|
|
|
|
|
| 2049 |
// No redraw needed, just highlight immediately
|
| 2050 |
-
highlightPath(path, path.label);
|
| 2051 |
}
|
| 2052 |
} else {
|
| 2053 |
// Button was active, now deactivate: reset to default (2 ensembles, 1 system)
|
| 2054 |
currentActivePathId = null; // Clear active path
|
| 2055 |
|
| 2056 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2057 |
const container = getElement('aws-topology-container');
|
| 2058 |
container.style.opacity = '0';
|
| 2059 |
|
|
@@ -2094,7 +2217,7 @@
|
|
| 2094 |
}
|
| 2095 |
|
| 2096 |
// Apply highlight immediately (before fade in)
|
| 2097 |
-
highlightPath(path, path.label);
|
| 2098 |
}
|
| 2099 |
}
|
| 2100 |
|
|
|
|
| 62 |
}
|
| 63 |
|
| 64 |
.aws-topology-container.fixed-height {
|
| 65 |
+
height: 850px;
|
| 66 |
}
|
| 67 |
|
| 68 |
.aws-topology-container svg {
|
|
|
|
| 74 |
transition: opacity 0.2s ease;
|
| 75 |
}
|
| 76 |
|
| 77 |
+
/* Add drop shadow to all links */
|
| 78 |
+
.aws-topology-container svg g[data-link-type] line,
|
| 79 |
+
.aws-topology-container svg g[data-link-type] path {
|
| 80 |
+
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.2));
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
.aws-topology-controls {
|
| 84 |
position: absolute;
|
| 85 |
bottom: 10px;
|
|
|
|
| 121 |
flex-shrink: 0;
|
| 122 |
}
|
| 123 |
|
| 124 |
+
/* Hide controls on mobile */
|
| 125 |
+
@media (max-width: 768px) {
|
| 126 |
+
.aws-topology-controls {
|
| 127 |
+
display: none;
|
| 128 |
+
}
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
.aws-topology-legend {
|
| 132 |
position: absolute;
|
| 133 |
bottom: 10px;
|
|
|
|
| 1196 |
// ============================================================================
|
| 1197 |
// DRAW SINGLE SYSTEM (variable number of ensembles)
|
| 1198 |
// ============================================================================
|
| 1199 |
+
function drawSystem(renderer, systemIndex, systemCenterX, cpuY, nvswitchY, ensembleCount = 1, systemCount = 1, drawEfaCrossLinks = false) {
|
| 1200 |
+
// For internode (2 systems), only show 1 ensemble per system for clarity
|
| 1201 |
+
const ensemblesToShow = (systemCount === 2) ? 1 : ensembleCount;
|
| 1202 |
+
|
| 1203 |
// Calculate ensemble width (4 groups)
|
| 1204 |
const ensembleWidth = CONFIG.groupCount * CONFIG.gaps.horizontal;
|
| 1205 |
|
| 1206 |
+
// Calculate system bounding box based on actual ensembles shown
|
| 1207 |
+
const systemWidth = ensemblesToShow * ensembleWidth + (ensemblesToShow - 1) * CONFIG.gaps.ensembleGap;
|
| 1208 |
const systemHeight = CONFIG.sizes.cpu + CONFIG.gaps.cpuToPcie + CONFIG.sizes.pcie.height +
|
| 1209 |
CONFIG.gaps.pcieToGpu + CONFIG.sizes.gpu.height +
|
| 1210 |
CONFIG.gaps.gpuToNvswitch + CONFIG.sizes.nvswitch.height;
|
|
|
|
| 1243 |
}
|
| 1244 |
|
| 1245 |
// Draw each ensemble in the system
|
| 1246 |
+
for (let ensIndex = 0; ensIndex < ensemblesToShow; ensIndex++) {
|
| 1247 |
const ensembleGlobalIndex = systemIndex * CONFIG.ensembleCount + ensIndex;
|
| 1248 |
|
| 1249 |
// Position ensemble within system
|
| 1250 |
+
const ensembleOffsetX = (ensIndex - (ensemblesToShow - 1) / 2) * (ensembleWidth + CONFIG.gaps.ensembleGap);
|
| 1251 |
const ensembleCenterX = systemCenterX + ensembleOffsetX;
|
| 1252 |
|
| 1253 |
drawEnsemble(renderer, ensembleGlobalIndex, ensembleCenterX, cpuY, nvswitchY);
|
|
|
|
| 1255 |
|
| 1256 |
// Draw NUMA node borders (one per ensemble) if 2 ensembles
|
| 1257 |
if (ensembleCount === 2) {
|
| 1258 |
+
for (let ensIndex = 0; ensIndex < ensemblesToShow; ensIndex++) {
|
| 1259 |
+
const ensembleOffsetX = (ensIndex - (ensemblesToShow - 1) / 2) * (ensembleWidth + CONFIG.gaps.ensembleGap);
|
| 1260 |
const ensembleCenterX = systemCenterX + ensembleOffsetX;
|
| 1261 |
|
| 1262 |
// Calculate NUMA node bounding box (same as system but for single ensemble)
|
|
|
|
| 1301 |
const offset = getLinkOffset(bw.width);
|
| 1302 |
|
| 1303 |
// Connect all GPUs in the system to all NVSwitches in the system
|
| 1304 |
+
const totalGpusInSystem = ensemblesToShow * CONFIG.groupCount;
|
| 1305 |
+
const totalNVSwitchesInSystem = ensemblesToShow * CONFIG.nvswitchCount;
|
| 1306 |
|
| 1307 |
for (let gpuIndex = 0; gpuIndex < totalGpusInSystem; gpuIndex++) {
|
| 1308 |
const gpuGlobalIndex = systemIndex * CONFIG.ensembleCount * CONFIG.groupCount + gpuIndex;
|
|
|
|
| 1314 |
}
|
| 1315 |
}
|
| 1316 |
|
| 1317 |
+
// Draw CPU-to-CPU link between ensembles (only if 2 ensembles visible)
|
| 1318 |
+
if (ensemblesToShow === 2) {
|
| 1319 |
const cpu0Id = systemIndex * CONFIG.ensembleCount === 0 ? 'cpu' : `cpu-${systemIndex * CONFIG.ensembleCount}`;
|
| 1320 |
const cpu1Id = `cpu-${systemIndex * CONFIG.ensembleCount + 1}`;
|
| 1321 |
|
|
|
|
| 1326 |
|
| 1327 |
renderer.drawLink(cpu0Id, cpu1Id, color, bw.width, 'right', 'left', offset, 0, 1, 0, 1, 'cpu', '16GB/s');
|
| 1328 |
|
| 1329 |
+
// Draw EFA-to-EFA link between ensembles (only if 2 ensembles visible and explicitly requested)
|
| 1330 |
+
if (ensemblesToShow === 2 && drawEfaCrossLinks) {
|
| 1331 |
const efaExt0Id = systemIndex * CONFIG.ensembleCount * CONFIG.groupCount === 0 ? 'efa-external' : `efa-external-${systemIndex * CONFIG.ensembleCount * CONFIG.groupCount}`;
|
| 1332 |
const efaExt1Id = `efa-external-${systemIndex * CONFIG.ensembleCount * CONFIG.groupCount + CONFIG.groupCount}`;
|
| 1333 |
|
|
|
|
| 1514 |
|
| 1515 |
// Only draw EFA cross-links for intranode EFA path
|
| 1516 |
const drawEfaCrossLinks = currentActivePathId === 'gpu-gpu-efa-intranode';
|
| 1517 |
+
drawSystem(renderer, sysIndex, centerX, cpuY, nvswitchY, ensembleCount, systemCount, drawEfaCrossLinks);
|
| 1518 |
}
|
| 1519 |
|
| 1520 |
// Draw EFA cross-link between systems (for internode)
|
|
|
|
| 1579 |
currentSystemCount = systemCount;
|
| 1580 |
}
|
| 1581 |
|
| 1582 |
+
// ============================================================================
|
| 1583 |
+
// REAL BANDWIDTH HELPERS
|
| 1584 |
+
// ============================================================================
|
| 1585 |
+
function getRealBandwidthForPath(pathId) {
|
| 1586 |
+
const pathToRealBandwidth = {
|
| 1587 |
+
'cpu-gpu': { value: '14.2', unit: 'GB/s' },
|
| 1588 |
+
'gpu-gpu-cpu': { value: '14.2', unit: 'GB/s' },
|
| 1589 |
+
'gpu-gpu-nvswitch': { value: '786', unit: 'GB/s' },
|
| 1590 |
+
'gpu-gpu-efa-intranode': { value: '480', unit: 'GB/s' },
|
| 1591 |
+
'gpu-gpu-efa-internode': { value: '42', unit: 'GB/s' },
|
| 1592 |
+
'gpu-storage': { value: '26', unit: 'GB/s' },
|
| 1593 |
+
'cpu-storage': { value: '26', unit: 'GB/s' },
|
| 1594 |
+
'gpu-cpu-storage': { value: '14.2', unit: 'GB/s' }
|
| 1595 |
+
};
|
| 1596 |
+
|
| 1597 |
+
const bandwidth = pathToRealBandwidth[pathId];
|
| 1598 |
+
if (bandwidth) {
|
| 1599 |
+
return {
|
| 1600 |
+
value: bandwidth.value,
|
| 1601 |
+
unit: bandwidth.unit
|
| 1602 |
+
};
|
| 1603 |
+
}
|
| 1604 |
+
return null;
|
| 1605 |
+
}
|
| 1606 |
+
|
| 1607 |
// ============================================================================
|
| 1608 |
// HIGHLIGHT HELPERS
|
| 1609 |
// ============================================================================
|
| 1610 |
+
function highlightPath(path, pathLabel = '', pathId = '') {
|
| 1611 |
const svg = getElement('aws-topology-container').querySelector('svg');
|
| 1612 |
if (!svg) return;
|
| 1613 |
|
|
|
|
| 1628 |
});
|
| 1629 |
});
|
| 1630 |
|
| 1631 |
+
// Dim all cross-link elements (EFA internode/intranode links)
|
| 1632 |
+
svg.querySelectorAll('g[data-link-type="efa-crosslink"], g[data-link-type="efa-crosslink-internode"]').forEach(el => {
|
| 1633 |
+
el.style.opacity = '0.5';
|
| 1634 |
+
el.querySelectorAll('line, path').forEach(linkElement => {
|
| 1635 |
+
linkElement.style.opacity = '0.2';
|
| 1636 |
+
});
|
| 1637 |
+
el.querySelectorAll('[data-link-circle]').forEach(circle => {
|
| 1638 |
+
circle.style.opacity = '0';
|
| 1639 |
+
});
|
| 1640 |
+
el.querySelectorAll('text').forEach(text => {
|
| 1641 |
+
text.style.opacity = '0.15';
|
| 1642 |
+
});
|
| 1643 |
+
});
|
| 1644 |
+
|
| 1645 |
// Highlight path nodes
|
| 1646 |
path.nodes.forEach(nodeId => {
|
| 1647 |
let nodeEl = svg.querySelector(`g[id="${nodeId}"]`);
|
|
|
|
| 1685 |
});
|
| 1686 |
});
|
| 1687 |
|
| 1688 |
+
// Highlight cross-link elements if they match the current path
|
| 1689 |
+
const currentPathId = currentActivePathId;
|
| 1690 |
+
if (currentPathId === 'gpu-gpu-efa-intranode' || currentPathId === 'gpu-gpu-efa-internode') {
|
| 1691 |
+
svg.querySelectorAll('g[data-link-type="efa-crosslink"], g[data-link-type="efa-crosslink-internode"]').forEach(linkGroup => {
|
| 1692 |
+
linkGroup.style.opacity = '1';
|
| 1693 |
+
linkGroup.querySelectorAll('line, path').forEach(linkElement => {
|
| 1694 |
+
linkElement.style.opacity = '1';
|
| 1695 |
+
});
|
| 1696 |
+
linkGroup.querySelectorAll('[data-link-circle]').forEach(circle => {
|
| 1697 |
+
circle.style.opacity = '1';
|
| 1698 |
+
});
|
| 1699 |
+
linkGroup.querySelectorAll('text').forEach(text => {
|
| 1700 |
+
text.style.opacity = '1';
|
| 1701 |
+
});
|
| 1702 |
+
});
|
| 1703 |
+
}
|
| 1704 |
+
|
| 1705 |
// Calculate and show bottleneck (minimum bandwidth in the path)
|
| 1706 |
let minBandwidth = Infinity;
|
| 1707 |
let minBandwidthValue = null;
|
|
|
|
| 1750 |
const bottleneckEl = getElement('aws-topology-bottleneck');
|
| 1751 |
const bottleneckValueEl = bottleneckEl.querySelector('.bottleneck-value');
|
| 1752 |
const bottleneckPathEl = bottleneckEl.querySelector('.bottleneck-path');
|
| 1753 |
+
const bottleneckLabelEl = bottleneckEl.querySelector('.bottleneck-label');
|
| 1754 |
const realBandwidthsEl = bottleneckEl.querySelector('.real-bandwidths');
|
| 1755 |
|
| 1756 |
// Check if real bandwidths are enabled
|
|
|
|
| 1758 |
const showRealBandwidths = embedConfig.showRealBandwidths;
|
| 1759 |
|
| 1760 |
if (showRealBandwidths) {
|
| 1761 |
+
// When real bandwidths are shown, display real bandwidth value directly
|
| 1762 |
+
const realBandwidth = getRealBandwidthForPath(pathId);
|
| 1763 |
+
if (realBandwidth) {
|
| 1764 |
+
bottleneckValueEl.textContent = realBandwidth.value;
|
| 1765 |
+
bottleneckPathEl.textContent = `for ${pathLabel}`;
|
| 1766 |
+
bottleneckLabelEl.textContent = 'Real Bandwidth';
|
| 1767 |
+
bottleneckEl.classList.add('visible');
|
| 1768 |
+
} else {
|
| 1769 |
+
// Fallback if no real bandwidth found
|
| 1770 |
+
bottleneckValueEl.textContent = '?';
|
| 1771 |
+
bottleneckPathEl.textContent = `for ${pathLabel}`;
|
| 1772 |
+
bottleneckLabelEl.textContent = 'Real Bandwidth';
|
| 1773 |
+
bottleneckEl.classList.add('visible');
|
| 1774 |
+
}
|
| 1775 |
+
// Hide the detailed real bandwidths list
|
| 1776 |
+
const realBandwidthsEl = bottleneckEl.querySelector('.real-bandwidths');
|
| 1777 |
+
if (realBandwidthsEl) {
|
| 1778 |
+
realBandwidthsEl.style.display = 'none';
|
| 1779 |
+
}
|
| 1780 |
} else {
|
| 1781 |
// Normal bottleneck display
|
| 1782 |
+
bottleneckLabelEl.textContent = 'Bandwidth Max';
|
| 1783 |
if (minBandwidthValue) {
|
| 1784 |
const value = minBandwidthValue.replace('GB/s', '');
|
| 1785 |
// For EFA (12.5GB/s), add ×4 to indicate 4 links
|
|
|
|
| 1800 |
const svg = getElement('aws-topology-container').querySelector('svg');
|
| 1801 |
if (!svg) return;
|
| 1802 |
|
| 1803 |
+
// Reset all node and link elements
|
| 1804 |
svg.querySelectorAll('g[data-node-type], g[data-link-type]').forEach(el => {
|
| 1805 |
el.style.opacity = '1';
|
| 1806 |
// Reset line opacity
|
| 1807 |
+
el.querySelectorAll('line, path').forEach(line => {
|
| 1808 |
line.style.opacity = '1';
|
| 1809 |
});
|
| 1810 |
// Reset circle opacity
|
|
|
|
| 1817 |
});
|
| 1818 |
});
|
| 1819 |
|
| 1820 |
+
// Reset all cross-link elements (EFA internode/intranode links)
|
| 1821 |
+
svg.querySelectorAll('g[data-link-type="efa-crosslink"], g[data-link-type="efa-crosslink-internode"]').forEach(el => {
|
| 1822 |
+
el.style.opacity = '1';
|
| 1823 |
+
el.querySelectorAll('line, path').forEach(line => {
|
| 1824 |
+
line.style.opacity = '1';
|
| 1825 |
+
});
|
| 1826 |
+
el.querySelectorAll('[data-link-circle]').forEach(circle => {
|
| 1827 |
+
circle.style.opacity = '1';
|
| 1828 |
+
});
|
| 1829 |
+
});
|
| 1830 |
+
|
| 1831 |
+
// Clear current active path to ensure EFA cross-links are not drawn
|
| 1832 |
+
currentActivePathId = null;
|
| 1833 |
+
|
| 1834 |
// Reset legend opacity
|
| 1835 |
const legendContainer = getElement('aws-topology-legend');
|
| 1836 |
if (legendContainer) {
|
|
|
|
| 1841 |
|
| 1842 |
// Hide bottleneck (unless real bandwidths are enabled)
|
| 1843 |
const bottleneckEl = getElement('aws-topology-bottleneck');
|
| 1844 |
+
const bottleneckLabelEl = bottleneckEl.querySelector('.bottleneck-label');
|
| 1845 |
const embedConfig = readEmbedConfig();
|
| 1846 |
const showRealBandwidths = embedConfig.showRealBandwidths;
|
| 1847 |
|
| 1848 |
if (!showRealBandwidths) {
|
| 1849 |
+
bottleneckLabelEl.textContent = 'Bandwidth Max';
|
| 1850 |
bottleneckEl.classList.remove('visible');
|
| 1851 |
} else {
|
| 1852 |
+
// When real bandwidths are enabled, hide the module when no path is active
|
| 1853 |
+
bottleneckLabelEl.textContent = 'Real Bandwidth';
|
| 1854 |
+
bottleneckEl.classList.remove('visible');
|
| 1855 |
+
// Hide the detailed real bandwidths list
|
| 1856 |
const realBandwidthsEl = bottleneckEl.querySelector('.real-bandwidths');
|
| 1857 |
if (realBandwidthsEl) {
|
| 1858 |
+
realBandwidthsEl.style.display = 'none';
|
|
|
|
| 1859 |
}
|
| 1860 |
}
|
| 1861 |
}
|
|
|
|
| 2009 |
// Setup real bandwidths display if enabled
|
| 2010 |
if (embedConfig.showRealBandwidths) {
|
| 2011 |
const bottleneckEl = getElement('aws-topology-bottleneck');
|
| 2012 |
+
const bottleneckLabelEl = bottleneckEl.querySelector('.bottleneck-label');
|
| 2013 |
const realBandwidthsEl = bottleneckEl.querySelector('.real-bandwidths');
|
| 2014 |
+
|
| 2015 |
+
// Change label to "Real Bandwidth"
|
| 2016 |
+
bottleneckLabelEl.textContent = 'Real Bandwidth';
|
| 2017 |
+
|
| 2018 |
+
// Hide the detailed real bandwidths list initially
|
| 2019 |
if (realBandwidthsEl) {
|
| 2020 |
+
realBandwidthsEl.style.display = 'none';
|
|
|
|
| 2021 |
}
|
| 2022 |
+
// Don't show the module initially - only when a path is selected
|
| 2023 |
+
bottleneckEl.classList.remove('visible');
|
| 2024 |
}
|
| 2025 |
|
| 2026 |
drawTopology();
|
|
|
|
| 2150 |
|
| 2151 |
// Wait for fade out to complete, then redraw
|
| 2152 |
setTimeout(() => {
|
| 2153 |
+
// Set active path BEFORE drawing topology so EFA cross-links are created
|
| 2154 |
+
currentActivePathId = pathId;
|
| 2155 |
drawTopology(path.requiredEnsembles, path.requiredSystems);
|
| 2156 |
|
| 2157 |
// Highlight BEFORE fade in (while still invisible)
|
| 2158 |
+
highlightPath(path, path.label, pathId);
|
| 2159 |
|
| 2160 |
// Then fade in with highlight already applied
|
| 2161 |
requestAnimationFrame(() => {
|
|
|
|
| 2163 |
});
|
| 2164 |
}, 150); // Wait for CSS transition to complete
|
| 2165 |
} else {
|
| 2166 |
+
// Set active path for EFA cross-links even without redraw
|
| 2167 |
+
currentActivePathId = pathId;
|
| 2168 |
// No redraw needed, just highlight immediately
|
| 2169 |
+
highlightPath(path, path.label, pathId);
|
| 2170 |
}
|
| 2171 |
} else {
|
| 2172 |
// Button was active, now deactivate: reset to default (2 ensembles, 1 system)
|
| 2173 |
currentActivePathId = null; // Clear active path
|
| 2174 |
|
| 2175 |
+
// Always redraw when deactivating EFA paths to remove cross-links
|
| 2176 |
+
const isEfaPath = pathId === 'gpu-gpu-efa-intranode' || pathId === 'gpu-gpu-efa-internode';
|
| 2177 |
+
const needsRedraw = currentEnsembleCount !== 2 || currentSystemCount !== 1 || isEfaPath;
|
| 2178 |
+
|
| 2179 |
+
if (needsRedraw) {
|
| 2180 |
const container = getElement('aws-topology-container');
|
| 2181 |
container.style.opacity = '0';
|
| 2182 |
|
|
|
|
| 2217 |
}
|
| 2218 |
|
| 2219 |
// Apply highlight immediately (before fade in)
|
| 2220 |
+
highlightPath(path, path.label, initialPathId);
|
| 2221 |
}
|
| 2222 |
}
|
| 2223 |
|
app/src/content/embeds/data-packing.html
CHANGED
|
@@ -3,37 +3,52 @@
|
|
| 3 |
.d3-data-packing {
|
| 4 |
font-family: 'Arial', sans-serif;
|
| 5 |
margin: 0;
|
| 6 |
-
padding: 20px;
|
| 7 |
-
background-color: #f5f5f5;
|
| 8 |
}
|
| 9 |
|
| 10 |
.d3-data-packing .container {
|
| 11 |
max-width: 1000px;
|
| 12 |
margin: 0 auto;
|
| 13 |
-
background: white;
|
| 14 |
border-radius: 10px;
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
}
|
| 18 |
|
| 19 |
.d3-data-packing .section {
|
| 20 |
-
|
|
|
|
| 21 |
}
|
| 22 |
|
| 23 |
.d3-data-packing .section-title {
|
| 24 |
-
font-size:
|
| 25 |
font-weight: bold;
|
| 26 |
-
|
|
|
|
| 27 |
text-align: center;
|
| 28 |
-
|
|
|
|
| 29 |
}
|
| 30 |
|
| 31 |
.d3-data-packing .dataset {
|
| 32 |
display: flex;
|
| 33 |
-
flex-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
gap: 3px;
|
| 35 |
justify-content: center;
|
| 36 |
-
|
| 37 |
}
|
| 38 |
|
| 39 |
.d3-data-packing .grid {
|
|
@@ -46,7 +61,7 @@
|
|
| 46 |
.d3-data-packing .block {
|
| 47 |
width: 30px;
|
| 48 |
height: 30px;
|
| 49 |
-
border:
|
| 50 |
border-radius: 4px;
|
| 51 |
display: flex;
|
| 52 |
align-items: center;
|
|
@@ -54,39 +69,42 @@
|
|
| 54 |
font-size: 10px;
|
| 55 |
font-weight: bold;
|
| 56 |
color: white;
|
| 57 |
-
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
| 58 |
}
|
| 59 |
|
| 60 |
.d3-data-packing .red {
|
| 61 |
-
background-color:
|
| 62 |
}
|
| 63 |
|
| 64 |
.d3-data-packing .orange {
|
| 65 |
-
background-color:
|
| 66 |
}
|
| 67 |
|
| 68 |
.d3-data-packing .yellow {
|
| 69 |
-
background-color:
|
| 70 |
}
|
| 71 |
|
| 72 |
.d3-data-packing .green {
|
| 73 |
-
background-color:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
}
|
| 75 |
|
| 76 |
.d3-data-packing .lightblue {
|
| 77 |
-
background-color:
|
| 78 |
}
|
| 79 |
|
| 80 |
.d3-data-packing .blue {
|
| 81 |
-
background-color:
|
| 82 |
}
|
| 83 |
|
| 84 |
.d3-data-packing .purple {
|
| 85 |
-
background-color:
|
| 86 |
}
|
| 87 |
|
| 88 |
.d3-data-packing .pink {
|
| 89 |
-
background-color:
|
| 90 |
}
|
| 91 |
|
| 92 |
.d3-data-packing .gray {
|
|
@@ -94,36 +112,17 @@
|
|
| 94 |
}
|
| 95 |
|
| 96 |
.d3-data-packing .packing-false {
|
|
|
|
| 97 |
grid-template-columns: repeat(7, 1fr);
|
|
|
|
|
|
|
| 98 |
}
|
| 99 |
|
| 100 |
.d3-data-packing .packing-true {
|
|
|
|
| 101 |
grid-template-columns: repeat(7, 1fr);
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
.d3-data-packing .description {
|
| 105 |
-
text-align: center;
|
| 106 |
-
margin-top: 15px;
|
| 107 |
-
color: #666;
|
| 108 |
-
font-size: 14px;
|
| 109 |
-
}
|
| 110 |
-
|
| 111 |
-
.d3-data-packing .efficiency {
|
| 112 |
-
background: #ecf0f1;
|
| 113 |
-
padding: 15px;
|
| 114 |
-
border-radius: 8px;
|
| 115 |
-
margin-top: 20px;
|
| 116 |
-
text-align: center;
|
| 117 |
-
}
|
| 118 |
-
|
| 119 |
-
.d3-data-packing .efficiency h3 {
|
| 120 |
-
margin: 0 0 10px 0;
|
| 121 |
-
color: #2c3e50;
|
| 122 |
-
}
|
| 123 |
-
|
| 124 |
-
.d3-data-packing .efficiency p {
|
| 125 |
-
margin: 5px 0;
|
| 126 |
-
color: #34495e;
|
| 127 |
}
|
| 128 |
</style>
|
| 129 |
<script>
|
|
@@ -142,79 +141,121 @@
|
|
| 142 |
container.dataset.mounted = 'true';
|
| 143 |
}
|
| 144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
// Create the HTML structure
|
| 146 |
container.innerHTML = `
|
| 147 |
<div class="container">
|
| 148 |
-
<div class="
|
| 149 |
-
<
|
| 150 |
-
|
| 151 |
-
<
|
| 152 |
-
|
| 153 |
-
<
|
| 154 |
-
<div class="block orange">O</div><div class="block orange">O</div><div class="block orange">O</div>
|
| 155 |
-
<!-- 4 yellow blocks -->
|
| 156 |
-
<div class="block yellow">Y</div><div class="block yellow">Y</div><div class="block yellow">Y</div><div class="block yellow">Y</div>
|
| 157 |
-
<!-- 7 green blocks -->
|
| 158 |
-
<div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div>
|
| 159 |
-
<!-- 10 light blue blocks -->
|
| 160 |
-
<div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div>
|
| 161 |
-
<!-- 3 blue blocks -->
|
| 162 |
-
<div class="block blue">B</div><div class="block blue">B</div><div class="block blue">B</div>
|
| 163 |
-
<!-- 5 purple blocks -->
|
| 164 |
-
<div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div>
|
| 165 |
-
<!-- 3 pink blocks -->
|
| 166 |
-
<div class="block pink">K</div><div class="block pink">K</div><div class="block pink">K</div>
|
| 167 |
</div>
|
| 168 |
-
<div class="description">42 unorganized data blocks</div>
|
| 169 |
-
</div>
|
| 170 |
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
<
|
| 176 |
-
<!-- Row 2: 3 orange + 4 gray -->
|
| 177 |
-
<div class="block orange">O</div><div class="block orange">O</div><div class="block orange">O</div><div class="block gray">-</div><div class="block gray">-</div><div class="block gray">-</div><div class="block gray">-</div>
|
| 178 |
-
<!-- Row 3: 4 yellow + 3 gray -->
|
| 179 |
-
<div class="block yellow">Y</div><div class="block yellow">Y</div><div class="block yellow">Y</div><div class="block yellow">Y</div><div class="block gray">-</div><div class="block gray">-</div><div class="block gray">-</div>
|
| 180 |
-
<!-- Row 4: 7 green -->
|
| 181 |
-
<div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div>
|
| 182 |
-
<!-- Row 5: 7 light blue -->
|
| 183 |
-
<div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div>
|
| 184 |
-
<!-- Row 6: 3 light blue + 4 gray -->
|
| 185 |
-
<div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block lightblue">L</div><div class="block gray">-</div><div class="block gray">-</div><div class="block gray">-</div><div class="block gray">-</div>
|
| 186 |
-
<!-- Row 7: 3 blue + 4 gray -->
|
| 187 |
-
<div class="block blue">B</div><div class="block blue">B</div><div class="block blue">B</div><div class="block gray">-</div><div class="block gray">-</div><div class="block gray">-</div><div class="block gray">-</div>
|
| 188 |
-
<!-- Row 8: 5 purple + 2 gray -->
|
| 189 |
-
<div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div><div class="block gray">-</div><div class="block gray">-</div>
|
| 190 |
</div>
|
| 191 |
-
<div class="description">Sequential placement with wasted space (17 empty cells)</div>
|
| 192 |
-
</div>
|
| 193 |
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
<
|
| 199 |
-
<!-- Row 2: 7 pink -->
|
| 200 |
-
<div class="block pink">K</div><div class="block pink">K</div><div class="block pink">K</div><div class="block pink">K</div><div class="block pink">K</div><div class="block pink">K</div><div class="block pink">K</div>
|
| 201 |
-
<!-- Row 3: 7 red -->
|
| 202 |
-
<div class="block red">R</div><div class="block red">R</div><div class="block red">R</div><div class="block red">R</div><div class="block red">R</div><div class="block red">R</div><div class="block red">R</div>
|
| 203 |
-
<!-- Row 4: 7 green -->
|
| 204 |
-
<div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div><div class="block green">G</div>
|
| 205 |
-
<!-- Row 5: 7 purple -->
|
| 206 |
-
<div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div><div class="block purple">P</div>
|
| 207 |
-
<!-- Row 6: 4 yellow + 3 orange -->
|
| 208 |
-
<div class="block yellow">Y</div><div class="block yellow">Y</div><div class="block yellow">Y</div><div class="block yellow">Y</div><div class="block orange">O</div><div class="block orange">O</div><div class="block orange">O</div>
|
| 209 |
</div>
|
| 210 |
-
<div class="description">Complete optimization with no wasted space (0 empty cells)</div>
|
| 211 |
-
</div>
|
| 212 |
-
|
| 213 |
-
<div class="efficiency">
|
| 214 |
-
<h3>Packing Efficiency</h3>
|
| 215 |
-
<p><strong>packing=False:</strong> 39 blocks used / 56 cells = 69.6% efficiency</p>
|
| 216 |
-
<p><strong>packing=True:</strong> 42 blocks used / 42 cells = 100% efficiency</p>
|
| 217 |
-
<p><strong>Gain:</strong> +30.4% efficiency and 14 cells saved</p>
|
| 218 |
</div>
|
| 219 |
</div>
|
| 220 |
`;
|
|
|
|
| 3 |
.d3-data-packing {
|
| 4 |
font-family: 'Arial', sans-serif;
|
| 5 |
margin: 0;
|
|
|
|
|
|
|
| 6 |
}
|
| 7 |
|
| 8 |
.d3-data-packing .container {
|
| 9 |
max-width: 1000px;
|
| 10 |
margin: 0 auto;
|
|
|
|
| 11 |
border-radius: 10px;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
.d3-data-packing .sections-container {
|
| 15 |
+
display: flex;
|
| 16 |
+
gap: 20px;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
@media (max-width: 768px) {
|
| 20 |
+
.d3-data-packing .sections-container {
|
| 21 |
+
flex-direction: column;
|
| 22 |
+
gap: 30px;
|
| 23 |
+
}
|
| 24 |
}
|
| 25 |
|
| 26 |
.d3-data-packing .section {
|
| 27 |
+
flex: 1;
|
| 28 |
+
margin-bottom: 0;
|
| 29 |
}
|
| 30 |
|
| 31 |
.d3-data-packing .section-title {
|
| 32 |
+
font-size: 16px;
|
| 33 |
font-weight: bold;
|
| 34 |
+
color: var(--text-color, #333);
|
| 35 |
+
margin: 0 auto 20px auto;
|
| 36 |
text-align: center;
|
| 37 |
+
width: 100%;
|
| 38 |
+
display: block;
|
| 39 |
}
|
| 40 |
|
| 41 |
.d3-data-packing .dataset {
|
| 42 |
display: flex;
|
| 43 |
+
flex-direction: column;
|
| 44 |
+
gap: 3px;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
.d3-data-packing .dataset-row {
|
| 48 |
+
display: flex;
|
| 49 |
gap: 3px;
|
| 50 |
justify-content: center;
|
| 51 |
+
flex-wrap: wrap;
|
| 52 |
}
|
| 53 |
|
| 54 |
.d3-data-packing .grid {
|
|
|
|
| 61 |
.d3-data-packing .block {
|
| 62 |
width: 30px;
|
| 63 |
height: 30px;
|
| 64 |
+
border: none;
|
| 65 |
border-radius: 4px;
|
| 66 |
display: flex;
|
| 67 |
align-items: center;
|
|
|
|
| 69 |
font-size: 10px;
|
| 70 |
font-weight: bold;
|
| 71 |
color: white;
|
|
|
|
| 72 |
}
|
| 73 |
|
| 74 |
.d3-data-packing .red {
|
| 75 |
+
background-color: var(--color-0);
|
| 76 |
}
|
| 77 |
|
| 78 |
.d3-data-packing .orange {
|
| 79 |
+
background-color: var(--color-1);
|
| 80 |
}
|
| 81 |
|
| 82 |
.d3-data-packing .yellow {
|
| 83 |
+
background-color: var(--color-2);
|
| 84 |
}
|
| 85 |
|
| 86 |
.d3-data-packing .green {
|
| 87 |
+
background-color: var(--color-3);
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
.d3-data-packing .lightgreen {
|
| 91 |
+
background-color: var(--color-4);
|
| 92 |
}
|
| 93 |
|
| 94 |
.d3-data-packing .lightblue {
|
| 95 |
+
background-color: var(--color-5);
|
| 96 |
}
|
| 97 |
|
| 98 |
.d3-data-packing .blue {
|
| 99 |
+
background-color: var(--color-6);
|
| 100 |
}
|
| 101 |
|
| 102 |
.d3-data-packing .purple {
|
| 103 |
+
background-color: var(--color-7);
|
| 104 |
}
|
| 105 |
|
| 106 |
.d3-data-packing .pink {
|
| 107 |
+
background-color: var(--color-8);
|
| 108 |
}
|
| 109 |
|
| 110 |
.d3-data-packing .gray {
|
|
|
|
| 112 |
}
|
| 113 |
|
| 114 |
.d3-data-packing .packing-false {
|
| 115 |
+
display: grid;
|
| 116 |
grid-template-columns: repeat(7, 1fr);
|
| 117 |
+
gap: 3px;
|
| 118 |
+
max-width: calc(7 * 30px + 6 * 3px);
|
| 119 |
}
|
| 120 |
|
| 121 |
.d3-data-packing .packing-true {
|
| 122 |
+
display: grid;
|
| 123 |
grid-template-columns: repeat(7, 1fr);
|
| 124 |
+
gap: 3px;
|
| 125 |
+
max-width: calc(7 * 30px + 6 * 3px);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
}
|
| 127 |
</style>
|
| 128 |
<script>
|
|
|
|
| 141 |
container.dataset.mounted = 'true';
|
| 142 |
}
|
| 143 |
|
| 144 |
+
// Apply categorical color palette
|
| 145 |
+
const applyColorPalette = () => {
|
| 146 |
+
try {
|
| 147 |
+
if (window.ColorPalettes && typeof window.ColorPalettes.getColors === 'function') {
|
| 148 |
+
const colors = window.ColorPalettes.getColors('categorical', 9);
|
| 149 |
+
colors.forEach((color, index) => {
|
| 150 |
+
document.documentElement.style.setProperty(`--color-${index}`, color);
|
| 151 |
+
});
|
| 152 |
+
} else {
|
| 153 |
+
// Fallback to CSS variables or default colors
|
| 154 |
+
const fallbackColors = [
|
| 155 |
+
'var(--primary-color, #E889AB)',
|
| 156 |
+
'#4EA5B7', '#E38A42', '#CEC0FA', '#9B59B6',
|
| 157 |
+
'#16A085', '#1f77b4', '#ff7f0e', '#2ca02c'
|
| 158 |
+
];
|
| 159 |
+
fallbackColors.forEach((color, index) => {
|
| 160 |
+
document.documentElement.style.setProperty(`--color-${index}`, color);
|
| 161 |
+
});
|
| 162 |
+
}
|
| 163 |
+
} catch (e) {
|
| 164 |
+
console.warn('ColorPalettes not available, using fallback colors');
|
| 165 |
+
}
|
| 166 |
+
};
|
| 167 |
+
|
| 168 |
+
// Apply colors immediately and on theme changes
|
| 169 |
+
applyColorPalette();
|
| 170 |
+
if (window.ColorPalettes && typeof window.ColorPalettes.refresh === 'function') {
|
| 171 |
+
window.ColorPalettes.refresh();
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
// Data structure - only colored blocks, no gray blocks
|
| 175 |
+
const dataset = [
|
| 176 |
+
{ color: 'red', count: 7, label: 'R' },
|
| 177 |
+
{ color: 'orange', count: 3, label: 'O' },
|
| 178 |
+
{ color: 'yellow', count: 4, label: 'Y' },
|
| 179 |
+
{ color: 'lightgreen', count: 6, label: 'G' },
|
| 180 |
+
{ color: 'lightblue', count: 12, label: 'L' },
|
| 181 |
+
{ color: 'purple', count: 6, label: 'P' },
|
| 182 |
+
{ color: 'pink', count: 4, label: 'K' }
|
| 183 |
+
];
|
| 184 |
+
|
| 185 |
+
const packingFalse = [
|
| 186 |
+
{ color: 'red', count: 7, label: 'R' },
|
| 187 |
+
{ color: 'orange', count: 3, label: 'O' },
|
| 188 |
+
{ color: 'gray', count: 4, label: '-' },
|
| 189 |
+
{ color: 'yellow', count: 4, label: 'Y' },
|
| 190 |
+
{ color: 'gray', count: 3, label: '-' },
|
| 191 |
+
{ color: 'lightgreen', count: 6, label: 'G' },
|
| 192 |
+
{ color: 'gray', count: 1, label: '-' },
|
| 193 |
+
{ color: 'lightblue', count: 7, label: 'L' },
|
| 194 |
+
{ color: 'lightblue', count: 3, label: 'L' },
|
| 195 |
+
{ color: 'gray', count: 4, label: '-' },
|
| 196 |
+
{ color: 'purple', count: 6, label: 'P' },
|
| 197 |
+
{ color: 'gray', count: 1, label: '-' },
|
| 198 |
+
{ color: 'pink', count: 4, label: 'K' },
|
| 199 |
+
{ color: 'gray', count: 3, label: '-' }
|
| 200 |
+
];
|
| 201 |
+
|
| 202 |
+
const packingTrue = [
|
| 203 |
+
// Ligne 1: 7 R
|
| 204 |
+
{ color: 'red', count: 7, label: 'R' },
|
| 205 |
+
// Ligne 2: 3 O + 4 Y (combinaison optimisée)
|
| 206 |
+
{ color: 'orange', count: 3, label: 'O' },
|
| 207 |
+
{ color: 'yellow', count: 4, label: 'Y' },
|
| 208 |
+
// Ligne 3: 6 G + 1 gris
|
| 209 |
+
{ color: 'lightgreen', count: 6, label: 'G' },
|
| 210 |
+
{ color: 'gray', count: 1, label: '-' },
|
| 211 |
+
// Ligne 4: 7 L (rangée complète)
|
| 212 |
+
{ color: 'lightblue', count: 7, label: 'L' },
|
| 213 |
+
// Ligne 5: 3 L + 4 K (combinaison optimisée)
|
| 214 |
+
{ color: 'lightblue', count: 3, label: 'L' },
|
| 215 |
+
{ color: 'pink', count: 4, label: 'K' },
|
| 216 |
+
// Ligne 6: 6 P + 1 gris
|
| 217 |
+
{ color: 'purple', count: 6, label: 'P' },
|
| 218 |
+
{ color: 'gray', count: 1, label: '-' }
|
| 219 |
+
];
|
| 220 |
+
|
| 221 |
+
// Helper function to create blocks
|
| 222 |
+
const createBlocks = (blocks) => {
|
| 223 |
+
return blocks.map(block =>
|
| 224 |
+
block.count > 0 ? `<div class="block ${block.color}"></div>`.repeat(block.count) : ''
|
| 225 |
+
).join('');
|
| 226 |
+
};
|
| 227 |
+
|
| 228 |
+
// Helper function to create dataset rows
|
| 229 |
+
const createDatasetRows = (dataset) => {
|
| 230 |
+
return dataset.map(item =>
|
| 231 |
+
`<div class="dataset-row">${createBlocks([item])}</div>`
|
| 232 |
+
).join('');
|
| 233 |
+
};
|
| 234 |
+
|
| 235 |
// Create the HTML structure
|
| 236 |
container.innerHTML = `
|
| 237 |
<div class="container">
|
| 238 |
+
<div class="sections-container">
|
| 239 |
+
<div class="section">
|
| 240 |
+
<label class="section-title">Dataset</label>
|
| 241 |
+
<div class="dataset">
|
| 242 |
+
${createDatasetRows(dataset)}
|
| 243 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 244 |
</div>
|
|
|
|
|
|
|
| 245 |
|
| 246 |
+
<div class="section">
|
| 247 |
+
<label class="section-title">packing=False</label>
|
| 248 |
+
<div class="grid packing-false">
|
| 249 |
+
${createBlocks(packingFalse)}
|
| 250 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
</div>
|
|
|
|
|
|
|
| 252 |
|
| 253 |
+
<div class="section">
|
| 254 |
+
<label class="section-title">packing=True</label>
|
| 255 |
+
<div class="grid packing-true">
|
| 256 |
+
${createBlocks(packingTrue)}
|
| 257 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
</div>
|
| 260 |
</div>
|
| 261 |
`;
|
app/src/content/embeds/input-labels-training.html
CHANGED
|
@@ -1,60 +1,66 @@
|
|
| 1 |
<div class="d3-input-labels"></div>
|
| 2 |
<style>
|
| 3 |
.d3-input-labels {
|
| 4 |
-
font-family: 'Arial', sans-serif;
|
| 5 |
margin: 0;
|
| 6 |
-
padding:
|
| 7 |
-
background-color: #f5f5f5;
|
| 8 |
}
|
| 9 |
|
| 10 |
.d3-input-labels .container {
|
| 11 |
-
max-width:
|
| 12 |
margin: 0 auto;
|
| 13 |
-
background: white;
|
| 14 |
border-radius: 10px;
|
| 15 |
-
padding: 30px;
|
| 16 |
-
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
| 17 |
}
|
| 18 |
|
| 19 |
-
.d3-input-labels .
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
color: #2c3e50;
|
| 25 |
}
|
| 26 |
|
| 27 |
-
.d3-input-labels .
|
| 28 |
display: flex;
|
| 29 |
flex-direction: column;
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
margin-bottom: 30px;
|
| 32 |
}
|
| 33 |
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
}
|
| 39 |
|
| 40 |
-
.d3-input-labels .
|
| 41 |
-
font-size:
|
| 42 |
font-weight: bold;
|
| 43 |
-
|
| 44 |
-
|
|
|
|
| 45 |
}
|
| 46 |
|
| 47 |
-
.d3-input-labels .tokens-
|
| 48 |
display: flex;
|
| 49 |
-
flex-wrap: wrap;
|
| 50 |
gap: 3px;
|
|
|
|
|
|
|
| 51 |
flex: 1;
|
| 52 |
}
|
| 53 |
|
| 54 |
.d3-input-labels .token {
|
| 55 |
-
width:
|
| 56 |
-
height:
|
| 57 |
-
border:
|
| 58 |
border-radius: 4px;
|
| 59 |
display: flex;
|
| 60 |
align-items: center;
|
|
@@ -62,28 +68,28 @@
|
|
| 62 |
font-size: 10px;
|
| 63 |
font-weight: bold;
|
| 64 |
color: white;
|
| 65 |
-
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
| 66 |
position: relative;
|
| 67 |
}
|
| 68 |
|
| 69 |
.d3-input-labels .user-token {
|
| 70 |
-
background-color:
|
| 71 |
}
|
| 72 |
|
| 73 |
.d3-input-labels .assistant-token {
|
| 74 |
-
background-color:
|
| 75 |
}
|
| 76 |
|
| 77 |
.d3-input-labels .label-token {
|
| 78 |
-
background-color:
|
| 79 |
}
|
| 80 |
|
| 81 |
.d3-input-labels .label-masked {
|
| 82 |
background: repeating-linear-gradient(45deg,
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
|
|
|
| 87 |
}
|
| 88 |
|
| 89 |
.d3-input-labels .turn-label {
|
|
@@ -91,68 +97,21 @@
|
|
| 91 |
top: -25px;
|
| 92 |
left: 50%;
|
| 93 |
transform: translateX(-50%);
|
| 94 |
-
font-size:
|
| 95 |
font-weight: bold;
|
| 96 |
-
color: #
|
| 97 |
-
background:
|
| 98 |
-
padding: 2px
|
| 99 |
-
|
| 100 |
-
border:
|
| 101 |
}
|
| 102 |
|
| 103 |
.d3-input-labels .user-label {
|
| 104 |
-
color:
|
| 105 |
}
|
| 106 |
|
| 107 |
.d3-input-labels .assistant-label {
|
| 108 |
-
color:
|
| 109 |
-
}
|
| 110 |
-
|
| 111 |
-
.d3-input-labels .explanation {
|
| 112 |
-
background: #ecf0f1;
|
| 113 |
-
padding: 20px;
|
| 114 |
-
border-radius: 8px;
|
| 115 |
-
margin-top: 20px;
|
| 116 |
-
}
|
| 117 |
-
|
| 118 |
-
.d3-input-labels .explanation h3 {
|
| 119 |
-
margin: 0 0 15px 0;
|
| 120 |
-
color: #2c3e50;
|
| 121 |
-
}
|
| 122 |
-
|
| 123 |
-
.d3-input-labels .explanation p {
|
| 124 |
-
margin: 8px 0;
|
| 125 |
-
color: #34495e;
|
| 126 |
-
line-height: 1.5;
|
| 127 |
-
}
|
| 128 |
-
|
| 129 |
-
.d3-input-labels .legend {
|
| 130 |
-
display: flex;
|
| 131 |
-
justify-content: center;
|
| 132 |
-
gap: 30px;
|
| 133 |
-
margin: 20px 0;
|
| 134 |
-
flex-wrap: wrap;
|
| 135 |
-
}
|
| 136 |
-
|
| 137 |
-
.d3-input-labels .legend-item {
|
| 138 |
-
display: flex;
|
| 139 |
-
align-items: center;
|
| 140 |
-
gap: 8px;
|
| 141 |
-
}
|
| 142 |
-
|
| 143 |
-
.d3-input-labels .legend-color {
|
| 144 |
-
width: 20px;
|
| 145 |
-
height: 20px;
|
| 146 |
-
border: 2px solid #333;
|
| 147 |
-
border-radius: 3px;
|
| 148 |
-
}
|
| 149 |
-
|
| 150 |
-
.d3-input-labels .legend-masked {
|
| 151 |
-
background: repeating-linear-gradient(45deg,
|
| 152 |
-
#3498db,
|
| 153 |
-
#3498db 2px,
|
| 154 |
-
#2980b9 2px,
|
| 155 |
-
#2980b9 4px);
|
| 156 |
}
|
| 157 |
</style>
|
| 158 |
<script>
|
|
@@ -171,116 +130,94 @@
|
|
| 171 |
container.dataset.mounted = 'true';
|
| 172 |
}
|
| 173 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
// Create the HTML structure
|
| 175 |
container.innerHTML = `
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
<div class="legend-item">
|
| 193 |
-
<div class="legend-color legend-masked"></div>
|
| 194 |
-
<span>Masked Labels (-100)</span>
|
| 195 |
-
</div>
|
| 196 |
-
</div>
|
| 197 |
-
|
| 198 |
-
<div class="conversation-container">
|
| 199 |
-
<div class="row">
|
| 200 |
-
<div class="row-label">input_ids</div>
|
| 201 |
-
<div class="tokens-container">
|
| 202 |
-
<!-- First user turn: 5 tokens -->
|
| 203 |
-
<div class="token user-token">
|
| 204 |
-
<div class="turn-label user-label">user</div>
|
| 205 |
-
U1
|
| 206 |
-
</div>
|
| 207 |
-
<div class="token user-token">U2</div>
|
| 208 |
-
<div class="token user-token">U3</div>
|
| 209 |
-
<div class="token user-token">U4</div>
|
| 210 |
-
<div class="token user-token">U5</div>
|
| 211 |
-
|
| 212 |
-
<!-- First assistant turn: 4 tokens -->
|
| 213 |
-
<div class="token assistant-token">
|
| 214 |
-
<div class="turn-label assistant-label">assistant</div>
|
| 215 |
-
A1
|
| 216 |
-
</div>
|
| 217 |
-
<div class="token assistant-token">A2</div>
|
| 218 |
-
<div class="token assistant-token">A3</div>
|
| 219 |
-
<div class="token assistant-token">A4</div>
|
| 220 |
-
|
| 221 |
-
<!-- Second user turn: 5 tokens -->
|
| 222 |
-
<div class="token user-token">
|
| 223 |
-
<div class="turn-label user-label">user</div>
|
| 224 |
-
U6
|
| 225 |
-
</div>
|
| 226 |
-
<div class="token user-token">U7</div>
|
| 227 |
-
<div class="token user-token">U8</div>
|
| 228 |
-
<div class="token user-token">U9</div>
|
| 229 |
-
<div class="token user-token">U10</div>
|
| 230 |
-
|
| 231 |
-
<!-- Second assistant turn: 4 tokens -->
|
| 232 |
-
<div class="token assistant-token">
|
| 233 |
-
<div class="turn-label assistant-label">assistant</div>
|
| 234 |
-
A5
|
| 235 |
</div>
|
| 236 |
-
|
| 237 |
-
<div class="token assistant-token">A7</div>
|
| 238 |
-
<div class="token assistant-token">A8</div>
|
| 239 |
-
</div>
|
| 240 |
-
</div>
|
| 241 |
-
|
| 242 |
-
<div class="row">
|
| 243 |
-
<div class="row-label">labels</div>
|
| 244 |
-
<div class="tokens-container">
|
| 245 |
-
<!-- Masked labels for first user turn (5 tokens) -->
|
| 246 |
-
<div class="token label-masked">-100</div>
|
| 247 |
-
<div class="token label-masked">-100</div>
|
| 248 |
-
<div class="token label-masked">-100</div>
|
| 249 |
-
<div class="token label-masked">-100</div>
|
| 250 |
-
<div class="token label-masked">-100</div>
|
| 251 |
-
|
| 252 |
-
<!-- Active labels for first assistant turn (4 tokens) -->
|
| 253 |
-
<div class="token label-token">A1</div>
|
| 254 |
-
<div class="token label-token">A2</div>
|
| 255 |
-
<div class="token label-token">A3</div>
|
| 256 |
-
<div class="token label-token">A4</div>
|
| 257 |
-
|
| 258 |
-
<!-- Masked labels for second user turn (5 tokens) -->
|
| 259 |
-
<div class="token label-masked">-100</div>
|
| 260 |
-
<div class="token label-masked">-100</div>
|
| 261 |
-
<div class="token label-masked">-100</div>
|
| 262 |
-
<div class="token label-masked">-100</div>
|
| 263 |
-
<div class="token label-masked">-100</div>
|
| 264 |
-
|
| 265 |
-
<!-- Active labels for second assistant turn (4 tokens) -->
|
| 266 |
-
<div class="token label-token">A5</div>
|
| 267 |
-
<div class="token label-token">A6</div>
|
| 268 |
-
<div class="token label-token">A7</div>
|
| 269 |
-
<div class="token label-token">A8</div>
|
| 270 |
-
</div>
|
| 271 |
-
</div>
|
| 272 |
-
</div>
|
| 273 |
-
|
| 274 |
-
<div class="explanation">
|
| 275 |
-
<h3>How it works:</h3>
|
| 276 |
-
<p><strong>input_ids:</strong> Complete sequence of input tokens (user + assistant)</p>
|
| 277 |
-
<p><strong>labels:</strong> Target tokens for training</p>
|
| 278 |
-
<p><strong>Masked labels (-100):</strong> User tokens are masked because the model should not learn to predict them</p>
|
| 279 |
-
<p><strong>Active labels:</strong> Only assistant tokens are used to calculate training loss</p>
|
| 280 |
-
<p><strong>Goal:</strong> The model learns to generate coherent assistant responses based on user context</p>
|
| 281 |
-
</div>
|
| 282 |
-
</div>
|
| 283 |
-
`;
|
| 284 |
};
|
| 285 |
|
| 286 |
if (document.readyState === 'loading') {
|
|
|
|
| 1 |
<div class="d3-input-labels"></div>
|
| 2 |
<style>
|
| 3 |
.d3-input-labels {
|
|
|
|
| 4 |
margin: 0;
|
| 5 |
+
padding: 10px 0;
|
|
|
|
| 6 |
}
|
| 7 |
|
| 8 |
.d3-input-labels .container {
|
| 9 |
+
max-width: 1000px;
|
| 10 |
margin: 0 auto;
|
|
|
|
| 11 |
border-radius: 10px;
|
|
|
|
|
|
|
| 12 |
}
|
| 13 |
|
| 14 |
+
.d3-input-labels .sections-container {
|
| 15 |
+
display: flex;
|
| 16 |
+
flex-direction: column;
|
| 17 |
+
gap: 20px;
|
| 18 |
+
align-items: center;
|
|
|
|
| 19 |
}
|
| 20 |
|
| 21 |
+
.d3-input-labels .section {
|
| 22 |
display: flex;
|
| 23 |
flex-direction: column;
|
| 24 |
+
align-items: flex-start;
|
| 25 |
+
gap: 10px;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
.d3-input-labels .section:first-child {
|
| 29 |
margin-bottom: 30px;
|
| 30 |
}
|
| 31 |
|
| 32 |
+
@media (max-width: 768px) {
|
| 33 |
+
.d3-input-labels .sections-container {
|
| 34 |
+
flex-direction: column;
|
| 35 |
+
gap: 30px;
|
| 36 |
+
}
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
.d3-input-labels .section {
|
| 40 |
+
flex: 1;
|
| 41 |
+
margin-bottom: 0;
|
| 42 |
}
|
| 43 |
|
| 44 |
+
.d3-input-labels .section-title {
|
| 45 |
+
font-size: 16px;
|
| 46 |
font-weight: bold;
|
| 47 |
+
color: var(--text-color, #333);
|
| 48 |
+
text-align: left;
|
| 49 |
+
margin-bottom: 15px;
|
| 50 |
}
|
| 51 |
|
| 52 |
+
.d3-input-labels .tokens-row {
|
| 53 |
display: flex;
|
|
|
|
| 54 |
gap: 3px;
|
| 55 |
+
justify-content: flex-start;
|
| 56 |
+
flex-wrap: wrap;
|
| 57 |
flex: 1;
|
| 58 |
}
|
| 59 |
|
| 60 |
.d3-input-labels .token {
|
| 61 |
+
width: 30px;
|
| 62 |
+
height: 30px;
|
| 63 |
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
| 64 |
border-radius: 4px;
|
| 65 |
display: flex;
|
| 66 |
align-items: center;
|
|
|
|
| 68 |
font-size: 10px;
|
| 69 |
font-weight: bold;
|
| 70 |
color: white;
|
|
|
|
| 71 |
position: relative;
|
| 72 |
}
|
| 73 |
|
| 74 |
.d3-input-labels .user-token {
|
| 75 |
+
background-color: var(--color-0);
|
| 76 |
}
|
| 77 |
|
| 78 |
.d3-input-labels .assistant-token {
|
| 79 |
+
background-color: var(--color-1);
|
| 80 |
}
|
| 81 |
|
| 82 |
.d3-input-labels .label-token {
|
| 83 |
+
background-color: var(--color-2);
|
| 84 |
}
|
| 85 |
|
| 86 |
.d3-input-labels .label-masked {
|
| 87 |
background: repeating-linear-gradient(45deg,
|
| 88 |
+
var(--color-2),
|
| 89 |
+
var(--color-2) 3px,
|
| 90 |
+
transparent 3px,
|
| 91 |
+
transparent 6px);
|
| 92 |
+
opacity: 0.6;
|
| 93 |
}
|
| 94 |
|
| 95 |
.d3-input-labels .turn-label {
|
|
|
|
| 97 |
top: -25px;
|
| 98 |
left: 50%;
|
| 99 |
transform: translateX(-50%);
|
| 100 |
+
font-size: 10px;
|
| 101 |
font-weight: bold;
|
| 102 |
+
color: var(--text-color, #333);
|
| 103 |
+
background: var(--surface-bg, #fafafa);
|
| 104 |
+
padding: 2px 4px;
|
| 105 |
+
white-space: nowrap;
|
| 106 |
+
border-radius: 2px;
|
| 107 |
}
|
| 108 |
|
| 109 |
.d3-input-labels .user-label {
|
| 110 |
+
color: var(--color-0);
|
| 111 |
}
|
| 112 |
|
| 113 |
.d3-input-labels .assistant-label {
|
| 114 |
+
color: var(--color-1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
}
|
| 116 |
</style>
|
| 117 |
<script>
|
|
|
|
| 130 |
container.dataset.mounted = 'true';
|
| 131 |
}
|
| 132 |
|
| 133 |
+
// Apply categorical color palette
|
| 134 |
+
const applyColorPalette = () => {
|
| 135 |
+
try {
|
| 136 |
+
if (window.ColorPalettes && typeof window.ColorPalettes.getColors === 'function') {
|
| 137 |
+
const colors = window.ColorPalettes.getColors('categorical', 4);
|
| 138 |
+
colors.forEach((color, index) => {
|
| 139 |
+
document.documentElement.style.setProperty(`--color-${index}`, color);
|
| 140 |
+
});
|
| 141 |
+
} else {
|
| 142 |
+
// Fallback colors
|
| 143 |
+
const fallbackColors = [
|
| 144 |
+
'#E889AB', '#4EA5B7', '#E38A42', '#CEC0FA'
|
| 145 |
+
];
|
| 146 |
+
fallbackColors.forEach((color, index) => {
|
| 147 |
+
document.documentElement.style.setProperty(`--color-${index}`, color);
|
| 148 |
+
});
|
| 149 |
+
}
|
| 150 |
+
} catch (e) {
|
| 151 |
+
console.warn('ColorPalettes not available, using fallback colors');
|
| 152 |
+
}
|
| 153 |
+
};
|
| 154 |
+
|
| 155 |
+
// Apply colors immediately and on theme changes
|
| 156 |
+
applyColorPalette();
|
| 157 |
+
if (window.ColorPalettes && typeof window.ColorPalettes.refresh === 'function') {
|
| 158 |
+
window.ColorPalettes.refresh();
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
// Data structure for input_ids and labels
|
| 162 |
+
const inputIds = [
|
| 163 |
+
{ type: 'user', count: 5, label: 'U' },
|
| 164 |
+
{ type: 'assistant', count: 4, label: 'A' },
|
| 165 |
+
{ type: 'user', count: 5, label: 'U' },
|
| 166 |
+
{ type: 'assistant', count: 4, label: 'A' }
|
| 167 |
+
];
|
| 168 |
+
|
| 169 |
+
const labels = [
|
| 170 |
+
{ type: 'masked', count: 5, label: '-100' },
|
| 171 |
+
{ type: 'active', count: 4, label: 'A' },
|
| 172 |
+
{ type: 'masked', count: 5, label: '-100' },
|
| 173 |
+
{ type: 'active', count: 4, label: 'A' }
|
| 174 |
+
];
|
| 175 |
+
|
| 176 |
+
// Helper function to create tokens
|
| 177 |
+
const createTokens = (tokens, rowType) => {
|
| 178 |
+
let tokenIndex = 1;
|
| 179 |
+
return tokens.map((token, groupIndex) => {
|
| 180 |
+
const tokens = [];
|
| 181 |
+
for (let i = 0; i < token.count; i++) {
|
| 182 |
+
const isFirst = i === 0;
|
| 183 |
+
const tokenClass = token.type === 'user' ? 'user-token' :
|
| 184 |
+
token.type === 'assistant' ? 'assistant-token' :
|
| 185 |
+
token.type === 'active' ? 'label-token' : 'label-masked';
|
| 186 |
+
|
| 187 |
+
const labelClass = token.type === 'user' ? 'user-label' : 'assistant-label';
|
| 188 |
+
const labelText = token.type === 'user' ? 'user' : 'assistant';
|
| 189 |
+
|
| 190 |
+
tokens.push(`
|
| 191 |
+
<div class="token ${tokenClass}">
|
| 192 |
+
${isFirst && rowType === 'input_ids' ? `<div class="turn-label ${labelClass}">${labelText}</div>` : ''}
|
| 193 |
+
</div>
|
| 194 |
+
`);
|
| 195 |
+
tokenIndex++;
|
| 196 |
+
}
|
| 197 |
+
return tokens.join('');
|
| 198 |
+
}).join('');
|
| 199 |
+
};
|
| 200 |
+
|
| 201 |
// Create the HTML structure
|
| 202 |
container.innerHTML = `
|
| 203 |
+
<div class="container">
|
| 204 |
+
<div class="sections-container">
|
| 205 |
+
<div class="section">
|
| 206 |
+
<label class="section-title">input_ids</label>
|
| 207 |
+
<div class="tokens-row">
|
| 208 |
+
${createTokens(inputIds, 'input_ids')}
|
| 209 |
+
</div>
|
| 210 |
+
</div>
|
| 211 |
+
|
| 212 |
+
<div class="section">
|
| 213 |
+
<label class="section-title">labels</label>
|
| 214 |
+
<div class="tokens-row">
|
| 215 |
+
${createTokens(labels, 'labels')}
|
| 216 |
+
</div>
|
| 217 |
+
</div>
|
| 218 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
</div>
|
| 220 |
+
`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
};
|
| 222 |
|
| 223 |
if (document.readyState === 'loading') {
|