import { Accordion, AccordionHeader, AccordionItem, AccordionPanel, Checkbox, Dropdown, Input, Label, Option, PresenceBadge, Select, Switch, Text } from '@fluentui/react-components'; import { AddCircle20Regular, DataUsageSettings20Regular, Delete20Regular, Save20Regular } from '@fluentui/react-icons'; import React, { FC, useCallback, useEffect, useRef } from 'react'; import { Section } from '../components/Section'; import { Labeled } from '../components/Labeled'; import { ToolTipButton } from '../components/ToolTipButton'; import commonStore from '../stores/commonStore'; import { observer } from 'mobx-react-lite'; import { toast } from 'react-toastify'; import { ValuedSlider } from '../components/ValuedSlider'; import { NumberInput } from '../components/NumberInput'; import { Page } from '../components/Page'; import { useNavigate } from 'react-router'; import { RunButton } from '../components/RunButton'; import { updateConfig } from '../apis'; import { getStrategy } from '../utils'; import { useTranslation } from 'react-i18next'; import strategyImg from '../assets/images/strategy.jpg'; import strategyZhImg from '../assets/images/strategy_zh.jpg'; import { ResetConfigsButton } from '../components/ResetConfigsButton'; import { useMediaQuery } from 'usehooks-ts'; import { ApiParameters, Device, ModelParameters, Precision } from '../types/configs'; import { convertModel, convertToGGML, convertToSt } from '../utils/convert-model'; import { defaultPenaltyDecay } from './defaultConfigs'; const ConfigSelector: FC<{ selectedIndex: number, updateSelectedIndex: (i: number) => void }> = observer(({ selectedIndex, updateSelectedIndex }) => { return ( { if (data.optionValue) { updateSelectedIndex(Number(data.optionValue)); } }}> {commonStore.modelConfigs.map((config, index) => {config.name} {commonStore.modelSourceList.find(item => item.name === config.modelParameters.modelName)?.isComplete && } )} ); }); const Configs: FC = observer(() => { const { t } = useTranslation(); const [selectedIndex, setSelectedIndex] = React.useState(commonStore.currentModelConfigIndex); const [selectedConfig, setSelectedConfig] = React.useState(commonStore.modelConfigs[selectedIndex]); const [displayStrategyImg, setDisplayStrategyImg] = React.useState(false); const advancedHeaderRef1 = useRef(null); const advancedHeaderRef2 = useRef(null); const mq = useMediaQuery('(min-width: 640px)'); const navigate = useNavigate(); const port = selectedConfig.apiParameters.apiPort; useEffect(() => { if (advancedHeaderRef1.current) (advancedHeaderRef1.current.firstElementChild as HTMLElement).style.padding = '0'; if (advancedHeaderRef2.current) (advancedHeaderRef2.current.firstElementChild as HTMLElement).style.padding = '0'; }, []); const updateSelectedIndex = useCallback((newIndex: number) => { setSelectedIndex(newIndex); setSelectedConfig(commonStore.modelConfigs[newIndex]); // if you don't want to update the config used by the current startup in real time, comment out this line commonStore.setCurrentConfigIndex(newIndex); }, []); const setSelectedConfigName = (newName: string) => { setSelectedConfig({ ...selectedConfig, name: newName }); }; const setSelectedConfigApiParams = (newParams: Partial) => { setSelectedConfig({ ...selectedConfig, apiParameters: { ...selectedConfig.apiParameters, ...newParams } }); }; const setSelectedConfigModelParams = (newParams: Partial) => { setSelectedConfig({ ...selectedConfig, modelParameters: { ...selectedConfig.modelParameters, ...newParams } }); }; const onClickSave = () => { commonStore.setModelConfig(selectedIndex, selectedConfig); updateConfig({ max_tokens: selectedConfig.apiParameters.maxResponseToken, temperature: selectedConfig.apiParameters.temperature, top_p: selectedConfig.apiParameters.topP, presence_penalty: selectedConfig.apiParameters.presencePenalty, frequency_penalty: selectedConfig.apiParameters.frequencyPenalty, penalty_decay: selectedConfig.apiParameters.penaltyDecay, global_penalty: selectedConfig.apiParameters.globalPenalty }); toast(t('Config Saved'), { autoClose: 300, type: 'success' }); }; return ( } onClick={() => { commonStore.createModelConfig(); updateSelectedIndex(commonStore.modelConfigs.length - 1); }} /> } onClick={() => { commonStore.deleteModelConfig(selectedIndex); updateSelectedIndex(Math.min(selectedIndex, commonStore.modelConfigs.length - 1)); }} /> { setSelectedIndex(0); setSelectedConfig(commonStore.modelConfigs[0]); }} /> } text={mq ? t('Save Config') : null} onClick={onClickSave} /> {t('Config Name')} { setSelectedConfigName(data.value); }} /> { setSelectedConfigApiParams({ apiPort: data.value }); }} /> } /> { setSelectedConfigApiParams({ maxResponseToken: data.value }); }} /> } /> { setSelectedConfigApiParams({ temperature: data.value }); }} /> } /> { setSelectedConfigApiParams({ topP: data.value }); }} /> } /> { if (data.value === 'advanced') commonStore.setApiParamsCollapsed(!commonStore.apiParamsCollapsed); }}> {t('Advanced')} { setSelectedConfigApiParams({ presencePenalty: data.value }); }} /> } /> { setSelectedConfigApiParams({ frequencyPenalty: data.value }); }} /> } /> { setSelectedConfigApiParams({ penaltyDecay: data.value }); }} /> } /> { setSelectedConfigApiParams({ globalPenalty: data.checked }); }} /> } /> } /> { const modelSource = commonStore.modelSourceList.find(item => item.name === data.value); if (modelSource?.customTokenizer) setSelectedConfigModelParams({ modelName: data.value, useCustomTokenizer: true, customTokenizer: modelSource?.customTokenizer }); else // prevent customTokenizer from being overwritten setSelectedConfigModelParams({ modelName: data.value, useCustomTokenizer: false }); }}> {!commonStore.modelSourceList.find(item => item.name === selectedConfig.modelParameters.modelName)?.isComplete && {selectedConfig.modelParameters.modelName} } {commonStore.modelSourceList.map((modelItem, index) => modelItem.isComplete && {modelItem.name} )} } onClick={() => { navigate({ pathname: '/models' }); }} /> } /> { !selectedConfig.modelParameters.device.startsWith('WebGPU') ? (selectedConfig.modelParameters.device !== 'CPU (rwkv.cpp)' ? convertModel(selectedConfig, navigate)} /> : convertToGGML(selectedConfig, navigate)} />) : convertToSt(selectedConfig, navigate)} /> } { if (data.optionValue) { setSelectedConfigModelParams({ device: data.optionValue as Device }); } }}> CPU {t('CPU (rwkv.cpp, Faster)')!} {/*{commonStore.platform === 'darwin' && MPS}*/} CUDA {/*{t('CUDA (Beta, Faster)')!}*/} WebGPU WebGPU (Python) {t('Custom')!} } /> { selectedConfig.modelParameters.device !== 'Custom' && { if (data.optionText) { setSelectedConfigModelParams({ precision: data.optionText as Precision }); } }}> {selectedConfig.modelParameters.device !== 'CPU' && selectedConfig.modelParameters.device !== 'MPS' && fp16} {selectedConfig.modelParameters.device !== 'CPU (rwkv.cpp)' && int8} {selectedConfig.modelParameters.device.startsWith('WebGPU') && nf4} {selectedConfig.modelParameters.device !== 'CPU (rwkv.cpp)' && !selectedConfig.modelParameters.device.startsWith('WebGPU') && fp32} {selectedConfig.modelParameters.device === 'CPU (rwkv.cpp)' && Q5_1} } /> } { selectedConfig.modelParameters.device.startsWith('CUDA') && {getStrategy(selectedConfig)} } /> } { selectedConfig.modelParameters.device.startsWith('CUDA') && { setSelectedConfigModelParams({ storedLayers: data.value }); }} /> } /> } { selectedConfig.modelParameters.device.startsWith('WebGPU') && { setSelectedConfigModelParams({ tokenChunkSize: data.value }); }} /> } /> } { selectedConfig.modelParameters.device.startsWith('WebGPU') && { setSelectedConfigModelParams({ quantizedLayers: data.value }); }} /> } /> } {selectedConfig.modelParameters.device.startsWith('CUDA') && } { displayStrategyImg && } { selectedConfig.modelParameters.device === 'Custom' && setDisplayStrategyImg(true)} onMouseLeave={() => setDisplayStrategyImg(false)} content={ cuda:1 fp16' : 'mps fp32'} value={selectedConfig.modelParameters.customStrategy} onChange={(e, data) => { setSelectedConfigModelParams({ customStrategy: data.value }); }} /> } /> } {selectedConfig.modelParameters.device === 'Custom' && } { (selectedConfig.modelParameters.device.startsWith('CUDA') || selectedConfig.modelParameters.device === 'Custom') && { setSelectedConfigModelParams({ useCustomCuda: data.checked }); }} /> } /> } {selectedConfig.modelParameters.device !== 'WebGPU' && { if (data.value === 'advanced') commonStore.setModelParamsCollapsed(!commonStore.modelParamsCollapsed); }}> {t('Advanced')} { setSelectedConfigModelParams({ useCustomTokenizer: data.checked as boolean }); }} /> { setSelectedConfigModelParams({ customTokenizer: data.value }); }} /> } } /> {mq && } {selectedConfig.modelParameters.device !== 'WebGPU' && { setSelectedConfig({ ...selectedConfig, enableWebUI: data.checked as boolean }); }} />} } /> ); }); export default Configs;