Spaces:
Sleeping
Sleeping
File size: 2,767 Bytes
b89c27d 275f68e b89c27d 275f68e b89c27d 275f68e b89c27d 275f68e b89c27d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import Plot from 'react-plotly.js'
const PLOTLY_BASE = {
font: { family: 'Inter', color: '#f3f0e8', size: 12 },
paper_bgcolor: '#2a2824',
plot_bgcolor: '#1f1d1a',
hoverlabel: { bgcolor: '#f3f0e8', font: { color: '#1f1d1a' } },
}
const AXIS = {
gridcolor: '#403b34', zerolinecolor: '#554e45',
showline: true, linecolor: '#554e45',
tickfont: { color: '#b5ada0' },
}
// Per-component weights from rewards.py. Breakdown bars show weighted
// contributions (sum → total reward) rather than raw component values, so
// the chart is directly readable as "which components are hurting / helping".
const WEIGHTS = {
r_regret: 1.0,
r_convergence: 0.3,
r_robustness: 0.3,
r_novelty: 0.1,
r_budget: -0.05, // subtractive
r_eval_failures: -0.5, // subtractive
}
const DISPLAY_NAMES = {
r_regret: 'regret (×1.0)',
r_convergence: 'convergence (×0.3)',
r_robustness: 'robustness (×0.3)',
r_novelty: 'novelty (×0.1)',
r_budget: 'budget (−0.05×)',
r_eval_failures: 'eval crashes (−0.5×)',
}
export function RewardBreakdown({ breakdown, total }) {
// Weighted contributions — sum to the terminal reward.
const entries = Object.entries(WEIGHTS).map(([k, w]) => ({
key: k,
label: DISPLAY_NAMES[k],
value: (breakdown[k] ?? 0) * w,
}))
const names = entries.map(e => e.label)
const vs = entries.map(e => e.value)
const colors = vs.map(v => v >= 0 ? '#3d6b4c' : '#a0483a')
const labels = vs.map(v => (v >= 0 ? '+' : '') + v.toFixed(3))
return (
<Plot
data={[{
type: 'bar', orientation: 'h',
y: names, x: vs,
marker: { color: colors, line: { color: '#1f1d1a', width: 1 } },
text: labels, textposition: 'outside', cliponaxis: false,
textfont: { color: '#f3f0e8', size: 11 },
hovertemplate: '%{y}<br>contribution=%{x:+.3f}<extra></extra>',
}]}
layout={{
...PLOTLY_BASE,
title: {
text: `Reward breakdown · total = ${(total >= 0 ? '+' : '') + total.toFixed(3)}`,
x: 0.02, xanchor: 'left',
font: { size: 14, color: '#f3f0e8' },
},
height: 260, margin: { l: 160, r: 50, t: 50, b: 30 },
xaxis: {
title: 'contribution to total reward',
range: [Math.min(...vs, 0) - 0.15, Math.max(...vs, 0) + 0.15],
...AXIS,
},
yaxis: { autorange: 'reversed', ...AXIS },
showlegend: false, bargap: 0.25,
shapes: [{
type: 'line', x0: 0, x1: 0, y0: -0.5, y1: names.length - 0.5,
line: { color: '#554e45', width: 1 },
}],
}}
config={{ displayModeBar: false, responsive: true }}
style={{ width: '100%' }}
useResizeHandler
/>
)
}
|