refactor: release v1.0.5 安全精简与网站发布
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
import { Download, Square } from 'lucide-react';
|
||||
import { Badge, Button, ProgressBar, PropertyRow } from '../components/ui';
|
||||
import type { MobileDeployment } from '../mobile/training';
|
||||
import { PretrainedIdentity } from './PretrainedSourceSelect';
|
||||
import { TrainingMetricsPanel } from './TrainingMetricsPanel';
|
||||
import { trainingLosses } from './trainingLosses';
|
||||
import { ACTIVE_STATES, stateLabel } from './trainingPresentation';
|
||||
import type { TrainingJob } from './types';
|
||||
|
||||
export function TrainingJobSection({
|
||||
job,
|
||||
mobileDeployment,
|
||||
busy,
|
||||
onContinue,
|
||||
onCancel,
|
||||
onImport,
|
||||
onNew,
|
||||
}: {
|
||||
job: TrainingJob;
|
||||
mobileDeployment?: MobileDeployment;
|
||||
busy: boolean;
|
||||
onContinue(): void;
|
||||
onCancel(): void | Promise<void>;
|
||||
onImport(): void | Promise<void>;
|
||||
onNew(): void;
|
||||
}) {
|
||||
const active = ACTIVE_STATES.has(job.state);
|
||||
return (
|
||||
<div className="mt-3 border-t border-border pt-3">
|
||||
<div className="mb-2 flex items-center justify-between gap-2">
|
||||
<span className="truncate text-xs font-medium text-text-primary" title={job.id}>
|
||||
{job.taskId}
|
||||
</span>
|
||||
<Badge
|
||||
tone={
|
||||
job.state === 'succeeded'
|
||||
? 'success'
|
||||
: job.state === 'failed' || job.state === 'cancelled'
|
||||
? 'warning'
|
||||
: 'accent'
|
||||
}
|
||||
>
|
||||
{stateLabel(job.state)}
|
||||
</Badge>
|
||||
</div>
|
||||
<PretrainedIdentity source={job.pretrained} />
|
||||
{mobileDeployment?.evaluation && (
|
||||
<div className="mt-2 text-xs">
|
||||
<PropertyRow label="阶段" value={mobileDeployment.trainingStage} />
|
||||
<PropertyRow
|
||||
label="独立评估成功率"
|
||||
value={`${(mobileDeployment.evaluation.successRate * 100).toFixed(1)}% / ${mobileDeployment.evaluation.episodes} 回合`}
|
||||
/>
|
||||
<PropertyRow
|
||||
label="实测关节峰值"
|
||||
value={`${mobileDeployment.evaluation.maxJointVelocity.toFixed(3)} rad/s`}
|
||||
/>
|
||||
<PropertyRow label="安全终止次数" value={mobileDeployment.evaluation.safetyStops} />
|
||||
<p className="text-warning">
|
||||
导出成功不代表策略达标;未达标策略导入仅用于调试,请先同阶段续训。
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{job.taskId === 'Unitree-Go2-Rough' && (
|
||||
<div>
|
||||
<p className="text-xs text-warning">仅后端评测:234 维 Rough 策略无法在浏览器加载。</p>
|
||||
</div>
|
||||
)}
|
||||
{job.deployment?.terrain && (
|
||||
<div>
|
||||
<p className="text-xs text-warning">
|
||||
导入会替换当前物理地图并启动配套策略,请先保存场景。
|
||||
</p>
|
||||
<Badge tone="warning">
|
||||
{job.deployment.terrain.approximation ? '近似碰撞布局' : '配套碰撞布局'}
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
<ProgressBar value={job.progress} label="训练进度" />
|
||||
<div className="mt-2">
|
||||
<PropertyRow label="迭代" value={`${job.iteration} / ${job.maxIterations}`} />
|
||||
<p role="status" className="break-words text-xs text-text-secondary">
|
||||
{job.message}
|
||||
</p>
|
||||
{trainingLosses(job.logs).map(({ label, value }) => (
|
||||
<PropertyRow key={label} label={label} value={value} />
|
||||
))}
|
||||
</div>
|
||||
<TrainingMetricsPanel key={job.id} jobId={job.id} logs={job.logs} />
|
||||
{job.logs.length > 0 && (
|
||||
<details className="mt-2">
|
||||
<summary className="cursor-pointer text-xs text-text-secondary">最近日志</summary>
|
||||
<pre className="mt-1 max-h-36 overflow-auto whitespace-pre-wrap break-all rounded bg-app p-2 text-xs leading-4 text-text-tertiary">
|
||||
{job.logs.slice(-40).join('\n')}
|
||||
</pre>
|
||||
</details>
|
||||
)}
|
||||
{mobileDeployment && job.state === 'succeeded' && (
|
||||
<Button disabled={busy} onClick={onContinue}>
|
||||
接续此作业(保留权重)
|
||||
</Button>
|
||||
)}
|
||||
<div className="mt-3 grid grid-cols-2 gap-2">
|
||||
{active ? (
|
||||
<Button
|
||||
variant="danger"
|
||||
className="col-span-2"
|
||||
icon={<Square className="h-3.5 w-3.5" />}
|
||||
disabled={busy}
|
||||
onClick={() => void onCancel()}
|
||||
>
|
||||
停止训练
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
disabled={
|
||||
busy ||
|
||||
!job.artifactReady ||
|
||||
job.taskId === 'Unitree-Go2-Rough' ||
|
||||
(job.deployment && !job.deployment.browserCompatible)
|
||||
}
|
||||
icon={<Download className="h-3.5 w-3.5" />}
|
||||
onClick={() => void onImport()}
|
||||
>
|
||||
导入策略
|
||||
</Button>
|
||||
<Button disabled={busy} onClick={onNew}>
|
||||
新建任务
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user