This commit is contained in:
@@ -3,27 +3,27 @@ import { Banner, Button, Spin, TextArea, Toast } from "@douyinfe/semi-ui-19";
|
||||
import { api, formatTime, jobStateLabels, post } from "../api";
|
||||
import type { Job } from "../types";
|
||||
|
||||
type Description = {
|
||||
idea: string;
|
||||
data_rationale: string;
|
||||
operator_rationale: string;
|
||||
};
|
||||
type Submission = {
|
||||
snapshot: string;
|
||||
sections: Record<string, { code: string | null; description: string }>;
|
||||
descriptions: Record<string, Description>;
|
||||
descriptions: Record<string, string>;
|
||||
model: string;
|
||||
can_generate: boolean;
|
||||
can_check: boolean;
|
||||
job: Job | null;
|
||||
};
|
||||
const fields = [
|
||||
["idea", "Idea"],
|
||||
["data_rationale", "Rationale for data used"],
|
||||
["operator_rationale", "Rationale for operators used"],
|
||||
] as const;
|
||||
const render = (value: Description) =>
|
||||
fields.map(([key, title]) => `${title}: ${value[key].trim()}`).join("\n");
|
||||
const validDescription = (text: string) => {
|
||||
const paragraphs = text.match(
|
||||
/^\s*Idea:\s*(.*?)\s*Rationale for data used:\s*(.*?)\s*Rationale for operators used:\s*(.*?)\s*$/s,
|
||||
);
|
||||
const length = Array.from(text).length;
|
||||
return (
|
||||
length >= 100 &&
|
||||
length <= 500 &&
|
||||
!!paragraphs &&
|
||||
paragraphs.slice(1).every((part) => part.trim())
|
||||
);
|
||||
};
|
||||
const activeStates = [
|
||||
"queued",
|
||||
"running",
|
||||
@@ -41,7 +41,7 @@ export function SubmissionPanel({
|
||||
onTask: () => void;
|
||||
}) {
|
||||
const [data, setData] = useState<Submission | null>(null);
|
||||
const [draft, setDraft] = useState<Record<string, Description>>({});
|
||||
const [draft, setDraft] = useState<Record<string, string>>({});
|
||||
const [snapshot, setSnapshot] = useState("");
|
||||
const [busy, setBusy] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
@@ -76,7 +76,7 @@ export function SubmissionPanel({
|
||||
setBusy("generate");
|
||||
setError("");
|
||||
try {
|
||||
const result = await post<{ descriptions: Record<string, Description> }>(
|
||||
const result = await post<{ descriptions: Record<string, string> }>(
|
||||
`/alphas/${id}/description/generate`,
|
||||
{ snapshot },
|
||||
);
|
||||
@@ -115,23 +115,19 @@ export function SubmissionPanel({
|
||||
const conflict = snapshot !== data.snapshot;
|
||||
const valid =
|
||||
Object.keys(draft).length > 0 &&
|
||||
Object.values(draft).every(
|
||||
(value) =>
|
||||
fields.every(([key]) => value[key].trim()) &&
|
||||
Array.from(render(value)).length >= 100,
|
||||
);
|
||||
Object.values(draft).every(validDescription);
|
||||
return (
|
||||
<div className="detail-section">
|
||||
<h3>Description 与 Check submission</h3>
|
||||
<h3>Description 与提交检查</h3>
|
||||
<p className="muted">
|
||||
AI 生成后可逐段修改。写回并检查会更新 BRAIN 的
|
||||
AI 一次生成完整的三段内容,可在下方统一修改。写回并检查会更新 BRAIN 的
|
||||
Description,随后获取平台提交检查结果,不会正式提交 Alpha。
|
||||
</p>
|
||||
{error && <Banner type="danger" description={error} />}
|
||||
{!data.can_check && (
|
||||
<Banner
|
||||
type="info"
|
||||
description="写回并检查需要待提交 Alpha,并先取得有效、样本完整且低于阈值的本地自相关结果。"
|
||||
description="写回并检查需要待提交 Alpha。有本地比较基准时,需取得有效、完整且低于阈值的自相关结果;没有本地基准时可直接继续平台检查。"
|
||||
/>
|
||||
)}
|
||||
{!data.can_generate && (
|
||||
@@ -145,7 +141,7 @@ export function SubmissionPanel({
|
||||
loading={busy === "generate"}
|
||||
disabled={!!busy || running || conflict || !data.can_generate}
|
||||
>
|
||||
AI 生成三段 Description
|
||||
AI 生成 Description
|
||||
</Button>
|
||||
{data.model && <span className="muted">模型:{data.model}</span>}
|
||||
</div>
|
||||
@@ -172,28 +168,27 @@ export function SubmissionPanel({
|
||||
</pre>
|
||||
</details>
|
||||
)}
|
||||
{fields.map(([key, title]) => (
|
||||
<label key={key}>
|
||||
{title}:
|
||||
<TextArea
|
||||
aria-label={`${section} ${title}`}
|
||||
value={value[key]}
|
||||
rows={3}
|
||||
maxCount={6000}
|
||||
disabled={!!busy || running}
|
||||
onChange={(text) => {
|
||||
dirty.current = true;
|
||||
setDraft((current) => ({
|
||||
...current,
|
||||
[section]: { ...current[section], [key]: text },
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
))}
|
||||
<label>
|
||||
完整 Description
|
||||
<TextArea
|
||||
aria-label={`${section} Description`}
|
||||
value={value}
|
||||
rows={7}
|
||||
maxCount={500}
|
||||
placeholder={
|
||||
"Idea: 策略假设\n\nRationale for data used: 数据选择理由\n\nRationale for operators used: 算子使用理由"
|
||||
}
|
||||
disabled={!!busy || running}
|
||||
onChange={(text) => {
|
||||
dirty.current = true;
|
||||
setDraft((current) => ({ ...current, [section]: text }));
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
<p className="muted">
|
||||
总长度:{Array.from(render(value)).length} 字符,至少 100
|
||||
字符(含标题和换行)。三段内容均需填写。
|
||||
总长度:{Array.from(value).length} / 500 字符;至少 100
|
||||
字符,包含标题与换行。 三个段落分别以 Idea:、Rationale for data
|
||||
used:、Rationale for operators used: 开头。
|
||||
</p>
|
||||
</section>
|
||||
))}
|
||||
@@ -222,7 +217,7 @@ export function SubmissionPanel({
|
||||
<div role="status">
|
||||
<p>
|
||||
最近任务:{jobStateLabels[data.job.status] ?? data.job.status}
|
||||
{data.job.status === "completed" && ",请在“指标与检查”查看结果"}
|
||||
{data.job.status === "completed" && ",请在“指标”查看结果"}
|
||||
{data.job.next_retry_at &&
|
||||
` · 下次轮询:${formatTime(data.job.next_retry_at)}`}
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user