Debug-XAI / frontend /index.html
rongyuan
Fix errors and change the name of the project to Debug-XAI
afa58e5
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NeuralPostmortem: An Interactive Framework for LLM Failures Analysis</title>
<link rel="stylesheet" href="css/style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<style>
/* Additional styles for step-by-step UI */
.step-container {
margin-bottom: 30px;
border: 2px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
}
.step-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 15px 20px;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: bold;
font-size: 1.1em;
}
.step-header.completed {
background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
}
.step-header.active {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.step-header.disabled {
background: #ccc;
cursor: not-allowed;
opacity: 0.6;
}
.step-number {
background: rgba(255,255,255,0.3);
width: 35px;
height: 35px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2em;
margin-right: 15px;
}
.step-title {
flex: 1;
}
.step-status {
font-size: 0.9em;
padding: 5px 15px;
background: rgba(255,255,255,0.2);
border-radius: 15px;
}
.step-body {
padding: 20px;
background: #f9f9f9;
}
.step-body.collapsed {
display: none;
}
.subsection {
margin: 15px 0;
padding: 15px;
background: white;
border-radius: 5px;
border-left: 4px solid #667eea;
}
.subsection h4 {
margin-top: 0;
color: #667eea;
}
.action-buttons {
margin-top: 20px;
display: flex;
gap: 10px;
}
.btn-primary {
background: #667eea;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 1em;
}
.btn-primary:hover {
background: #5568d3;
}
.btn-primary:disabled {
background: #ccc;
cursor: not-allowed;
}
.btn-secondary {
background: #6c757d;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 1em;
}
.vote-details {
margin-top: 10px;
padding: 10px;
background: #f0f0f0;
border-radius: 5px;
}
.vote-item {
padding: 5px;
margin: 5px 0;
background: white;
border-radius: 3px;
}
/* Method Selector Styles */
.method-btn {
background: rgba(255,255,255,0.15);
color: #ccc;
border: 1px solid rgba(255,255,255,0.25);
padding: 6px 16px;
border-radius: 20px;
cursor: pointer;
font-size: 0.9em;
font-weight: 500;
transition: all 0.2s ease;
}
.method-btn:hover {
background: rgba(255,255,255,0.25);
color: white;
}
.method-btn.active {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-color: #764ba2;
box-shadow: 0 2px 8px rgba(102,126,234,0.4);
}
.method-btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
/* Method-specific visibility */
.attnlrp-only { display: block; }
</style>
</head>
<body>
<div id="app">
<header>
<h1>๐Ÿ” Debug-XAI</h1>
<p style="margin: 10px 0; color: #666;">An Interactive Framework for LLM Failure Analysis</p>
<!-- Method Selector Bar -->
<div id="method-bar" style="margin-top: 12px; display: flex; align-items: center; gap: 15px;">
<span style="font-weight: 600; color: #ccc; font-size: 0.95em;">Attribution Method:</span>
<div id="method-selector" style="display: flex; gap: 6px;">
<button class="method-btn active" data-method="attnlrp" data-port="8000">Attn-LRP</button>
</div>
<span id="method-status" style="font-size: 0.85em; color: #8e8e8e; margin-left: 10px;">
Backend: <code id="current-api-base" style="color: #38ef7d;">localhost:8000</code>
</span>
</div>
</header>
<main style="max-width: 1400px; margin: 0 auto; padding: 20px;">
<!-- Step 1: Case Setup & Model Configuration -->
<div class="step-container" id="step-1">
<div class="step-header active" onclick="toggleStep(1)">
<div style="display: flex; align-items: center;">
<span class="step-number">1</span>
<span class="step-title">Case Setup & Model Configuration</span>
</div>
<span class="step-status" id="status-1">Pending</span>
</div>
<div class="step-body" id="body-1">
<div class="subsection">
<h4>๐Ÿ“ Load from Trace (Auto-fills all fields)</h4>
<div class="control-group">
<label>Dataset:
<select id="trace-dataset">
<option value="">-- Select --</option>
<!-- Populated by JS -->
</select>
</label>
<label>Trace File:
<select id="trace-file" disabled>
<option value="">-- Select Dataset First --</option>
</select>
</label>
</div>
</div>
<div class="subsection">
<h4>โœ๏ธ Manual Input</h4>
<div class="control-group">
<label for="input-prompt"><strong>Prompt:</strong></label>
<textarea id="input-prompt" rows="4" placeholder="Enter your prompt here..."></textarea>
</div>
<div class="control-group">
<label for="input-completion"><strong>Completion:</strong></label>
<textarea id="input-completion" rows="4" placeholder="Enter the completion to analyze..."></textarea>
</div>
<div class="control-group">
<label for="input-ground-truth"><strong>Ground Truth (Optional):</strong></label>
<textarea id="input-ground-truth" rows="2" placeholder="Expected correct answer..."></textarea>
</div>
</div>
<div class="subsection">
<h4>๐Ÿค– Model Configuration</h4>
<div class="control-group">
<div style="display: flex; gap: 15px; flex-wrap: wrap;">
<label>Series:
<select id="model-series">
<option value="Qwen3">Qwen3</option>
<option value="Qwen2">Qwen2</option>
<option value="OLMo3">OLMo3</option>
</select>
</label>
<label>Model:
<select id="model-select">
<!-- Populated dynamically -->
</select>
</label>
<label>DType:
<select id="model-dtype">
<option value="float16">float16</option>
<option value="bfloat16" selected>bfloat16</option>
<option value="float32">float32</option>
</select>
</label>
<label>
<input type="checkbox" id="quant-4bit"> 4-bit Quantization
</label>
</div>
</div>
<div class="control-group">
<label>Model Path:
<input type="text" id="model-path" value="Qwen/Qwen3-0.6B" style="width: 400px;">
</label>
</div>
</div>
<div class="action-buttons">
<button class="btn-primary" id="btn-load-model">Load Model & Proceed</button>
<span id="model-load-status" style="margin-left: 15px; line-height: 40px; color: #666;"></span>
</div>
</div>
</div>
<!-- Step 2: Contrast Token Pair Identification -->
<div class="step-container" id="step-2">
<div class="step-header disabled" onclick="toggleStep(2)">
<div style="display: flex; align-items: center;">
<span class="step-number">2</span>
<span class="step-title">Contrast Token Pair Identification</span>
</div>
<span class="step-status" id="status-2">Locked</span>
</div>
<div class="step-body collapsed" id="body-2">
<!-- Subsection 3.1: Error Token Localization -->
<div class="subsection">
<h4>๐ŸŽฏ Target Token Localization & Text Truncation</h4>
<p style="color: #666; margin-bottom: 15px;">
Use multiple LLM validators to identify the first erroneous token in the completion.
</p>
<div class="control-group">
<label style="display: flex; align-items: center; gap: 10px;">
<input type="checkbox" id="use-llm-search" checked> Use LLM search (validators)
</label>
</div>
<div class="control-group" style="margin-top: 10px;" id="manual-chunk-group" hidden>
<label><strong>Manual Localization(s):</strong> (Include both prompt and completion)</label>
<textarea id="manual-chunks" rows="3" style="width: 100%; font-family: monospace;"></textarea>
</div>
<div class="control-group" style="margin-top: 10px;">
<label><strong>Validator Models:</strong></label>
<div style="display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0;">
<label><input type="checkbox" id="validator-gpt52" checked> GPT-5.2</label>
<label><input type="checkbox" id="validator-gptoss" checked> GPT-OSS-120B</label>
<label><input type="checkbox" id="validator-deepseek" checked> DeepSeek-V3.2</label>
<label><input type="checkbox" id="validator-kimi"> Kimi-K2-Thinking</label>
</div>
</div>
<div class="action-buttons">
<button class="btn-primary" id="btn-locate-error">Locate Target Token</button>
<span id="error-locate-status" style="margin-left: 15px; line-height: 40px; color: #666;"></span>
</div>
<!-- Results -->
<div id="error-location-results" class="hidden" style="margin-top: 20px;">
<h5 style="color: #667eea;">๐Ÿ“Š Voting Results:</h5>
<div id="vote-details" class="vote-details">
<!-- Populated by JS -->
</div>
<h5 style="color: #667eea; margin-top: 15px;">โœ‚๏ธ Truncated Text:</h5>
<div class="control-group">
<textarea id="truncated-text" rows="5" style="width: 100%; font-family: monospace;"></textarea>
</div>
<h5 style="color: #667eea;">๐Ÿ’ก Explanation:</h5>
<div id="error-explanation" style="padding: 10px; background: #fff3cd; border-radius: 5px; white-space: pre-wrap;"></div>
<div class="action-buttons" style="margin-top: 15px;">
<button class="btn-primary" id="btn-accept-truncation">Accept & Use Truncated Text</button>
<button class="btn-secondary" id="btn-edit-truncation">Edit Truncation</button>
<span id="accept-status" style="margin-left: 15px; line-height: 40px; color: #28a745; font-weight: bold;"></span>
</div>
</div>
</div>
<!-- Subsection 3.2: Contrast Token Selection -->
<div class="subsection" id="contrast-selection-section" class="hidden">
<h4>๐Ÿ”„ Contrast Token Selection</h4>
<p style="color: #666; margin-bottom: 15px;">
After error token localization, identify the contrast token (correct alternative).
</p>
<div class="control-group">
<label><strong>Selection Method:</strong></label>
<div style="margin: 10px 0;">
<label style="display: block; margin: 5px 0;">
<input type="radio" name="contrast-method" value="manual" checked>
Manual Selection (from Top-K predictions)
</label>
<label style="display: block; margin: 5px 0;">
<input type="radio" name="contrast-method" value="beam">
Beam Search (automatic exploration)
</label>
</div>
</div>
<div id="manual-contrast-section">
<div class="action-buttons">
<button class="btn-primary" id="btn-compute-topk">Compute Top-K Predictions</button>
<label style="margin-left: 15px;">
K = <input type="number" id="topk-value" value="10" min="1" max="100" style="width: 60px;">
</label>
</div>
<!-- Top-K Table -->
<div id="topk-results" class="hidden" style="margin-top: 20px;">
<h5>Top-K Token Predictions:</h5>
<div class="scrollable-table">
<table id="topk-table">
<thead>
<tr>
<th>Rank</th>
<th>Token</th>
<th>Logit</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<!-- Populated by JS -->
</tbody>
</table>
</div>
</div>
</div>
<div id="beam-contrast-section" class="hidden">
<p style="color: #999; font-style: italic;">Beam search functionality - Coming soon...</p>
<div class="action-buttons">
<button class="btn-primary" disabled>Run Beam Search</button>
</div>
</div>
<!-- Selected Contrast Token Display -->
<div id="contrast-selected" class="hidden" style="margin-top: 20px; padding: 15px; background: #d4edda; border-radius: 5px;">
<h5 style="margin-top: 0; color: #155724;">โœ“ Contrast Token Pair Identified:</h5>
<p><strong>Error Token:</strong> <span id="display-error-token">-</span></p>
<p><strong>Contrast Token:</strong> <span id="display-contrast-token">-</span></p>
<p><strong>Logit Difference:</strong> <span id="display-logit-diff">-</span></p>
</div>
</div>
<div class="action-buttons" style="margin-top: 20px;">
<button class="btn-primary" id="btn-proceed-to-lrp" disabled>Proceed to Input Attribution Analysis</button>
</div>
</div>
</div>
<!-- Step 3: Input Attribution -->
<div class="step-container" id="step-3">
<div class="step-header disabled" onclick="toggleStep(3)">
<div style="display: flex; align-items: center;">
<span class="step-number">3</span>
<span class="step-title">Input Attribution Analysis</span>
</div>
<span class="step-status" id="status-3">Locked</span>
</div>
<div class="step-body collapsed" id="body-3">
<div class="subsection attnlrp-only">
<h4>โš™๏ธ Input Attribution Configuration</h4>
<div class="control-group">
<label>Rule:
<select id="lrp-rule">
<option value="Attn-LRP" selected>Attn-LRP</option>
<option value="CP-LRP">CP-LRP</option>
<option value="Gradient">Gradient (Vanilla)</option>
</select>
</label>
<label style="margin-left: 20px;">
<input type="checkbox" id="capture-mid"> Attn/MLP Split
</label>
</div>
</div>
<div class="subsection">
<h4>๐ŸŽจ Input Attribution Visualization</h4>
<div class="control-group">
<label>Mode:
<select id="attr-mode">
<option value="max_logit">Max Logit</option>
<option value="logit_diff" selected>Logit Difference</option>
</select>
</label>
<label style="margin-left: 15px;">Strategy:
<select id="attr-strategy">
<option value="by_topk_avg">By Top-K Avg</option>
<option value="demean">Demean</option>
<option value="by_ref_token" selected>By Reference Token</option>
</select>
</label>
</div>
<div class="action-buttons">
<button class="btn-primary" id="btn-compute-attribution">Compute Input Attribution</button>
</div>
<div id="attribution-results" class="hidden" style="margin-top: 20px;">
<h5>Attribution Map:</h5>
<div id="attribution-display" style="padding: 15px; background: white; border: 1px solid #ddd; border-radius: 5px; font-family: monospace; line-height: 1.8;">
<!-- Populated by JS -->
</div>
<div class="action-buttons" style="margin-top: 10px;">
<button class="btn-secondary" id="btn-save-attr-png" style="background-color: #2ecc71;">Save PNG</button>
<button class="btn-secondary" id="btn-save-attr-pdf" style="background-color: #e74c3c;">Save PDF</button>
</div>
<!-- Positive Relevance Sorted Indices -->
<div id="positive-relevance-sorted" class="hidden" style="margin-top: 18px;">
<h5 style="margin: 0 0 8px 0; color: #667eea;">Positive Relevance Tokens (Sorted by Relevance, Descending)</h5>
<div id="pos-rel-indices" style="padding: 10px; background: #f8f9fa; border: 1px solid #ddd; border-radius: 4px; font-family: monospace; font-size: 0.95em; word-break: break-all; line-height: 1.8;"></div>
<h5 style="margin: 12px 0 8px 0; color: #7f8c8d; font-size: 0.9em;">Corresponding Tokens (for verification)</h5>
<div id="pos-rel-tokens" style="padding: 10px; background: #fefefe; border: 1px solid #eee; border-radius: 4px; font-family: monospace; font-size: 0.9em; word-break: break-all; line-height: 1.8; color: #555;"></div>
</div>
</div>
</div>
<!-- Perturbation Evaluation Subsection -->
<div class="subsection">
<h4>๐Ÿงช Perturbation Evaluation (Ground-Truth Comparison)</h4>
<p style="color: #666; margin-bottom: 15px;">
Evaluate attribution quality by zeroing out top-attributed tokens and checking if the model's error is fixed.
A better attribution method should fix the error at smaller K values.
</p>
<div class="control-group">
<label>K values (comma-separated):
<input type="text" id="perturbation-k-values" value="1, 3, 5, 10" style="width: 200px;">
</label>
</div>
<div class="action-buttons">
<button class="btn-primary" id="btn-run-perturbation" disabled>Run Perturbation Evaluation</button>
<span id="perturbation-status" style="margin-left: 15px; line-height: 40px; color: #666;"></span>
</div>
<div id="perturbation-results" class="hidden" style="margin-top: 20px;">
<h5>Perturbation Results:</h5>
<div class="scrollable-table">
<table id="perturbation-table">
<thead>
<tr>
<th>K</th>
<th>Perturbed Tokens</th>
<th>New Top-1 Token</th>
<th>Error Fixed?</th>
<th>Target Rank After</th>
<th>Logit Change</th>
</tr>
</thead>
<tbody>
<!-- Populated by JS -->
</tbody>
</table>
</div>
</div>
<!-- Manual Perturbation Sub-section -->
<div style="margin-top: 25px; padding-top: 20px; border-top: 2px dashed #dee2e6;">
<h5 style="color: #667eea; margin-top: 0;">๐Ÿ–ฑ๏ธ Manual Token Perturbation</h5>
<p style="color: #666; font-size: 0.9em; margin-bottom: 12px;">
Click tokens in the <strong>Attribution Map</strong> above to select/deselect which tokens to mask.
Selected tokens will be highlighted with a dashed border.
</p>
<div style="margin-bottom: 12px;">
<strong style="font-size: 0.9em;">Selected Tokens:</strong>
<div id="manual-perturb-selected" style="display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; min-height: 32px; padding: 8px; background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 5px;">
<span style="color: #999; font-size: 0.85em; line-height: 24px;" id="manual-perturb-placeholder">No tokens selected</span>
</div>
</div>
<div class="action-buttons">
<button class="btn-secondary" id="btn-clear-manual-selection" style="background: #95a5a6;">Clear Selection</button>
<button class="btn-primary" id="btn-run-manual-perturbation" disabled>Run Manual Perturbation</button>
<span id="manual-perturbation-status" style="margin-left: 15px; line-height: 40px; color: #666;"></span>
</div>
<div id="manual-perturbation-result" class="hidden" style="margin-top: 15px;">
<!-- Populated by JS -->
</div>
</div>
</div>
<div class="action-buttons" style="margin-top: 20px;">
<button class="btn-primary" id="btn-proceed-to-graph">Proceed to Attribution Graph</button>
</div>
</div>
</div>
<!-- Step 4: Attribution Graph -->
<div class="step-container" id="step-4">
<div class="step-header disabled" onclick="toggleStep(4)">
<div style="display: flex; align-items: center;">
<span class="step-number">4</span>
<span class="step-title">Attribution Graph Visualization</span>
</div>
<span class="step-status" id="status-4">Locked</span>
</div>
<div class="step-body collapsed" id="body-4">
<div class="subsection">
<h4>๐Ÿ”ง Graph Configuration</h4>
<div class="control-group">
<label><strong>Layer Selection:</strong></label>
<input type="text" id="layers-list" placeholder="e.g., 0, 10, 20, 27" style="width: 300px;">
<button class="btn-secondary" id="btn-layer-preset-default">Recommended</button>
<button class="btn-secondary" id="btn-layer-preset-all">All Layers</button>
</div>
<div class="control-group" style="margin-top: 15px;">
<label>Backprop Mode:
<select id="graph-bp-mode">
<option value="max_logit">Max Logit</option>
<option value="logit_diff" selected>Logit Difference</option>
</select>
</label>
<label style="margin-left: 15px;">Strategy:
<select id="graph-bp-strategy">
<option value="by_topk_avg" selected>By Top-K Avg</option>
<option value="demean">Demean</option>
<option value="by_ref_token">By Reference Token</option>
</select>
</label>
</div>
<div class="control-group" style="margin-top: 15px;">
<label>Pruning Mode:
<select id="pruning-mode">
<option value="by_per_layer_cum_mass_percentile" selected>By Top-P Mass (Layer)</option>
<option value="by_global_threshold">By Global Threshold</option>
</select>
</label>
</div>
<div id="ctrl-top-p" class="control-group" style="margin-top: 10px;">
<label>Top-P Mass (0-1):
<input type="range" id="top-p-slider" min="0" max="1" step="0.01" value="0.85" style="width: 200px; margin-left: 10px;">
<input type="number" id="top-p-value" value="0.85" min="0" max="1" step="0.01" style="width: 70px; margin-left: 10px;">
</label>
</div>
<div id="ctrl-global-thresh" class="control-group hidden" style="margin-top: 10px;">
<label>Global Edge Threshold:
<input type="number" id="global-thresh-value" value="0.01" min="0" max="1" step="0.001" style="width: 100px; margin-left: 10px;">
</label>
</div>
<div class="action-buttons">
<button class="btn-primary" id="btn-compute-graph">Compute & Visualize Graph</button>
</div>
</div>
<div id="graph-results" class="hidden" style="margin-top: 20px;">
<h4>๐Ÿ“Š Circuit Visualization</h4>
<!-- Visualization Controls -->
<div style="display: flex; gap: 15px; margin-bottom: 15px; flex-wrap: wrap; align-items: center;">
<label><input type="checkbox" id="show-all-tokens"> Show All Tokens</label>
<label><input type="checkbox" id="hide-bos"> Hide BOS Token</label>
<label><input type="checkbox" id="show-values" checked> Show Node Values</label>
</div>
<div style="display: flex; gap: 20px; margin-bottom: 15px; flex-wrap: wrap; align-items: center;">
<label style="display: flex; align-items: center; gap: 8px;">
Line Strength:
<input type="range" id="line-strength" min="2" max="20" value="6" step="0.1" style="width: 120px;">
<span id="line-strength-val" style="min-width: 35px; font-weight: bold;">6.0</span>
</label>
<label style="display: flex; align-items: center; gap: 8px;">
Layer Spacing (px):
<input type="range" id="layer-spacing-slider" min="50" max="400" value="100" step="10" style="width: 120px;">
<input type="number" id="layer-spacing-value" min="50" max="400" value="100" step="10" style="width: 60px;">
</label>
</div>
<!-- Threshold Adjustment (Post-Compute) -->
<div style="padding: 10px; background: #f0f0f0; border-radius: 5px; margin-bottom: 15px;">
<strong>๐ŸŽ›๏ธ Adjust Graph Sparsity:</strong>
<div id="post-ctrl-top-p" style="margin-top: 8px;">
<label>Top-P Mass:
<input type="range" id="post-top-p-slider" min="0" max="1" step="0.01" value="0.85" style="width: 200px; margin-left: 10px;">
<input type="number" id="post-top-p-value" value="0.85" min="0" max="1" step="0.01" style="width: 70px; margin-left: 10px;">
<button class="btn-secondary" id="btn-recompute-threshold" style="margin-left: 10px;">Recompute</button>
</label>
</div>
<div id="post-ctrl-global-thresh" class="hidden" style="margin-top: 8px;">
<label>Global Threshold:
<input type="number" id="post-global-thresh-value" value="0.01" min="0" max="1" step="0.001" style="width: 100px; margin-left: 10px;">
<button class="btn-secondary" id="btn-recompute-threshold-global" style="margin-left: 10px;">Recompute</button>
</label>
</div>
</div>
<div id="canvas-container" style="border: 1px solid #ddd; border-radius: 5px; overflow: hidden;">
<canvas id="graph-canvas"></canvas>
<div id="graph-tooltip"></div>
</div>
<div class="action-buttons" style="margin-top: 15px;">
<button class="btn-secondary" id="btn-save-graph">Save as PNG</button>
<button class="btn-secondary" id="btn-save-graph-pdf">Save as PDF</button>
</div>
</div>
<div style="margin-top: 30px; padding: 20px; background: #d4edda; border-radius: 8px;">
<h3 style="margin-top: 0; color: #155724;">โœ… Analysis Complete!</h3>
<p>You have completed the full step-by-step analysis pipeline. Review the results above or export your findings.</p>
</div>
</div>
</div>
</main>
</div>
<!-- Loading Overlay -->
<div id="loading-overlay" class="hidden">
<div class="spinner"></div>
<div id="loading-message">Processing...</div>
</div>
<script src="js/main_new.js?v=20260330"></script>
</body>
</html>