feat: Add expert source selector UI
- Add expert source dropdown in TransformationInputPanel - Options: LLM 生成, Wikidata, ConceptNet - Shows description for each source - Pass expertSource through App -> TransformationPanel -> hook -> API - Default source remains 'llm' 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@ import { useAttribute } from './hooks/useAttribute';
|
||||
import { getModels } from './services/api';
|
||||
import type { MindmapDAGRef } from './components/MindmapDAG';
|
||||
import type { TransformationDAGRef } from './components/TransformationDAG';
|
||||
import type { CategoryMode } from './types';
|
||||
import type { CategoryMode, ExpertSource } from './types';
|
||||
|
||||
const { Header, Sider, Content } = Layout;
|
||||
const { Title } = Typography;
|
||||
@@ -44,6 +44,7 @@ function App() {
|
||||
custom_experts: undefined,
|
||||
});
|
||||
const [customExpertsInput, setCustomExpertsInput] = useState('');
|
||||
const [expertSource, setExpertSource] = useState<ExpertSource>('llm');
|
||||
const [shouldStartTransform, setShouldStartTransform] = useState(false);
|
||||
const [transformLoading, setTransformLoading] = useState(false);
|
||||
|
||||
@@ -186,6 +187,7 @@ function App() {
|
||||
model={transformModel}
|
||||
temperature={transformTemperature}
|
||||
expertConfig={expertConfig}
|
||||
expertSource={expertSource}
|
||||
shouldStartTransform={shouldStartTransform}
|
||||
onTransformComplete={() => setShouldStartTransform(false)}
|
||||
onLoadingChange={setTransformLoading}
|
||||
@@ -226,10 +228,12 @@ function App() {
|
||||
temperature={transformTemperature}
|
||||
expertConfig={expertConfig}
|
||||
customExpertsInput={customExpertsInput}
|
||||
expertSource={expertSource}
|
||||
onModelChange={setTransformModel}
|
||||
onTemperatureChange={setTransformTemperature}
|
||||
onExpertConfigChange={setExpertConfig}
|
||||
onCustomExpertsInputChange={setCustomExpertsInput}
|
||||
onExpertSourceChange={setExpertSource}
|
||||
availableModels={availableModels}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import { Card, Select, Slider, Typography, Space, Button, Divider } from 'antd';
|
||||
import { ThunderboltOutlined } from '@ant-design/icons';
|
||||
import { ExpertConfigPanel } from './transformation';
|
||||
import type { ExpertSource } from '../types';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
const EXPERT_SOURCE_OPTIONS = [
|
||||
{ label: 'LLM 生成', value: 'llm' as ExpertSource, description: '使用 AI 模型生成專家' },
|
||||
{ label: 'Wikidata', value: 'wikidata' as ExpertSource, description: '從維基數據查詢職業' },
|
||||
{ label: 'ConceptNet', value: 'conceptnet' as ExpertSource, description: '從知識圖譜查詢概念' },
|
||||
];
|
||||
|
||||
interface TransformationInputPanelProps {
|
||||
onTransform: () => void;
|
||||
loading: boolean;
|
||||
@@ -17,6 +24,7 @@ interface TransformationInputPanelProps {
|
||||
custom_experts?: string[];
|
||||
};
|
||||
customExpertsInput: string;
|
||||
expertSource: ExpertSource;
|
||||
onModelChange: (model: string) => void;
|
||||
onTemperatureChange: (temperature: number) => void;
|
||||
onExpertConfigChange: (config: {
|
||||
@@ -25,6 +33,7 @@ interface TransformationInputPanelProps {
|
||||
custom_experts?: string[];
|
||||
}) => void;
|
||||
onCustomExpertsInputChange: (value: string) => void;
|
||||
onExpertSourceChange: (source: ExpertSource) => void;
|
||||
availableModels: string[];
|
||||
}
|
||||
|
||||
@@ -37,10 +46,12 @@ export const TransformationInputPanel: React.FC<TransformationInputPanelProps> =
|
||||
temperature,
|
||||
expertConfig,
|
||||
customExpertsInput,
|
||||
expertSource,
|
||||
onModelChange,
|
||||
onTemperatureChange,
|
||||
onExpertConfigChange,
|
||||
onCustomExpertsInputChange,
|
||||
onExpertSourceChange,
|
||||
availableModels,
|
||||
}) => {
|
||||
return (
|
||||
@@ -108,6 +119,31 @@ export const TransformationInputPanel: React.FC<TransformationInputPanelProps> =
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
{/* Expert Source Selection */}
|
||||
<Card
|
||||
size="small"
|
||||
title="專家來源"
|
||||
style={{
|
||||
background: isDark ? '#1f1f1f' : '#fafafa',
|
||||
border: `1px solid ${isDark ? '#434343' : '#d9d9d9'}`,
|
||||
}}
|
||||
>
|
||||
<Space direction="vertical" size="small" style={{ width: '100%' }}>
|
||||
<Select
|
||||
value={expertSource}
|
||||
onChange={onExpertSourceChange}
|
||||
style={{ width: '100%' }}
|
||||
options={EXPERT_SOURCE_OPTIONS.map((opt) => ({
|
||||
label: opt.label,
|
||||
value: opt.value,
|
||||
}))}
|
||||
/>
|
||||
<Text type="secondary" style={{ fontSize: 11 }}>
|
||||
{EXPERT_SOURCE_OPTIONS.find((opt) => opt.value === expertSource)?.description}
|
||||
</Text>
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
{/* Expert Configuration */}
|
||||
<ExpertConfigPanel
|
||||
expertCount={expertConfig.expert_count}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { forwardRef, useMemo, useCallback, useEffect } from 'react';
|
||||
import { Empty, Spin, Button, Progress, Card, Space, Typography, Tag } from 'antd';
|
||||
import { ReloadOutlined } from '@ant-design/icons';
|
||||
import type { AttributeDAG, ExpertTransformationInput } from '../types';
|
||||
import type { AttributeDAG, ExpertTransformationInput, ExpertSource } from '../types';
|
||||
import { TransformationDAG } from './TransformationDAG';
|
||||
import type { TransformationDAGRef } from './TransformationDAG';
|
||||
import { useExpertTransformation } from '../hooks/useExpertTransformation';
|
||||
@@ -18,20 +18,21 @@ interface TransformationPanelProps {
|
||||
keywords_per_expert: number;
|
||||
custom_experts?: string[];
|
||||
};
|
||||
expertSource: ExpertSource;
|
||||
shouldStartTransform: boolean;
|
||||
onTransformComplete: () => void;
|
||||
onLoadingChange: (loading: boolean) => void;
|
||||
}
|
||||
|
||||
export const TransformationPanel = forwardRef<TransformationDAGRef, TransformationPanelProps>(
|
||||
({ attributeData, isDark, model, temperature, expertConfig, shouldStartTransform, onTransformComplete, onLoadingChange }, ref) => {
|
||||
({ attributeData, isDark, model, temperature, expertConfig, expertSource, shouldStartTransform, onTransformComplete, onLoadingChange }, ref) => {
|
||||
const {
|
||||
loading,
|
||||
progress,
|
||||
results,
|
||||
transformAll,
|
||||
clearResults,
|
||||
} = useExpertTransformation({ model, temperature });
|
||||
} = useExpertTransformation({ model, temperature, expertSource });
|
||||
|
||||
// Notify parent of loading state changes
|
||||
useEffect(() => {
|
||||
|
||||
@@ -7,11 +7,13 @@ import type {
|
||||
ExpertTransformationDAGResult,
|
||||
ExpertProfile,
|
||||
CategoryDefinition,
|
||||
ExpertSource,
|
||||
} from '../types';
|
||||
|
||||
interface UseExpertTransformationOptions {
|
||||
model?: string;
|
||||
temperature?: number;
|
||||
expertSource?: ExpertSource;
|
||||
}
|
||||
|
||||
export function useExpertTransformation(options: UseExpertTransformationOptions = {}) {
|
||||
@@ -60,6 +62,7 @@ export function useExpertTransformation(options: UseExpertTransformationOptions
|
||||
expert_count: expertConfig.expert_count,
|
||||
keywords_per_expert: expertConfig.keywords_per_expert,
|
||||
custom_experts: expertConfig.custom_experts,
|
||||
expert_source: options.expertSource,
|
||||
model: options.model,
|
||||
temperature: options.temperature,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user