234 lines
8.4 KiB
JavaScript
234 lines
8.4 KiB
JavaScript
|
|
import React from 'react';
|
|||
|
|
import {
|
|||
|
|
Input,
|
|||
|
|
Slider,
|
|||
|
|
Typography,
|
|||
|
|
Button,
|
|||
|
|
Tag,
|
|||
|
|
} from '@douyinfe/semi-ui';
|
|||
|
|
import {
|
|||
|
|
Hash,
|
|||
|
|
Thermometer,
|
|||
|
|
Target,
|
|||
|
|
Repeat,
|
|||
|
|
Ban,
|
|||
|
|
Shuffle,
|
|||
|
|
Check,
|
|||
|
|
X,
|
|||
|
|
} from 'lucide-react';
|
|||
|
|
|
|||
|
|
const ParameterControl = ({
|
|||
|
|
inputs,
|
|||
|
|
parameterEnabled,
|
|||
|
|
onInputChange,
|
|||
|
|
onParameterToggle,
|
|||
|
|
}) => {
|
|||
|
|
return (
|
|||
|
|
<>
|
|||
|
|
{/* Temperature */}
|
|||
|
|
<div className={`transition-opacity duration-200 ${!parameterEnabled.temperature ? 'opacity-50' : ''}`}>
|
|||
|
|
<div className="flex items-center justify-between mb-2">
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<Thermometer size={16} className="text-gray-500" />
|
|||
|
|
<Typography.Text strong className="text-sm">
|
|||
|
|
Temperature
|
|||
|
|
</Typography.Text>
|
|||
|
|
<Tag size="small" className="!rounded-full">
|
|||
|
|
{inputs.temperature}
|
|||
|
|
</Tag>
|
|||
|
|
</div>
|
|||
|
|
<Button
|
|||
|
|
theme={parameterEnabled.temperature ? 'solid' : 'borderless'}
|
|||
|
|
type={parameterEnabled.temperature ? 'primary' : 'tertiary'}
|
|||
|
|
size="small"
|
|||
|
|
icon={parameterEnabled.temperature ? <Check size={10} /> : <X size={10} />}
|
|||
|
|
onClick={() => onParameterToggle('temperature')}
|
|||
|
|
className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
<Typography.Text className="text-xs text-gray-500 mb-2">
|
|||
|
|
控制输出的随机性和创造性
|
|||
|
|
</Typography.Text>
|
|||
|
|
<Slider
|
|||
|
|
step={0.1}
|
|||
|
|
min={0.1}
|
|||
|
|
max={1}
|
|||
|
|
value={inputs.temperature}
|
|||
|
|
onChange={(value) => onInputChange('temperature', value)}
|
|||
|
|
className="mt-2"
|
|||
|
|
disabled={!parameterEnabled.temperature}
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Top P */}
|
|||
|
|
<div className={`transition-opacity duration-200 ${!parameterEnabled.top_p ? 'opacity-50' : ''}`}>
|
|||
|
|
<div className="flex items-center justify-between mb-2">
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<Target size={16} className="text-gray-500" />
|
|||
|
|
<Typography.Text strong className="text-sm">
|
|||
|
|
Top P
|
|||
|
|
</Typography.Text>
|
|||
|
|
<Tag size="small" className="!rounded-full">
|
|||
|
|
{inputs.top_p}
|
|||
|
|
</Tag>
|
|||
|
|
</div>
|
|||
|
|
<Button
|
|||
|
|
theme={parameterEnabled.top_p ? 'solid' : 'borderless'}
|
|||
|
|
type={parameterEnabled.top_p ? 'primary' : 'tertiary'}
|
|||
|
|
size="small"
|
|||
|
|
icon={parameterEnabled.top_p ? <Check size={10} /> : <X size={10} />}
|
|||
|
|
onClick={() => onParameterToggle('top_p')}
|
|||
|
|
className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
<Typography.Text className="text-xs text-gray-500 mb-2">
|
|||
|
|
核采样,控制词汇选择的多样性
|
|||
|
|
</Typography.Text>
|
|||
|
|
<Slider
|
|||
|
|
step={0.1}
|
|||
|
|
min={0.1}
|
|||
|
|
max={1}
|
|||
|
|
value={inputs.top_p}
|
|||
|
|
onChange={(value) => onInputChange('top_p', value)}
|
|||
|
|
className="mt-2"
|
|||
|
|
disabled={!parameterEnabled.top_p}
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Frequency Penalty */}
|
|||
|
|
<div className={`transition-opacity duration-200 ${!parameterEnabled.frequency_penalty ? 'opacity-50' : ''}`}>
|
|||
|
|
<div className="flex items-center justify-between mb-2">
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<Repeat size={16} className="text-gray-500" />
|
|||
|
|
<Typography.Text strong className="text-sm">
|
|||
|
|
Frequency Penalty
|
|||
|
|
</Typography.Text>
|
|||
|
|
<Tag size="small" className="!rounded-full">
|
|||
|
|
{inputs.frequency_penalty}
|
|||
|
|
</Tag>
|
|||
|
|
</div>
|
|||
|
|
<Button
|
|||
|
|
theme={parameterEnabled.frequency_penalty ? 'solid' : 'borderless'}
|
|||
|
|
type={parameterEnabled.frequency_penalty ? 'primary' : 'tertiary'}
|
|||
|
|
size="small"
|
|||
|
|
icon={parameterEnabled.frequency_penalty ? <Check size={10} /> : <X size={10} />}
|
|||
|
|
onClick={() => onParameterToggle('frequency_penalty')}
|
|||
|
|
className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
<Typography.Text className="text-xs text-gray-500 mb-2">
|
|||
|
|
频率惩罚,减少重复词汇的出现
|
|||
|
|
</Typography.Text>
|
|||
|
|
<Slider
|
|||
|
|
step={0.1}
|
|||
|
|
min={-2}
|
|||
|
|
max={2}
|
|||
|
|
value={inputs.frequency_penalty}
|
|||
|
|
onChange={(value) => onInputChange('frequency_penalty', value)}
|
|||
|
|
className="mt-2"
|
|||
|
|
disabled={!parameterEnabled.frequency_penalty}
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Presence Penalty */}
|
|||
|
|
<div className={`transition-opacity duration-200 ${!parameterEnabled.presence_penalty ? 'opacity-50' : ''}`}>
|
|||
|
|
<div className="flex items-center justify-between mb-2">
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<Ban size={16} className="text-gray-500" />
|
|||
|
|
<Typography.Text strong className="text-sm">
|
|||
|
|
Presence Penalty
|
|||
|
|
</Typography.Text>
|
|||
|
|
<Tag size="small" className="!rounded-full">
|
|||
|
|
{inputs.presence_penalty}
|
|||
|
|
</Tag>
|
|||
|
|
</div>
|
|||
|
|
<Button
|
|||
|
|
theme={parameterEnabled.presence_penalty ? 'solid' : 'borderless'}
|
|||
|
|
type={parameterEnabled.presence_penalty ? 'primary' : 'tertiary'}
|
|||
|
|
size="small"
|
|||
|
|
icon={parameterEnabled.presence_penalty ? <Check size={10} /> : <X size={10} />}
|
|||
|
|
onClick={() => onParameterToggle('presence_penalty')}
|
|||
|
|
className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
<Typography.Text className="text-xs text-gray-500 mb-2">
|
|||
|
|
存在惩罚,鼓励讨论新话题
|
|||
|
|
</Typography.Text>
|
|||
|
|
<Slider
|
|||
|
|
step={0.1}
|
|||
|
|
min={-2}
|
|||
|
|
max={2}
|
|||
|
|
value={inputs.presence_penalty}
|
|||
|
|
onChange={(value) => onInputChange('presence_penalty', value)}
|
|||
|
|
className="mt-2"
|
|||
|
|
disabled={!parameterEnabled.presence_penalty}
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* MaxTokens */}
|
|||
|
|
<div className={`transition-opacity duration-200 ${!parameterEnabled.max_tokens ? 'opacity-50' : ''}`}>
|
|||
|
|
<div className="flex items-center justify-between mb-2">
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<Hash size={16} className="text-gray-500" />
|
|||
|
|
<Typography.Text strong className="text-sm">
|
|||
|
|
Max Tokens
|
|||
|
|
</Typography.Text>
|
|||
|
|
</div>
|
|||
|
|
<Button
|
|||
|
|
theme={parameterEnabled.max_tokens ? 'solid' : 'borderless'}
|
|||
|
|
type={parameterEnabled.max_tokens ? 'primary' : 'tertiary'}
|
|||
|
|
size="small"
|
|||
|
|
icon={parameterEnabled.max_tokens ? <Check size={10} /> : <X size={10} />}
|
|||
|
|
onClick={() => onParameterToggle('max_tokens')}
|
|||
|
|
className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
<Input
|
|||
|
|
placeholder='MaxTokens'
|
|||
|
|
name='max_tokens'
|
|||
|
|
required
|
|||
|
|
autoComplete='new-password'
|
|||
|
|
defaultValue={0}
|
|||
|
|
value={inputs.max_tokens}
|
|||
|
|
onChange={(value) => onInputChange('max_tokens', value)}
|
|||
|
|
className="!rounded-lg"
|
|||
|
|
disabled={!parameterEnabled.max_tokens}
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Seed */}
|
|||
|
|
<div className={`transition-opacity duration-200 ${!parameterEnabled.seed ? 'opacity-50' : ''}`}>
|
|||
|
|
<div className="flex items-center justify-between mb-2">
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<Shuffle size={16} className="text-gray-500" />
|
|||
|
|
<Typography.Text strong className="text-sm">
|
|||
|
|
Seed
|
|||
|
|
</Typography.Text>
|
|||
|
|
<Typography.Text className="text-xs text-gray-400">
|
|||
|
|
(可选,用于复现结果)
|
|||
|
|
</Typography.Text>
|
|||
|
|
</div>
|
|||
|
|
<Button
|
|||
|
|
theme={parameterEnabled.seed ? 'solid' : 'borderless'}
|
|||
|
|
type={parameterEnabled.seed ? 'primary' : 'tertiary'}
|
|||
|
|
size="small"
|
|||
|
|
icon={parameterEnabled.seed ? <Check size={10} /> : <X size={10} />}
|
|||
|
|
onClick={() => onParameterToggle('seed')}
|
|||
|
|
className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
<Input
|
|||
|
|
placeholder='随机种子 (留空为随机)'
|
|||
|
|
name='seed'
|
|||
|
|
autoComplete='new-password'
|
|||
|
|
value={inputs.seed || ''}
|
|||
|
|
onChange={(value) => onInputChange('seed', value === '' ? null : value)}
|
|||
|
|
className="!rounded-lg"
|
|||
|
|
disabled={!parameterEnabled.seed}
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default ParameterControl;
|