feat: 使用 Semi AI 组件升级研究助手与研究入口

This commit is contained in:
yuxuanhui
2026-09-10 12:22:26 +08:00
parent 9334b6f651
commit d403008f9b
16 changed files with 974 additions and 174 deletions
+43 -26
View File
@@ -8,6 +8,8 @@ import {
TextArea,
Toast,
} from "@douyinfe/semi-ui-19";
import { ResearchInput } from "../ai/ResearchInput";
import { IconAIEditLevel3 } from "@douyinfe/semi-icons";
import { api, post } from "../api";
import type { PageContext, UIAction } from "../ai/types";
import { TemplateEditor } from "./TemplateEditor";
@@ -210,6 +212,7 @@ export function FeaturesPage({
)}
</ResearchList>
<ResearchDetail
width="min(100vw, max(640px, 60vw))"
title={asset ? asset.name : "新建特征方案"}
visible={active && detailOpen}
onClose={() => setDetailOpen(false)}
@@ -246,14 +249,49 @@ export function FeaturesPage({
onChange={(name) => setDraft({ ...draft, name })}
/>
</label>
<label>
经济假设
<TextArea
aria-label="特征经济假设"
<section className="research-ai-section">
<h4>
<IconAIEditLevel3 aria-hidden="true" />
经济假设
</h4>
<ResearchInput
maxLength={10000}
label="特征经济假设"
value={draft.hypothesis}
onChange={(hypothesis) => setDraft({ ...draft, hypothesis })}
placeholder="描述特征的经济含义、处理方式和预期信号…"
references={inputs
.filter((i) => draft.input_ids.includes(i.id))
.map((i) => ({
id: i.id,
name: `${i.dataset_id} · ${i.scope.region}/${i.scope.universe}/D${i.scope.delay} · ${i.field_ids.length} 字段 · ${i.id}`,
}))}
disabled={!!busy}
busy={busy === "generate"}
canSubmit={!!draft.input_ids.length}
submitLabel="AI 生成新方案"
sendHotKey="shift+enter"
onSubmit={() =>
void run("generate", async () => {
await load(
await post<FeatureAsset>("/research/generate", {
name: draft.name,
hypothesis: draft.hypothesis,
input_ids: draft.input_ids,
method: "feature",
}),
);
setRevision((n) => n + 1);
})
}
prompts={["研究字段的时序变化,构建具有经济解释的特征"]}
hint={
draft.input_ids.length
? "生成处理步骤与输出模板,保留假设供继续迭代。"
: "请先在下方关联固定输入。"
}
/>
</label>
</section>
<label>
固定输入
<ResearchSelect
@@ -394,27 +432,6 @@ export function FeaturesPage({
>
保存并转为模板
</Button>
<Button
disabled={
Boolean(busy) || !draft.input_ids.length || !draft.hypothesis
}
loading={busy === "generate"}
onClick={() =>
void run("generate", async () => {
await load(
await post<FeatureAsset>("/research/generate", {
name: draft.name,
hypothesis: draft.hypothesis,
input_ids: draft.input_ids,
method: "feature",
}),
);
setRevision((n) => n + 1);
})
}
>
AI 生成新方案
</Button>
</div>
<p className="research-hint">
保存步骤不会计算原始时间序列。转换后的模板保留此方案的完整版本,回测前仍需展开校验并确认候选。