Files
LLM-Labs/src/components/labs/LabContent.tsx
T
2026-04-27 14:50:55 -06:00

692 lines
20 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import {
Fragment,
memo,
useCallback,
useEffect,
useRef,
useState,
} from "react";
import { Lab1ConfidenceChat } from "~/components/labs/Lab1ConfidenceChat";
import { Lab1NetronPanel } from "~/components/labs/Lab1NetronPanel";
import { Lab3TerminalFrame } from "~/components/labs/Lab3TerminalFrame";
import { Lab8Chat } from "~/components/labs/Lab8Chat";
import { InferenceSettingsVisualization } from "~/components/labs/InferenceSettingsVisualization";
import { Objective5Chat } from "~/components/labs/Objective5Chat";
import { QuantizationGridExplorer } from "~/components/labs/QuantizationGridExplorer";
import { QuantizationExplorer } from "~/components/labs/QuantizationExplorer";
import { TokenizerPlaygroundEmbed } from "~/components/labs/TokenizerPlaygroundEmbed";
import {
fetchCoursewareRuntimeConfig,
isCoursewareServiceId,
normalizeCoursewareRuntimeConfig,
resolveCoursewareServiceAddress,
resolveCoursewareServiceUrl,
type ResolvedCoursewareRuntimeConfig,
} from "~/lib/courseware-runtime";
type LabContentProps = {
className: string;
html: string;
};
type LabContentArticleProps = LabContentProps & {
onZoomImage: (image: ZoomedImageState) => void;
};
const cliLanguagePattern =
/\b(language-(bash|sh|shell|zsh|console|terminal)|bash|shell|zsh)\b/i;
const cliCommandPattern =
/(^|\n)\s*(\$|sudo\s|git\s|python3?\s|pip\s|npm\s|pnpm\s|yarn\s|llama-|ollama\s|curl\s|wget\s|apt\s|cd\s|ls\s|cat\s|cp\s|mv\s|chmod\s|make\s)/i;
const promptLanguagePattern =
/\b(language-(text|plaintext|md|markdown)|text|plaintext|markdown)\b/i;
const promptSignalPattern =
/\b(you are|guidelines|follow these|example|when provided|system prompt|tasked with)\b/i;
type ParsedSetting = {
key: string;
value: string;
};
type ZoomedImageState = {
src: string;
alt: string;
};
const quantizationExplorerToken = "<div data-quantization-explorer></div>";
const quantizationGridExplorerToken =
"<div data-quantization-grid-explorer></div>";
const objective5ChatToken = "<div data-objective5-chat></div>";
const lab8ChatToken = "<div data-lab8-chat></div>";
const lab3TerminalToken = "<div data-lab3-terminal></div>";
const lab1ConfidenceToken = "<div data-lab1-confidence></div>";
const lab1NetronToken = "<div data-lab1-netron-panel></div>";
const tokenizerPlaygroundToken = "<div data-tokenizer-playground></div>";
const inferenceSettingsVisualizationToken =
"<div data-inference-settings-visualization></div>";
const serviceTokenPattern =
/\{\{service-(url|address):([a-z0-9-]+)(?::([^}]+))?\}\}/g;
const serviceLabels: Record<string, string> = {
chunkviz: "ChunkViz",
"embedding-atlas": "Embedding Atlas",
"open-webui": "Open WebUI",
promptfoo: "Promptfoo",
ssh: "SSH",
unsloth: "Unsloth",
};
function looksLikeCliCommand(commandText: string, className: string) {
if (cliLanguagePattern.test(className)) return true;
return (
cliCommandPattern.test(commandText) || /--[a-z0-9-]+/i.test(commandText)
);
}
function looksLikePromptTextBlock(text: string, className: string) {
if (looksLikeCliCommand(text, className)) return false;
const normalizedText = text.trim();
if (!normalizedText) return false;
const lineCount = normalizedText.split("\n").length;
if (promptLanguagePattern.test(className) && normalizedText.length > 80)
return true;
if (lineCount >= 4 && promptSignalPattern.test(normalizedText)) return true;
if (lineCount >= 6 && /(^|\n)\s*[*-]\s+/.test(normalizedText)) return true;
return false;
}
function escapeRegex(value: string) {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function escapeHtml(value: string) {
return value
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll('"', "&quot;")
.replaceAll("'", "&#39;");
}
function parseSettingListItem(item: HTMLLIElement): ParsedSetting | null {
const keyElement = item.querySelector("code");
if (!keyElement) return null;
const key = (keyElement.textContent ?? "").replace(/\s+/g, " ").trim();
if (!key || key.length > 40) return null;
const text = (item.textContent ?? "").replace(/\s+/g, " ").trim();
const match = new RegExp(
`^${escapeRegex(key)}\\s*(?:-||—|:|=)\\s*(.+)$`,
).exec(text);
if (!match) return null;
const value = (match[1] ?? "").replace(/\s+/g, " ").trim();
if (!value || value.length > 36) return null;
if (/[.;]/.test(value) && value.length > 16) return null;
return { key, value };
}
function enhanceSettingsLists(root: HTMLElement) {
const lists = root.querySelectorAll<HTMLUListElement>("ul");
for (const list of lists) {
if (list.dataset.settingsEnhanced === "true") continue;
const items = Array.from(list.children).filter(
(node): node is HTMLLIElement => {
return node.tagName === "LI";
},
);
if (items.length < 2) continue;
const parsedItems = items.map((item) => parseSettingListItem(item));
if (parsedItems.some((parsedItem) => parsedItem === null)) continue;
const settings = parsedItems as ParsedSetting[];
const compactValueCount = settings.filter(
(setting) => setting.value.length <= 20,
).length;
if (compactValueCount < Math.max(2, Math.ceil(settings.length * 0.66)))
continue;
list.dataset.settingsEnhanced = "true";
list.classList.add("lab-settings-list");
for (let i = 0; i < items.length; i++) {
const item = items[i];
const setting = settings[i];
if (!item || !setting) continue;
item.classList.add("lab-settings-item");
item.innerHTML =
`<span class="lab-setting-key">${escapeHtml(setting.key)}</span>` +
`<span class="lab-setting-value">${escapeHtml(setting.value)}</span>`;
}
}
}
function ensureCopyButton(pre: HTMLPreElement, label: string) {
if (pre.dataset.copyEnhanced === "true") return;
pre.dataset.copyEnhanced = "true";
const copyButton = document.createElement("button");
copyButton.type = "button";
copyButton.className = "lab-copy-button";
copyButton.textContent = label;
copyButton.dataset.defaultLabel = label;
copyButton.setAttribute("aria-label", "Copy block to clipboard");
pre.appendChild(copyButton);
}
async function copyTextToClipboard(text: string) {
if (window.isSecureContext && navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(text);
return;
}
const activeElement =
document.activeElement instanceof HTMLElement
? document.activeElement
: null;
const selection = document.getSelection();
const previousRanges =
selection && selection.rangeCount > 0
? Array.from({ length: selection.rangeCount }, (_, index) =>
selection.getRangeAt(index).cloneRange(),
)
: [];
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.setAttribute("readonly", "");
textarea.setAttribute("aria-hidden", "true");
textarea.style.position = "fixed";
textarea.style.top = "0";
textarea.style.left = "-9999px";
textarea.style.opacity = "0";
textarea.style.pointerEvents = "none";
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
textarea.setSelectionRange(0, textarea.value.length);
try {
const didCopy = document.execCommand("copy");
if (!didCopy) {
throw new Error("Copy command was rejected");
}
} finally {
document.body.removeChild(textarea);
if (selection) {
selection.removeAllRanges();
for (const range of previousRanges) {
selection.addRange(range);
}
}
activeElement?.focus();
}
}
function enhanceHarnessSelectors(root: HTMLElement) {
const harnessButtons = Array.from(
root.querySelectorAll<HTMLButtonElement>("button[data-harness-choice]"),
);
const harnessBranches = Array.from(
root.querySelectorAll<HTMLElement>("[data-harness-branch]"),
);
if (harnessButtons.length === 0 || harnessBranches.length === 0) {
return () => {};
}
const supportedHarnesses = new Set(
harnessButtons
.map((button) => button.dataset.harnessChoice?.trim())
.filter((value): value is string => Boolean(value)),
);
let selectedHarness: string | null = null;
const syncHarnessSelection = () => {
for (const button of harnessButtons) {
const harnessId = button.dataset.harnessChoice?.trim() ?? "";
const isSelected =
selectedHarness !== null && harnessId === selectedHarness;
button.setAttribute("aria-pressed", isSelected ? "true" : "false");
button.dataset.selected = isSelected ? "true" : "false";
}
for (const branch of harnessBranches) {
const harnessId = branch.dataset.harnessBranch?.trim() ?? "";
const shouldHide =
selectedHarness === null || harnessId !== selectedHarness;
branch.hidden = shouldHide;
branch.setAttribute("aria-hidden", shouldHide ? "true" : "false");
}
};
syncHarnessSelection();
const handleHarnessClick = (event: Event) => {
const target = event.target as HTMLElement;
const button = target.closest<HTMLButtonElement>(
"button[data-harness-choice]",
);
if (!button || !root.contains(button)) return;
const harnessId = button.dataset.harnessChoice?.trim() ?? "";
if (!supportedHarnesses.has(harnessId)) return;
event.preventDefault();
selectedHarness = selectedHarness === harnessId ? null : harnessId;
syncHarnessSelection();
};
root.addEventListener("click", handleHarnessClick);
return () => {
root.removeEventListener("click", handleHarnessClick);
};
}
function resolveServiceTokenValue(
runtimeConfig: ResolvedCoursewareRuntimeConfig,
tokenType: string,
serviceId: string,
pathSuffix?: string,
) {
if (!isCoursewareServiceId(serviceId)) {
return null;
}
if (tokenType === "url") {
return resolveCoursewareServiceUrl(runtimeConfig, serviceId, pathSuffix);
}
if (tokenType === "address") {
return resolveCoursewareServiceAddress(runtimeConfig, serviceId);
}
return null;
}
function replaceServiceTokens(
root: HTMLElement,
runtimeConfig: ResolvedCoursewareRuntimeConfig,
) {
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode(node) {
if (!(node instanceof Text)) {
return NodeFilter.FILTER_REJECT;
}
if (!node.nodeValue?.includes("{{service-")) {
return NodeFilter.FILTER_REJECT;
}
const parent = node.parentElement;
if (!parent) {
return NodeFilter.FILTER_REJECT;
}
if (parent.closest("[data-widget-enhanced='true']")) {
return NodeFilter.FILTER_REJECT;
}
return NodeFilter.FILTER_ACCEPT;
},
});
const textNodes: Text[] = [];
let currentNode = walker.nextNode();
while (currentNode) {
if (currentNode instanceof Text) {
textNodes.push(currentNode);
}
currentNode = walker.nextNode();
}
for (const textNode of textNodes) {
const parent = textNode.parentElement;
const nodeValue = textNode.nodeValue;
if (!parent || !nodeValue) {
continue;
}
const allowLinks = !parent.closest("code, pre, a");
const nextTextValue = nodeValue.replace(
serviceTokenPattern,
(
fullMatch,
tokenType: string,
serviceId: string,
pathSuffix?: string,
) => {
const replacement = resolveServiceTokenValue(
runtimeConfig,
tokenType,
serviceId,
pathSuffix,
);
return replacement ?? fullMatch;
},
);
if (!allowLinks) {
if (nextTextValue !== nodeValue) {
textNode.nodeValue = nextTextValue;
}
continue;
}
serviceTokenPattern.lastIndex = 0;
let lastIndex = 0;
let didReplace = false;
const fragment = document.createDocumentFragment();
let match = serviceTokenPattern.exec(nodeValue);
while (match) {
const [fullMatch, tokenType, serviceId, pathSuffix] = match;
const replacement = resolveServiceTokenValue(
runtimeConfig,
tokenType,
serviceId,
pathSuffix,
);
if (replacement === null) {
match = serviceTokenPattern.exec(nodeValue);
continue;
}
didReplace = true;
if (match.index > lastIndex) {
fragment.append(nodeValue.slice(lastIndex, match.index));
}
if (tokenType === "url") {
const link = document.createElement("a");
const serviceLabel = serviceLabels[serviceId] ?? replacement;
let visibleLabel = serviceLabel;
try {
const resolvedUrl = new URL(replacement);
if (resolvedUrl.port) {
visibleLabel = `${serviceLabel} on port ${resolvedUrl.port}`;
}
} catch {
visibleLabel = serviceLabel;
}
link.className = "lab-service-pill";
link.dataset.serviceId = serviceId;
link.href = replacement;
link.rel = "noreferrer";
link.target = "_blank";
link.title = replacement;
link.textContent = visibleLabel;
fragment.append(link);
} else {
fragment.append(replacement);
}
lastIndex = match.index + fullMatch.length;
match = serviceTokenPattern.exec(nodeValue);
}
if (!didReplace) {
continue;
}
if (lastIndex < nodeValue.length) {
fragment.append(nodeValue.slice(lastIndex));
}
textNode.replaceWith(fragment);
}
}
const LabContentArticle = memo(function LabContentArticle({
className,
html,
onZoomImage,
}: LabContentArticleProps) {
const containerRef = useRef<HTMLElement>(null);
const [runtimeConfig, setRuntimeConfig] = useState(() =>
normalizeCoursewareRuntimeConfig(),
);
const [isRuntimeResolved, setIsRuntimeResolved] = useState(false);
const renderedContent = html
.split(
new RegExp(
`(${escapeRegex(quantizationExplorerToken)}|${escapeRegex(quantizationGridExplorerToken)}|${escapeRegex(objective5ChatToken)}|${escapeRegex(lab8ChatToken)}|${escapeRegex(lab3TerminalToken)}|${escapeRegex(lab1ConfidenceToken)}|${escapeRegex(lab1NetronToken)}|${escapeRegex(tokenizerPlaygroundToken)}|${escapeRegex(inferenceSettingsVisualizationToken)})`,
"g",
),
)
.filter(Boolean)
.map((part, index) => {
if (part === quantizationExplorerToken) {
return <QuantizationExplorer key={`quantization-explorer-${index}`} />;
}
if (part === quantizationGridExplorerToken) {
return (
<QuantizationGridExplorer
key={`quantization-grid-explorer-${index}`}
/>
);
}
if (part === objective5ChatToken) {
return <Objective5Chat key={`objective5-chat-${index}`} />;
}
if (part === lab8ChatToken) {
return <Lab8Chat key={`lab8-chat-${index}`} />;
}
if (part === lab3TerminalToken) {
return <Lab3TerminalFrame key={`lab3-terminal-${index}`} />;
}
if (part === lab1ConfidenceToken) {
return <Lab1ConfidenceChat key={`lab1-confidence-${index}`} />;
}
if (part === lab1NetronToken) {
return <Lab1NetronPanel key={`lab1-netron-${index}`} />;
}
if (part === tokenizerPlaygroundToken) {
return (
<TokenizerPlaygroundEmbed key={`tokenizer-playground-${index}`} />
);
}
if (part === inferenceSettingsVisualizationToken) {
return (
<InferenceSettingsVisualization
key={`inference-settings-viz-${index}`}
/>
);
}
return (
<Fragment key={`html-segment-${index}`}>
<div dangerouslySetInnerHTML={{ __html: part }} />
</Fragment>
);
});
useEffect(() => {
let isCancelled = false;
void fetchCoursewareRuntimeConfig()
.then((nextRuntimeConfig) => {
if (isCancelled) return;
setRuntimeConfig(nextRuntimeConfig);
})
.catch(() => {
if (isCancelled) return;
setRuntimeConfig(normalizeCoursewareRuntimeConfig());
})
.finally(() => {
if (isCancelled) return;
setIsRuntimeResolved(true);
});
return () => {
isCancelled = true;
};
}, []);
useEffect(() => {
const root = containerRef.current;
if (!root || !isRuntimeResolved) return;
replaceServiceTokens(root, runtimeConfig);
const preBlocks = root.querySelectorAll<HTMLPreElement>("pre");
for (const pre of preBlocks) {
const code = pre.querySelector<HTMLElement>("code");
if (!code) continue;
const blockText = code.textContent ?? "";
if (looksLikeCliCommand(blockText, code.className)) {
pre.classList.add("lab-cli-shell");
ensureCopyButton(pre, "Copy");
continue;
}
if (looksLikePromptTextBlock(blockText, code.className)) {
pre.classList.add("lab-prompt-card");
ensureCopyButton(pre, "Copy Text");
}
}
enhanceSettingsLists(root);
const cleanupHarnessSelectors = enhanceHarnessSelectors(root);
const handleRootClick = (event: Event) => {
const target = event.target as HTMLElement;
const button = target.closest<HTMLButtonElement>(
"button.lab-copy-button",
);
if (button) {
const pre = button.closest("pre");
const code = pre?.querySelector("code");
const commandText = code?.textContent?.trimEnd();
if (!commandText) return;
const defaultLabel = button.dataset.defaultLabel ?? "Copy";
void copyTextToClipboard(commandText)
.then(() => {
button.textContent = "Copied";
button.classList.add("is-copied");
window.setTimeout(() => {
button.textContent = defaultLabel;
button.classList.remove("is-copied");
}, 1200);
})
.catch(() => {
button.textContent = "Failed";
window.setTimeout(() => {
button.textContent = defaultLabel;
}, 1200);
});
return;
}
const image = target.closest<HTMLImageElement>("img");
if (!image || !root.contains(image)) return;
const src = image.getAttribute("src");
if (!src) return;
event.preventDefault();
event.stopPropagation();
onZoomImage({
src,
alt: image.getAttribute("alt") ?? "",
});
};
root.addEventListener("click", handleRootClick);
return () => {
cleanupHarnessSelectors();
root.removeEventListener("click", handleRootClick);
};
}, [html, isRuntimeResolved, onZoomImage, runtimeConfig]);
return (
<article ref={containerRef} className={className}>
{renderedContent}
</article>
);
});
export function LabContent({ className, html }: LabContentProps) {
const [zoomedImage, setZoomedImage] = useState<ZoomedImageState | null>(null);
const handleZoomImage = useCallback((image: ZoomedImageState) => {
setZoomedImage(image);
}, []);
useEffect(() => {
if (!zoomedImage) return;
const previousOverflow = document.body.style.overflow;
document.body.style.overflow = "hidden";
const activeElement = document.activeElement;
const previousFocusedElement =
activeElement instanceof HTMLElement ? activeElement : null;
const handleEscape = (event: KeyboardEvent) => {
if (event.key === "Escape") {
setZoomedImage(null);
}
};
window.addEventListener("keydown", handleEscape);
return () => {
window.removeEventListener("keydown", handleEscape);
document.body.style.overflow = previousOverflow;
previousFocusedElement?.focus();
};
}, [zoomedImage]);
return (
<>
<LabContentArticle
className={className}
html={html}
onZoomImage={handleZoomImage}
/>
{zoomedImage ? (
<div
className="lab-image-modal"
role="presentation"
onClick={() => setZoomedImage(null)}
>
<div
className="lab-image-modal__surface"
onClick={(event) => event.stopPropagation()}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
className="lab-image-modal__image"
src={zoomedImage.src}
alt={zoomedImage.alt}
/>
</div>
</div>
) : null}
</>
);
}