ParameterControl.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import React from 'react';
  2. import {
  3. Input,
  4. Slider,
  5. Typography,
  6. Button,
  7. Tag,
  8. } from '@douyinfe/semi-ui';
  9. import {
  10. Hash,
  11. Thermometer,
  12. Target,
  13. Repeat,
  14. Ban,
  15. Shuffle,
  16. Check,
  17. X,
  18. } from 'lucide-react';
  19. const ParameterControl = ({
  20. inputs,
  21. parameterEnabled,
  22. onInputChange,
  23. onParameterToggle,
  24. }) => {
  25. return (
  26. <>
  27. {/* Temperature */}
  28. <div className={`transition-opacity duration-200 ${!parameterEnabled.temperature ? 'opacity-50' : ''}`}>
  29. <div className="flex items-center justify-between mb-2">
  30. <div className="flex items-center gap-2">
  31. <Thermometer size={16} className="text-gray-500" />
  32. <Typography.Text strong className="text-sm">
  33. Temperature
  34. </Typography.Text>
  35. <Tag size="small" className="!rounded-full">
  36. {inputs.temperature}
  37. </Tag>
  38. </div>
  39. <Button
  40. theme={parameterEnabled.temperature ? 'solid' : 'borderless'}
  41. type={parameterEnabled.temperature ? 'primary' : 'tertiary'}
  42. size="small"
  43. icon={parameterEnabled.temperature ? <Check size={10} /> : <X size={10} />}
  44. onClick={() => onParameterToggle('temperature')}
  45. className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
  46. />
  47. </div>
  48. <Typography.Text className="text-xs text-gray-500 mb-2">
  49. 控制输出的随机性和创造性
  50. </Typography.Text>
  51. <Slider
  52. step={0.1}
  53. min={0.1}
  54. max={1}
  55. value={inputs.temperature}
  56. onChange={(value) => onInputChange('temperature', value)}
  57. className="mt-2"
  58. disabled={!parameterEnabled.temperature}
  59. />
  60. </div>
  61. {/* Top P */}
  62. <div className={`transition-opacity duration-200 ${!parameterEnabled.top_p ? 'opacity-50' : ''}`}>
  63. <div className="flex items-center justify-between mb-2">
  64. <div className="flex items-center gap-2">
  65. <Target size={16} className="text-gray-500" />
  66. <Typography.Text strong className="text-sm">
  67. Top P
  68. </Typography.Text>
  69. <Tag size="small" className="!rounded-full">
  70. {inputs.top_p}
  71. </Tag>
  72. </div>
  73. <Button
  74. theme={parameterEnabled.top_p ? 'solid' : 'borderless'}
  75. type={parameterEnabled.top_p ? 'primary' : 'tertiary'}
  76. size="small"
  77. icon={parameterEnabled.top_p ? <Check size={10} /> : <X size={10} />}
  78. onClick={() => onParameterToggle('top_p')}
  79. className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
  80. />
  81. </div>
  82. <Typography.Text className="text-xs text-gray-500 mb-2">
  83. 核采样,控制词汇选择的多样性
  84. </Typography.Text>
  85. <Slider
  86. step={0.1}
  87. min={0.1}
  88. max={1}
  89. value={inputs.top_p}
  90. onChange={(value) => onInputChange('top_p', value)}
  91. className="mt-2"
  92. disabled={!parameterEnabled.top_p}
  93. />
  94. </div>
  95. {/* Frequency Penalty */}
  96. <div className={`transition-opacity duration-200 ${!parameterEnabled.frequency_penalty ? 'opacity-50' : ''}`}>
  97. <div className="flex items-center justify-between mb-2">
  98. <div className="flex items-center gap-2">
  99. <Repeat size={16} className="text-gray-500" />
  100. <Typography.Text strong className="text-sm">
  101. Frequency Penalty
  102. </Typography.Text>
  103. <Tag size="small" className="!rounded-full">
  104. {inputs.frequency_penalty}
  105. </Tag>
  106. </div>
  107. <Button
  108. theme={parameterEnabled.frequency_penalty ? 'solid' : 'borderless'}
  109. type={parameterEnabled.frequency_penalty ? 'primary' : 'tertiary'}
  110. size="small"
  111. icon={parameterEnabled.frequency_penalty ? <Check size={10} /> : <X size={10} />}
  112. onClick={() => onParameterToggle('frequency_penalty')}
  113. className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
  114. />
  115. </div>
  116. <Typography.Text className="text-xs text-gray-500 mb-2">
  117. 频率惩罚,减少重复词汇的出现
  118. </Typography.Text>
  119. <Slider
  120. step={0.1}
  121. min={-2}
  122. max={2}
  123. value={inputs.frequency_penalty}
  124. onChange={(value) => onInputChange('frequency_penalty', value)}
  125. className="mt-2"
  126. disabled={!parameterEnabled.frequency_penalty}
  127. />
  128. </div>
  129. {/* Presence Penalty */}
  130. <div className={`transition-opacity duration-200 ${!parameterEnabled.presence_penalty ? 'opacity-50' : ''}`}>
  131. <div className="flex items-center justify-between mb-2">
  132. <div className="flex items-center gap-2">
  133. <Ban size={16} className="text-gray-500" />
  134. <Typography.Text strong className="text-sm">
  135. Presence Penalty
  136. </Typography.Text>
  137. <Tag size="small" className="!rounded-full">
  138. {inputs.presence_penalty}
  139. </Tag>
  140. </div>
  141. <Button
  142. theme={parameterEnabled.presence_penalty ? 'solid' : 'borderless'}
  143. type={parameterEnabled.presence_penalty ? 'primary' : 'tertiary'}
  144. size="small"
  145. icon={parameterEnabled.presence_penalty ? <Check size={10} /> : <X size={10} />}
  146. onClick={() => onParameterToggle('presence_penalty')}
  147. className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
  148. />
  149. </div>
  150. <Typography.Text className="text-xs text-gray-500 mb-2">
  151. 存在惩罚,鼓励讨论新话题
  152. </Typography.Text>
  153. <Slider
  154. step={0.1}
  155. min={-2}
  156. max={2}
  157. value={inputs.presence_penalty}
  158. onChange={(value) => onInputChange('presence_penalty', value)}
  159. className="mt-2"
  160. disabled={!parameterEnabled.presence_penalty}
  161. />
  162. </div>
  163. {/* MaxTokens */}
  164. <div className={`transition-opacity duration-200 ${!parameterEnabled.max_tokens ? 'opacity-50' : ''}`}>
  165. <div className="flex items-center justify-between mb-2">
  166. <div className="flex items-center gap-2">
  167. <Hash size={16} className="text-gray-500" />
  168. <Typography.Text strong className="text-sm">
  169. Max Tokens
  170. </Typography.Text>
  171. </div>
  172. <Button
  173. theme={parameterEnabled.max_tokens ? 'solid' : 'borderless'}
  174. type={parameterEnabled.max_tokens ? 'primary' : 'tertiary'}
  175. size="small"
  176. icon={parameterEnabled.max_tokens ? <Check size={10} /> : <X size={10} />}
  177. onClick={() => onParameterToggle('max_tokens')}
  178. className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
  179. />
  180. </div>
  181. <Input
  182. placeholder='MaxTokens'
  183. name='max_tokens'
  184. required
  185. autoComplete='new-password'
  186. defaultValue={0}
  187. value={inputs.max_tokens}
  188. onChange={(value) => onInputChange('max_tokens', value)}
  189. className="!rounded-lg"
  190. disabled={!parameterEnabled.max_tokens}
  191. />
  192. </div>
  193. {/* Seed */}
  194. <div className={`transition-opacity duration-200 ${!parameterEnabled.seed ? 'opacity-50' : ''}`}>
  195. <div className="flex items-center justify-between mb-2">
  196. <div className="flex items-center gap-2">
  197. <Shuffle size={16} className="text-gray-500" />
  198. <Typography.Text strong className="text-sm">
  199. Seed
  200. </Typography.Text>
  201. <Typography.Text className="text-xs text-gray-400">
  202. (可选,用于复现结果)
  203. </Typography.Text>
  204. </div>
  205. <Button
  206. theme={parameterEnabled.seed ? 'solid' : 'borderless'}
  207. type={parameterEnabled.seed ? 'primary' : 'tertiary'}
  208. size="small"
  209. icon={parameterEnabled.seed ? <Check size={10} /> : <X size={10} />}
  210. onClick={() => onParameterToggle('seed')}
  211. className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
  212. />
  213. </div>
  214. <Input
  215. placeholder='随机种子 (留空为随机)'
  216. name='seed'
  217. autoComplete='new-password'
  218. value={inputs.seed || ''}
  219. onChange={(value) => onInputChange('seed', value === '' ? null : value)}
  220. className="!rounded-lg"
  221. disabled={!parameterEnabled.seed}
  222. />
  223. </div>
  224. </>
  225. );
  226. };
  227. export default ParameterControl;