Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files
frontend/package-lock.json
CHANGED
|
@@ -8,6 +8,7 @@
|
|
| 8 |
"name": "landscapeforge-frontend",
|
| 9 |
"version": "0.1.0",
|
| 10 |
"dependencies": {
|
|
|
|
| 11 |
"lucide-react": "^0.460.0",
|
| 12 |
"plotly.js-basic-dist-min": "^2.35.0",
|
| 13 |
"react": "^18.3.1",
|
|
@@ -3221,6 +3222,15 @@
|
|
| 3221 |
"node": ">= 0.4"
|
| 3222 |
}
|
| 3223 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3224 |
"node_modules/iconv-lite": {
|
| 3225 |
"version": "0.4.24",
|
| 3226 |
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
|
|
|
| 8 |
"name": "landscapeforge-frontend",
|
| 9 |
"version": "0.1.0",
|
| 10 |
"dependencies": {
|
| 11 |
+
"highlight.js": "^11.11.1",
|
| 12 |
"lucide-react": "^0.460.0",
|
| 13 |
"plotly.js-basic-dist-min": "^2.35.0",
|
| 14 |
"react": "^18.3.1",
|
|
|
|
| 3222 |
"node": ">= 0.4"
|
| 3223 |
}
|
| 3224 |
},
|
| 3225 |
+
"node_modules/highlight.js": {
|
| 3226 |
+
"version": "11.11.1",
|
| 3227 |
+
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
|
| 3228 |
+
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
|
| 3229 |
+
"license": "BSD-3-Clause",
|
| 3230 |
+
"engines": {
|
| 3231 |
+
"node": ">=12.0.0"
|
| 3232 |
+
}
|
| 3233 |
+
},
|
| 3234 |
"node_modules/iconv-lite": {
|
| 3235 |
"version": "0.4.24",
|
| 3236 |
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
frontend/package.json
CHANGED
|
@@ -9,6 +9,7 @@
|
|
| 9 |
"preview": "vite preview"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
|
|
|
| 12 |
"lucide-react": "^0.460.0",
|
| 13 |
"plotly.js-basic-dist-min": "^2.35.0",
|
| 14 |
"react": "^18.3.1",
|
|
|
|
| 9 |
"preview": "vite preview"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
| 12 |
+
"highlight.js": "^11.11.1",
|
| 13 |
"lucide-react": "^0.460.0",
|
| 14 |
"plotly.js-basic-dist-min": "^2.35.0",
|
| 15 |
"react": "^18.3.1",
|
frontend/src/components/CodeBlock.jsx
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useEffect, useRef } from 'react'
|
| 2 |
+
import hljs from 'highlight.js/lib/core'
|
| 3 |
+
import python from 'highlight.js/lib/languages/python'
|
| 4 |
+
import json from 'highlight.js/lib/languages/json'
|
| 5 |
+
import 'highlight.js/styles/atom-one-dark.css'
|
| 6 |
+
|
| 7 |
+
hljs.registerLanguage('python', python)
|
| 8 |
+
hljs.registerLanguage('json', json)
|
| 9 |
+
|
| 10 |
+
/**
|
| 11 |
+
* CodeBlock — a syntax-highlighted <pre><code> block.
|
| 12 |
+
*
|
| 13 |
+
* Dark, compact styling tuned to match the Claude-ish palette. Uses hljs's
|
| 14 |
+
* atom-one-dark theme then overrides the background with our canvas so it
|
| 15 |
+
* blends with the card surface.
|
| 16 |
+
*/
|
| 17 |
+
export function CodeBlock({ code, language = 'python', className = '' }) {
|
| 18 |
+
const ref = useRef(null)
|
| 19 |
+
|
| 20 |
+
useEffect(() => {
|
| 21 |
+
if (ref.current) {
|
| 22 |
+
// Remove the hljs "highlighted" marker so reruns pick up the new code
|
| 23 |
+
delete ref.current.dataset.highlighted
|
| 24 |
+
hljs.highlightElement(ref.current)
|
| 25 |
+
}
|
| 26 |
+
}, [code, language])
|
| 27 |
+
|
| 28 |
+
return (
|
| 29 |
+
<pre className={`rounded-lg border border-border overflow-x-auto
|
| 30 |
+
bg-[#14120f] my-1 ${className}`}>
|
| 31 |
+
<code ref={ref} className={`language-${language} block p-4 text-[0.82rem]
|
| 32 |
+
leading-relaxed font-mono !bg-transparent`}>
|
| 33 |
+
{code}
|
| 34 |
+
</code>
|
| 35 |
+
</pre>
|
| 36 |
+
)
|
| 37 |
+
}
|
frontend/src/components/RewardBreakdown.jsx
CHANGED
|
@@ -12,17 +12,36 @@ const AXIS = {
|
|
| 12 |
tickfont: { color: '#b5ada0' },
|
| 13 |
}
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
export function RewardBreakdown({ breakdown, total }) {
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
const names = Object.keys(components)
|
| 25 |
-
const vs = names.map(n => components[n])
|
| 26 |
const colors = vs.map(v => v >= 0 ? '#3d6b4c' : '#a0483a')
|
| 27 |
const labels = vs.map(v => (v >= 0 ? '+' : '') + v.toFixed(3))
|
| 28 |
|
|
@@ -43,9 +62,9 @@ export function RewardBreakdown({ breakdown, total }) {
|
|
| 43 |
x: 0.02, xanchor: 'left',
|
| 44 |
font: { size: 14, color: '#f3f0e8' },
|
| 45 |
},
|
| 46 |
-
height: 260, margin: { l:
|
| 47 |
xaxis: {
|
| 48 |
-
title: '
|
| 49 |
range: [Math.min(...vs, 0) - 0.15, Math.max(...vs, 0) + 0.15],
|
| 50 |
...AXIS,
|
| 51 |
},
|
|
|
|
| 12 |
tickfont: { color: '#b5ada0' },
|
| 13 |
}
|
| 14 |
|
| 15 |
+
// Per-component weights from rewards.py. Breakdown bars show weighted
|
| 16 |
+
// contributions (sum → total reward) rather than raw component values, so
|
| 17 |
+
// the chart is directly readable as "which components are hurting / helping".
|
| 18 |
+
const WEIGHTS = {
|
| 19 |
+
r_regret: 1.0,
|
| 20 |
+
r_convergence: 0.3,
|
| 21 |
+
r_robustness: 0.3,
|
| 22 |
+
r_novelty: 0.1,
|
| 23 |
+
r_budget: -0.05, // subtractive
|
| 24 |
+
r_eval_failures: -0.5, // subtractive
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
const DISPLAY_NAMES = {
|
| 28 |
+
r_regret: 'regret (×1.0)',
|
| 29 |
+
r_convergence: 'convergence (×0.3)',
|
| 30 |
+
r_robustness: 'robustness (×0.3)',
|
| 31 |
+
r_novelty: 'novelty (×0.1)',
|
| 32 |
+
r_budget: 'budget (−0.05×)',
|
| 33 |
+
r_eval_failures: 'eval crashes (−0.5×)',
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
export function RewardBreakdown({ breakdown, total }) {
|
| 37 |
+
// Weighted contributions — sum to the terminal reward.
|
| 38 |
+
const entries = Object.entries(WEIGHTS).map(([k, w]) => ({
|
| 39 |
+
key: k,
|
| 40 |
+
label: DISPLAY_NAMES[k],
|
| 41 |
+
value: (breakdown[k] ?? 0) * w,
|
| 42 |
+
}))
|
| 43 |
+
const names = entries.map(e => e.label)
|
| 44 |
+
const vs = entries.map(e => e.value)
|
|
|
|
|
|
|
| 45 |
const colors = vs.map(v => v >= 0 ? '#3d6b4c' : '#a0483a')
|
| 46 |
const labels = vs.map(v => (v >= 0 ? '+' : '') + v.toFixed(3))
|
| 47 |
|
|
|
|
| 62 |
x: 0.02, xanchor: 'left',
|
| 63 |
font: { size: 14, color: '#f3f0e8' },
|
| 64 |
},
|
| 65 |
+
height: 260, margin: { l: 160, r: 50, t: 50, b: 30 },
|
| 66 |
xaxis: {
|
| 67 |
+
title: 'contribution to total reward',
|
| 68 |
range: [Math.min(...vs, 0) - 0.15, Math.max(...vs, 0) + 0.15],
|
| 69 |
...AXIS,
|
| 70 |
},
|
frontend/src/components/TurnCard.jsx
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
|
|
|
|
|
| 1 |
const KIND_STYLES = {
|
| 2 |
draft: 'text-accent border-accent',
|
| 3 |
run_baseline: 'text-[#7ecfc5] border-[#5a9c94]',
|
|
@@ -30,10 +32,9 @@ export function TurnCard({ turn, kind, action_str, output, duration_s,
|
|
| 30 |
</Row>
|
| 31 |
|
| 32 |
{code && (
|
| 33 |
-
<
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
</pre>
|
| 37 |
)}
|
| 38 |
</div>
|
| 39 |
)
|
|
|
|
| 1 |
+
import { CodeBlock } from './CodeBlock.jsx'
|
| 2 |
+
|
| 3 |
const KIND_STYLES = {
|
| 4 |
draft: 'text-accent border-accent',
|
| 5 |
run_baseline: 'text-[#7ecfc5] border-[#5a9c94]',
|
|
|
|
| 32 |
</Row>
|
| 33 |
|
| 34 |
{code && (
|
| 35 |
+
<div className="mt-3">
|
| 36 |
+
<CodeBlock code={code.trim()} language="python" />
|
| 37 |
+
</div>
|
|
|
|
| 38 |
)}
|
| 39 |
</div>
|
| 40 |
)
|
frontend/src/pages/ApiPlayground.jsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import { useState } from 'react'
|
| 2 |
import { envReset, envStep } from '../lib/api.js'
|
|
|
|
| 3 |
|
| 4 |
const SAMPLE_CODE = `class Optimizer:
|
| 5 |
def __init__(self, dim):
|
|
@@ -130,11 +131,11 @@ export function ApiPlayground() {
|
|
| 130 |
|
| 131 |
<div className="space-y-3">
|
| 132 |
<div className="text-sm text-muted font-mono">{status}</div>
|
| 133 |
-
<
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
</div>
|
| 139 |
</div>
|
| 140 |
)
|
|
|
|
| 1 |
import { useState } from 'react'
|
| 2 |
import { envReset, envStep } from '../lib/api.js'
|
| 3 |
+
import { CodeBlock } from '../components/CodeBlock.jsx'
|
| 4 |
|
| 5 |
const SAMPLE_CODE = `class Optimizer:
|
| 6 |
def __init__(self, dim):
|
|
|
|
| 131 |
|
| 132 |
<div className="space-y-3">
|
| 133 |
<div className="text-sm text-muted font-mono">{status}</div>
|
| 134 |
+
<CodeBlock
|
| 135 |
+
code={obs ? JSON.stringify(obs, null, 2) : '// hit Reset to begin'}
|
| 136 |
+
language="json"
|
| 137 |
+
className="max-h-[640px] overflow-y-auto"
|
| 138 |
+
/>
|
| 139 |
</div>
|
| 140 |
</div>
|
| 141 |
)
|
frontend/src/pages/RunWithLlm.jsx
CHANGED
|
@@ -212,6 +212,9 @@ function RangeRow({ label, min, max, step, value, onChange }) {
|
|
| 212 |
function EpisodeDone({ done }) {
|
| 213 |
const reward = done.reward
|
| 214 |
const speedup = done.speedup_vs_adam
|
|
|
|
|
|
|
|
|
|
| 215 |
const rewardTone =
|
| 216 |
reward >= 0.5 ? 'good' : reward >= 0 ? 'warn' : 'bad'
|
| 217 |
const speedupTone = speedup >= 1.0 ? 'good' : 'warn'
|
|
@@ -219,6 +222,13 @@ function EpisodeDone({ done }) {
|
|
| 219 |
? `${speedup.toFixed(2)}×`
|
| 220 |
: `${Math.round(speedup)}×`
|
| 221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
return (
|
| 223 |
<div className="card"
|
| 224 |
style={{ background: 'linear-gradient(180deg, rgba(226,135,99,0.07) 0%, rgba(42,40,36,0) 60%)' }}>
|
|
@@ -232,13 +242,26 @@ function EpisodeDone({ done }) {
|
|
| 232 |
</div>
|
| 233 |
|
| 234 |
<div className="grid grid-cols-3 gap-3 mb-5">
|
| 235 |
-
<KpiCard
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
</div>
|
| 243 |
|
| 244 |
<RewardBreakdown breakdown={done.breakdown} total={reward} />
|
|
|
|
| 212 |
function EpisodeDone({ done }) {
|
| 213 |
const reward = done.reward
|
| 214 |
const speedup = done.speedup_vs_adam
|
| 215 |
+
const myProg = done.my_progress
|
| 216 |
+
const adamProg = done.adam_progress
|
| 217 |
+
|
| 218 |
const rewardTone =
|
| 219 |
reward >= 0.5 ? 'good' : reward >= 0 ? 'warn' : 'bad'
|
| 220 |
const speedupTone = speedup >= 1.0 ? 'good' : 'warn'
|
|
|
|
| 222 |
? `${speedup.toFixed(2)}×`
|
| 223 |
: `${Math.round(speedup)}×`
|
| 224 |
|
| 225 |
+
// Verdict: how does this compare to Adam?
|
| 226 |
+
let verdict = 'Matches Adam'
|
| 227 |
+
let verdictTone = 'warn'
|
| 228 |
+
if (speedup >= 1.5) { verdict = 'Beats Adam'; verdictTone = 'good' }
|
| 229 |
+
else if (speedup >= 1.1) { verdict = 'Edges Adam'; verdictTone = 'good' }
|
| 230 |
+
else if (speedup < 0.9) { verdict = 'Behind Adam'; verdictTone = 'bad' }
|
| 231 |
+
|
| 232 |
return (
|
| 233 |
<div className="card"
|
| 234 |
style={{ background: 'linear-gradient(180deg, rgba(226,135,99,0.07) 0%, rgba(42,40,36,0) 60%)' }}>
|
|
|
|
| 242 |
</div>
|
| 243 |
|
| 244 |
<div className="grid grid-cols-3 gap-3 mb-5">
|
| 245 |
+
<KpiCard
|
| 246 |
+
label="Reward"
|
| 247 |
+
value={reward.toFixed(3)}
|
| 248 |
+
sub="GRPO scalar · range [−1.5, +1.8]"
|
| 249 |
+
tone={rewardTone}
|
| 250 |
+
sign={reward >= 0 ? '+' : ''} />
|
| 251 |
+
<KpiCard
|
| 252 |
+
label="Speedup vs Adam"
|
| 253 |
+
value={speedupDisplay}
|
| 254 |
+
sub={`descent ${myProg.toFixed(2)} vs Adam ${adamProg.toFixed(2)}`}
|
| 255 |
+
tone={speedupTone} />
|
| 256 |
+
<KpiCard
|
| 257 |
+
label="Verdict"
|
| 258 |
+
value={verdict}
|
| 259 |
+
sub={verdict === 'Behind Adam'
|
| 260 |
+
? `lost ${(100 * (1 - speedup)).toFixed(0)}% of Adam's ground`
|
| 261 |
+
: verdict === 'Beats Adam'
|
| 262 |
+
? `${((speedup - 1) * 100).toFixed(0)}% further than Adam`
|
| 263 |
+
: 'within ±10% of Adam'}
|
| 264 |
+
tone={verdictTone} />
|
| 265 |
</div>
|
| 266 |
|
| 267 |
<RewardBreakdown breakdown={done.breakdown} total={reward} />
|