Skip to content
372 changes: 260 additions & 112 deletions align_browser/static/app.js

Large diffs are not rendered by default.

51 changes: 35 additions & 16 deletions align_browser/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
<body>
<main>
<div class="table-header">
<h2>Align System Experiments</h2>
<h2>
Align System Experiments
<span id="loading-spinner" class="loading-spinner" style="visibility: hidden;">
<span class="spinner"></span>
</span>
</h2>
<button
id="add-column-btn"
class="btn btn-primary"
Expand All @@ -28,43 +33,57 @@ <h2>Align System Experiments</h2>
</tr>
</thead>
<tbody>
<tr class="parameter-row" data-category="scenario">
<td class="parameter-name">Scenario</td>
<tr class="parameter-row" data-parameter="scenario">
<td class="parameter-name">
<div class="parameter-name-content">
<span>Scenario</span>
<div class="link-toggle" onclick="toggleParameterLink('scenario')">
<span class="link-icon">⛓️‍💥</span>
</div>
</div>
</td>
</tr>
<tr class="parameter-row" data-category="scene">
<td class="parameter-name">Scene</td>
<tr class="parameter-row" data-parameter="scene">
<td class="parameter-name">
<div class="parameter-name-content">
<span>Scene</span>
<div class="link-toggle" onclick="toggleParameterLink('scene')">
<span class="link-icon">⛓️‍💥</span>
</div>
</div>
</td>
</tr>
<tr class="parameter-row" data-category="scenario_state">
<tr class="parameter-row" data-parameter="scenario_state">
<td class="parameter-name">Scenario State</td>
</tr>
<tr class="parameter-row" data-category="available_choices">
<tr class="parameter-row" data-parameter="available_choices">
<td class="parameter-name">Choices</td>
</tr>
<tr class="parameter-row" data-category="kdma_values">
<tr class="parameter-row" data-parameter="kdma_values">
<td class="parameter-name">KDMAs</td>
</tr>
<tr class="parameter-row" data-category="adm_type">
<tr class="parameter-row" data-parameter="adm_type">
<td class="parameter-name">ADM</td>
</tr>
<tr class="parameter-row" data-category="llm_backbone">
<tr class="parameter-row" data-parameter="llm_backbone">
<td class="parameter-name">LLM Backbone</td>
</tr>
<tr class="parameter-row" data-category="run_variant">
<tr class="parameter-row" data-parameter="run_variant">
<td class="parameter-name">Run Variant</td>
</tr>
<tr class="parameter-row" data-category="adm_decision">
<tr class="parameter-row" data-parameter="adm_decision">
<td class="parameter-name">Decision</td>
</tr>
<tr class="parameter-row" data-category="justification">
<tr class="parameter-row" data-parameter="justification">
<td class="parameter-name">Justification</td>
</tr>
<tr class="parameter-row" data-category="choice_info">
<tr class="parameter-row" data-parameter="choice_info">
<td class="parameter-name">Choice Info</td>
</tr>
<tr class="parameter-row" data-category="probe_time">
<tr class="parameter-row" data-parameter="probe_time">
<td class="parameter-name">Probe Time</td>
</tr>
<tr class="parameter-row" data-category="input_output_json">
<tr class="parameter-row" data-parameter="input_output_json">
<td class="parameter-name">Input Output JSON</td>
</tr>
</tbody>
Expand Down
99 changes: 95 additions & 4 deletions align_browser/static/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@

import { showWarning } from './notifications.js';

// Centralized parameter mappings
export const PARAMETER_MAPPINGS = {
// Maps validation API names back to internal names
API_TO_INTERNAL: {
'scenario': 'scenario',
'scene': 'scene',
'adm': 'admType',
'llm': 'llmBackbone',
'kdma_values': 'kdmaValues',
'run_variant': 'runVariant'
}
};

// Constants for KDMA processing
const KDMA_CONSTANTS = {
DECIMAL_PRECISION: 10, // For 1 decimal place normalization
Expand Down Expand Up @@ -82,7 +95,8 @@ export function createInitialState() {
availableLLMs: [],

// Comparison state
pinnedRuns: new Map()
pinnedRuns: new Map(),
linkedParameters: new Set()
};
}

