Refactor pipeline and assistant page components for improved structure and performance
- Remove unused imports and classes from pipeline.py to streamline the codebase. - Consolidate dynamic variable handling and workflow management in AssistantPage, enhancing clarity and maintainability. - Update WorkflowEditor to utilize a more modular approach, improving the overall architecture and reducing complexity. - Enhance the import structure across components for better organization and readability.
This commit is contained in:
302
frontend/src/components/assistant-editor/prompt-editor.tsx
Normal file
302
frontend/src/components/assistant-editor/prompt-editor.tsx
Normal file
@@ -0,0 +1,302 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Bot,
|
||||
Brain,
|
||||
Database,
|
||||
Loader2,
|
||||
MessageSquareText,
|
||||
Save,
|
||||
Sparkles,
|
||||
Wrench,
|
||||
} from "lucide-react";
|
||||
|
||||
import { DebugDrawer } from "@/components/assistant-editor/debug-preview";
|
||||
import {
|
||||
DynamicVariableEditorHint,
|
||||
DynamicVariablesDialog,
|
||||
} from "@/components/assistant-editor/dynamic-variables";
|
||||
import {
|
||||
AssistantIdentity,
|
||||
EditableTitle,
|
||||
EditorBackButton,
|
||||
KnowledgeRetrievalConfigDialog,
|
||||
ResourceSelectField,
|
||||
RuntimeModeSelector,
|
||||
TextAreaField,
|
||||
ToggleRow,
|
||||
ToolPicker,
|
||||
} from "@/components/assistant-editor/editor-controls";
|
||||
import type { AssistantForm } from "@/components/assistant-editor/types";
|
||||
import { SectionCard } from "@/components/editor/section-card";
|
||||
import { TurnConfigEditor } from "@/components/turn-config-editor";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { DynamicVariableDefinition, Tool } from "@/lib/api";
|
||||
|
||||
type ResourceOption = { value: string; label: string };
|
||||
|
||||
type PromptEditorProps = {
|
||||
assistantId: string | null;
|
||||
form: AssistantForm;
|
||||
dynamicVariablesOpen: boolean;
|
||||
dynamicVariableDefinitions: Record<string, DynamicVariableDefinition>;
|
||||
saving: boolean;
|
||||
dirty: boolean;
|
||||
saveError: string | null;
|
||||
llmOptions: ResourceOption[];
|
||||
asrOptions: ResourceOption[];
|
||||
ttsOptions: ResourceOption[];
|
||||
realtimeOptions: ResourceOption[];
|
||||
visionModelOptions: ResourceOption[];
|
||||
knowledgeOptions: ResourceOption[];
|
||||
tools: Tool[];
|
||||
onBack: () => void;
|
||||
onSave: () => void;
|
||||
setDynamicVariablesOpen: (open: boolean) => void;
|
||||
updateForm: <K extends keyof AssistantForm>(
|
||||
key: K,
|
||||
value: AssistantForm[K],
|
||||
) => void;
|
||||
handlePromptVisionEnabledChange: (enabled: boolean) => void;
|
||||
handlePromptModelChange: (value: string) => void;
|
||||
};
|
||||
|
||||
export function PromptEditor({
|
||||
assistantId,
|
||||
form,
|
||||
dynamicVariablesOpen,
|
||||
dynamicVariableDefinitions,
|
||||
saving,
|
||||
dirty,
|
||||
saveError,
|
||||
llmOptions,
|
||||
asrOptions,
|
||||
ttsOptions,
|
||||
realtimeOptions,
|
||||
visionModelOptions,
|
||||
knowledgeOptions: kbOptions,
|
||||
tools,
|
||||
onBack,
|
||||
onSave,
|
||||
setDynamicVariablesOpen,
|
||||
updateForm,
|
||||
handlePromptVisionEnabledChange,
|
||||
handlePromptModelChange,
|
||||
}: PromptEditorProps) {
|
||||
return (
|
||||
<div className="-mt-6 flex h-full flex-col gap-4">
|
||||
<div className="flex shrink-0 items-center justify-between gap-6 border-b border-hairline pb-3 pt-1">
|
||||
<div className="flex min-w-0 items-center gap-2">
|
||||
<EditorBackButton onClick={onBack} />
|
||||
<EditableTitle
|
||||
value={form.name}
|
||||
onChange={(value) => updateForm("name", value)}
|
||||
/>
|
||||
<AssistantIdentity assistantId={assistantId} />
|
||||
</div>
|
||||
|
||||
<div className="flex shrink-0 gap-2">
|
||||
{saveError && (
|
||||
<span className="self-center text-xs text-destructive">
|
||||
{saveError}
|
||||
</span>
|
||||
)}
|
||||
<Button
|
||||
className="gap-2"
|
||||
disabled={saving || !dirty || !form.name.trim()}
|
||||
onClick={() => onSave()}
|
||||
>
|
||||
{saving ? (
|
||||
<Loader2 size={16} className="animate-spin" />
|
||||
) : (
|
||||
<Save size={16} />
|
||||
)}
|
||||
保存
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DynamicVariablesDialog
|
||||
open={dynamicVariablesOpen}
|
||||
onOpenChange={setDynamicVariablesOpen}
|
||||
definitions={dynamicVariableDefinitions}
|
||||
onChange={(dynamicVariableDefinitions) =>
|
||||
updateForm(
|
||||
"dynamicVariableDefinitions",
|
||||
dynamicVariableDefinitions,
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="flex min-h-0 flex-1 gap-4">
|
||||
<div className="scrollbar-subtle min-w-0 flex-1 space-y-3 overflow-y-auto pr-1">
|
||||
<SectionCard
|
||||
icon={<MessageSquareText size={15} />}
|
||||
title="提示词"
|
||||
description="描述助手的角色、能力和回答要求"
|
||||
>
|
||||
<TextAreaField
|
||||
value={form.prompt}
|
||||
onChange={(value) => updateForm("prompt", value)}
|
||||
placeholder="请输入提示词,描述助手的角色、能力和回答要求"
|
||||
rows={8}
|
||||
/>
|
||||
<DynamicVariableEditorHint
|
||||
count={Object.keys(dynamicVariableDefinitions).length}
|
||||
onOpen={() => setDynamicVariablesOpen(true)}
|
||||
/>
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Bot size={15} />}
|
||||
title="开场白"
|
||||
description="助手与用户首次对话时的开场语"
|
||||
>
|
||||
<TextAreaField
|
||||
value={form.greeting}
|
||||
onChange={(value) => updateForm("greeting", value)}
|
||||
placeholder="请输入助手开场白"
|
||||
/>
|
||||
<DynamicVariableEditorHint
|
||||
count={Object.keys(dynamicVariableDefinitions).length}
|
||||
onOpen={() => setDynamicVariablesOpen(true)}
|
||||
/>
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Brain size={15} />}
|
||||
title="模型配置"
|
||||
description={
|
||||
form.runtimeMode === "pipeline"
|
||||
? "选择运行方式,以及大语言模型、语音识别与语音合成资源"
|
||||
: "选择运行方式;Realtime 模型内置语音识别与语音合成"
|
||||
}
|
||||
>
|
||||
<RuntimeModeSelector
|
||||
value={form.runtimeMode}
|
||||
onChange={(runtimeMode) => updateForm("runtimeMode", runtimeMode)}
|
||||
/>
|
||||
|
||||
{form.runtimeMode === "pipeline" ? (
|
||||
<>
|
||||
<ToggleRow
|
||||
title="视觉理解"
|
||||
hint="开启后,开始对话时会允许助手按需理解当前视频画面。视觉模型选「模型自己」时,大语言模型本身必须支持图片输入。"
|
||||
checked={form.visionEnabled}
|
||||
onChange={handlePromptVisionEnabledChange}
|
||||
/>
|
||||
{form.visionEnabled && (
|
||||
<ResourceSelectField
|
||||
label="视觉模型"
|
||||
value={form.visionModelResourceId}
|
||||
onChange={(value) =>
|
||||
updateForm("visionModelResourceId", value)
|
||||
}
|
||||
options={visionModelOptions}
|
||||
noneLabel="模型自己"
|
||||
/>
|
||||
)}
|
||||
<ResourceSelectField
|
||||
label="大语言模型"
|
||||
value={form.model}
|
||||
onChange={handlePromptModelChange}
|
||||
options={llmOptions}
|
||||
noneLabel="无"
|
||||
/>
|
||||
<ResourceSelectField
|
||||
label="语音识别"
|
||||
value={form.asr}
|
||||
onChange={(value) => updateForm("asr", value)}
|
||||
options={asrOptions}
|
||||
noneLabel="无"
|
||||
/>
|
||||
<ResourceSelectField
|
||||
label="语音合成"
|
||||
value={form.voice}
|
||||
onChange={(value) => updateForm("voice", value)}
|
||||
options={ttsOptions}
|
||||
noneLabel="无"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<ResourceSelectField
|
||||
label="Realtime 模型"
|
||||
value={form.realtimeModel}
|
||||
onChange={(value) => updateForm("realtimeModel", value)}
|
||||
options={realtimeOptions}
|
||||
noneLabel="无"
|
||||
/>
|
||||
)}
|
||||
</SectionCard>
|
||||
|
||||
{form.runtimeMode === "pipeline" && (
|
||||
<SectionCard
|
||||
icon={<Database size={15} />}
|
||||
title="知识库配置"
|
||||
description="选择助手回答时可检索的业务知识来源"
|
||||
>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
知识库选择
|
||||
</span>
|
||||
<KnowledgeRetrievalConfigDialog
|
||||
disabled={!form.knowledgeBase}
|
||||
value={form.knowledgeRetrievalConfig}
|
||||
onChange={(config) =>
|
||||
updateForm("knowledgeRetrievalConfig", config)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<ResourceSelectField
|
||||
value={form.knowledgeBase}
|
||||
onChange={(value) => updateForm("knowledgeBase", value)}
|
||||
options={kbOptions}
|
||||
noneLabel="无"
|
||||
/>
|
||||
</SectionCard>
|
||||
)}
|
||||
|
||||
<SectionCard
|
||||
icon={<Wrench size={15} />}
|
||||
title="工具"
|
||||
description="配置该提示词助手可以调用的工具"
|
||||
>
|
||||
<ToolPicker
|
||||
tools={tools.filter((tool) => tool.status === "active")}
|
||||
selectedIds={form.toolIds}
|
||||
onChange={(toolIds) => updateForm("toolIds", toolIds)}
|
||||
/>
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Sparkles size={15} />}
|
||||
title="交互策略"
|
||||
description="设置实时视频对话时的交互体验"
|
||||
>
|
||||
{form.runtimeMode === "pipeline" ? (
|
||||
<TurnConfigEditor
|
||||
enabled={form.enableInterrupt}
|
||||
config={form.turnConfig}
|
||||
onEnabledChange={(checked) => updateForm("enableInterrupt", checked)}
|
||||
onConfigChange={(config) => updateForm("turnConfig", config)}
|
||||
/>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
高级抢话与轮次检测当前仅支持 Pipeline 模式。
|
||||
</p>
|
||||
)}
|
||||
</SectionCard>
|
||||
</div>
|
||||
|
||||
<DebugDrawer
|
||||
assistantId={assistantId}
|
||||
hasUnsavedChanges={dirty}
|
||||
vision={form.visionEnabled}
|
||||
dynamicVariablesEnabled
|
||||
dynamicVariableDefinitions={dynamicVariableDefinitions}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user