Spaces:
Runtime error
Runtime error
| import type { ActivationData, AnomalyData, CircuitData } from '../types/scan'; | |
| import type { CompareData, LayerDiff } from '../types/compare'; | |
| import type { ScanMode } from '../types/model'; | |
| export interface ScanDataPair { | |
| activationData: ActivationData | null; | |
| circuitData: CircuitData | null; | |
| anomalyData: AnomalyData | null; | |
| } | |
| /** | |
| * Compute layer-wise diffs between two scan datasets. | |
| * Works for both multi-prompt (same model) and cross-model comparisons. | |
| */ | |
| export function computeLayerDiffs( | |
| mode: ScanMode, | |
| labelA: string, | |
| labelB: string, | |
| tokensA: string[], | |
| tokensB: string[], | |
| dataA: ScanDataPair, | |
| dataB: ScanDataPair, | |
| ): CompareData | null { | |
| if (mode === 'fMRI' && dataA.activationData && dataB.activationData) { | |
| const a = dataA.activationData; | |
| const b = dataB.activationData; | |
| const diffs: LayerDiff[] = []; | |
| for (let i = 0; i < Math.min(a.layers.length, b.layers.length); i++) { | |
| const aActs = a.layers[i].activations; | |
| const bActs = b.layers[i].activations; | |
| const avgA = aActs.reduce((s, v) => s + v, 0) / Math.max(aActs.length, 1); | |
| const avgB = bActs.reduce((s, v) => s + v, 0) / Math.max(bActs.length, 1); | |
| diffs.push({ layer_id: a.layers[i].layer_id, delta: avgB - avgA }); | |
| } | |
| const maxAbs = Math.max(...diffs.map((d) => Math.abs(d.delta)), 0.001); | |
| return { promptA: labelA, promptB: labelB, tokens_a: tokensA, tokens_b: tokensB, layerDiffs: diffs, maxAbsDelta: maxAbs }; | |
| } | |
| if (mode === 'DTI' && dataA.circuitData && dataB.circuitData) { | |
| const a = dataA.circuitData; | |
| const b = dataB.circuitData; | |
| const aMap = new Map(a.components.map((c) => [c.layer_id, c.importance])); | |
| const diffs: LayerDiff[] = b.components.map((c) => ({ | |
| layer_id: c.layer_id, | |
| delta: c.importance - (aMap.get(c.layer_id) ?? 0), | |
| })); | |
| const maxAbs = Math.max(...diffs.map((d) => Math.abs(d.delta)), 0.001); | |
| return { promptA: labelA, promptB: labelB, tokens_a: tokensA, tokens_b: tokensB, layerDiffs: diffs, maxAbsDelta: maxAbs }; | |
| } | |
| if (mode === 'FLAIR' && dataA.anomalyData && dataB.anomalyData) { | |
| const a = dataA.anomalyData; | |
| const b = dataB.anomalyData; | |
| const diffs: LayerDiff[] = []; | |
| for (let i = 0; i < Math.min(a.layers.length, b.layers.length); i++) { | |
| const aScores = a.layers[i].anomaly_scores; | |
| const bScores = b.layers[i].anomaly_scores; | |
| const avgA = aScores.reduce((s, v) => s + v, 0) / Math.max(aScores.length, 1); | |
| const avgB = bScores.reduce((s, v) => s + v, 0) / Math.max(bScores.length, 1); | |
| diffs.push({ layer_id: a.layers[i].layer_id, delta: avgB - avgA }); | |
| } | |
| const maxAbs = Math.max(...diffs.map((d) => Math.abs(d.delta)), 0.001); | |
| return { promptA: labelA, promptB: labelB, tokens_a: tokensA, tokens_b: tokensB, layerDiffs: diffs, maxAbsDelta: maxAbs }; | |
| } | |
| return null; | |
| } | |