Expand Down Expand Up @@ -148,7 +162,7 @@ export function createRunConfig(params, availableKDMAs) {
scenes: params.availableScenes || [],
admTypes: params.availableAdmTypes || [],
llms: params.availableLLMs || [],
kdmas: kdmaStructure // Sophisticated structure with constraint information
kdmaValues: kdmaStructure // Sophisticated structure with constraint information
}
};
}
Expand All @@ -161,7 +175,7 @@ export function createParameterStructure(params = {}) {
admType: params.admType || null,
llmBackbone: params.llmBackbone || null,
runVariant: params.runVariant || 'default',
kdmas: params.kdmas || {}
kdmaValues: params.kdmaValues || {}
};
}

Expand All @@ -170,6 +184,7 @@ export function encodeStateToURL(state) {
const manifest = GlobalState.getManifest();
const urlState = {
manifestCreatedAt: manifest?.generated_at,
linkedParameters: Array.from(state.linkedParameters || []),
pinnedRuns: Array.from(state.pinnedRuns.values()).map(run => ({
scenario: run.scenario,
scene: run.scene,
Expand Down Expand Up @@ -325,6 +340,82 @@ const updateParametersBase = (priorityOrder) => (manifest) => (currentParams, ch
// Export updateParameters with priority order already curried
export const updateParameters = updateParametersBase(PARAMETER_CONFIG.PRIORITY_ORDER);

export function toggleParameterLink(paramName, appState, callbacks) {
if (appState.linkedParameters.has(paramName)) {
appState.linkedParameters.delete(paramName);
callbacks.renderTable();
callbacks.updateURL();
return null;
} else {
appState.linkedParameters.add(paramName);
// When enabling link, propagate the leftmost column's value
const firstRun = Array.from(appState.pinnedRuns.values())[0];
let propagationResult = null;
if (firstRun) {
const currentValue = getParameterValueFromRun(firstRun, paramName);
propagationResult = propagateParameterToAllRuns(paramName, currentValue, firstRun.id, appState, callbacks);
}
callbacks.renderTable();
callbacks.updateURL();
return propagationResult;
}
}

export function propagateParameterToAllRuns(paramName, value, sourceRunId, appState, callbacks) {
// Temporarily disable link for this parameter to prevent infinite loops
const wasLinked = appState.linkedParameters.has(paramName);
appState.linkedParameters.delete(paramName);

// Parameters that require data reload when changed
const reloadRequiredParams = new Set([
'scenario', 'scene', 'admType', 'llmBackbone', 'kdmaValues', 'runVariant'
]);

const needsReload = reloadRequiredParams.has(paramName);

// Collect run IDs that need reloading for the callback to handle
const runIdsToReload = [];

appState.pinnedRuns.forEach((_, runId) => {
if (runId !== sourceRunId) {
callbacks.updateParameterForRun(runId, paramName, value, true);

// If this parameter change requires data reload, collect the runId
if (needsReload) {
runIdsToReload.push(runId);
}
}
});

// Re-enable link if it was previously enabled
if (wasLinked) {
appState.linkedParameters.add(paramName);
}

// Return information for the caller to handle async operations
return {
needsReload,
runIdsToReload
};
}

export function getParameterValueFromRun(run, paramName) {
return run[paramName];
}

export function isParameterLinked(paramName, appState) {
return appState.linkedParameters.has(paramName);
}

// Helper function to identify result parameters (those that depend on experiment data)
export function isResultParameter(paramName) {
const resultParams = new Set([
'scenario_state', 'available_choices', 'choice_info',
'adm_decision', 'justification', 'probe_time', 'input_output_json'
]);
return resultParams.has(paramName);
}

// Global state encapsulation
const GlobalState = {
manifest: null,
Expand Down Expand Up @@ -359,7 +450,7 @@ export async function loadManifest() {
}


function resolveParametersToRun(params) {
export function resolveParametersToRun(params) {
if (GlobalState.isParameterRunMapEmpty()) {
console.warn('parameterRunMap is empty or not initialized');
return undefined;
Expand Down
Loading
Loading