feat: ai proxy v1 (#3898)
* feat: ai proxy v1 * perf: ai proxy channel crud * feat: ai proxy logs * feat: channel test * doc * update lock
This commit is contained in:
@@ -33,7 +33,6 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import {
|
||||
deleteSystemModel,
|
||||
getModelConfigJson,
|
||||
getSystemModelDefaultConfig,
|
||||
getSystemModelDetail,
|
||||
getSystemModelList,
|
||||
getTestModel,
|
||||
@@ -44,24 +43,20 @@ import MyBox from '@fastgpt/web/components/common/MyBox';
|
||||
import { SystemModelItemType } from '@fastgpt/service/core/ai/type';
|
||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||
import MyIconButton from '@fastgpt/web/components/common/Icon/button';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
|
||||
import MyTextarea from '@/components/common/Textarea/MyTextarea';
|
||||
import JsonEditor from '@fastgpt/web/components/common/Textarea/JsonEditor';
|
||||
import { clientInitData } from '@/web/common/system/staticData';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
||||
import { putUpdateWithJson } from '@/web/core/ai/config';
|
||||
import CopyBox from '@fastgpt/web/components/common/String/CopyBox';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import AIModelSelector from '@/components/Select/AIModelSelector';
|
||||
import { useRefresh } from '../../../../../../packages/web/hooks/useRefresh';
|
||||
import { Prompt_CQJson, Prompt_ExtractJson } from '@fastgpt/global/core/ai/prompt/agent';
|
||||
import MyDivider from '@fastgpt/web/components/common/MyDivider';
|
||||
import { AddModelButton } from './AddModelBox';
|
||||
|
||||
const MyModal = dynamic(() => import('@fastgpt/web/components/common/MyModal'));
|
||||
const ModelEditModal = dynamic(() => import('./AddModelBox').then((mod) => mod.ModelEditModal));
|
||||
|
||||
const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -271,6 +266,7 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const onCreateModel = (type: ModelTypeEnum) => {
|
||||
const defaultModel = defaultModels[type];
|
||||
|
||||
@@ -316,37 +312,7 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
|
||||
<Button variant={'whiteBase'} mr={2} onClick={onOpenJsonConfig}>
|
||||
{t('account:model.json_config')}
|
||||
</Button>
|
||||
<MyMenu
|
||||
trigger="hover"
|
||||
size="sm"
|
||||
Button={<Button>{t('account:create_model')}</Button>}
|
||||
menuList={[
|
||||
{
|
||||
children: [
|
||||
{
|
||||
label: t('common:model.type.chat'),
|
||||
onClick: () => onCreateModel(ModelTypeEnum.llm)
|
||||
},
|
||||
{
|
||||
label: t('common:model.type.embedding'),
|
||||
onClick: () => onCreateModel(ModelTypeEnum.embedding)
|
||||
},
|
||||
{
|
||||
label: t('common:model.type.tts'),
|
||||
onClick: () => onCreateModel(ModelTypeEnum.tts)
|
||||
},
|
||||
{
|
||||
label: t('common:model.type.stt'),
|
||||
onClick: () => onCreateModel(ModelTypeEnum.stt)
|
||||
},
|
||||
{
|
||||
label: t('common:model.type.reRank'),
|
||||
onClick: () => onCreateModel(ModelTypeEnum.rerank)
|
||||
}
|
||||
]
|
||||
}
|
||||
]}
|
||||
/>
|
||||
<AddModelButton onCreate={onCreateModel} />
|
||||
</Flex>
|
||||
)}
|
||||
<MyBox flex={'1 0 0'} isLoading={isLoading}>
|
||||
@@ -512,650 +478,6 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const InputStyles = {
|
||||
maxW: '300px',
|
||||
bg: 'myGray.50',
|
||||
w: '100%',
|
||||
rows: 3
|
||||
};
|
||||
const ModelEditModal = ({
|
||||
modelData,
|
||||
onSuccess,
|
||||
onClose
|
||||
}: {
|
||||
modelData: SystemModelItemType;
|
||||
onSuccess: () => void;
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
|
||||
const { register, getValues, setValue, handleSubmit, watch, reset } =
|
||||
useForm<SystemModelItemType>({
|
||||
defaultValues: modelData
|
||||
});
|
||||
|
||||
const isCustom = !!modelData.isCustom;
|
||||
const isLLMModel = modelData?.type === ModelTypeEnum.llm;
|
||||
const isEmbeddingModel = modelData?.type === ModelTypeEnum.embedding;
|
||||
const isTTSModel = modelData?.type === ModelTypeEnum.tts;
|
||||
const isSTTModel = modelData?.type === ModelTypeEnum.stt;
|
||||
const isRerankModel = modelData?.type === ModelTypeEnum.rerank;
|
||||
|
||||
const provider = watch('provider');
|
||||
const providerData = useMemo(() => getModelProvider(provider), [provider]);
|
||||
|
||||
const providerList = useRef<{ label: any; value: ModelProviderIdType }[]>(
|
||||
ModelProviderList.map((item) => ({
|
||||
label: (
|
||||
<HStack>
|
||||
<Avatar src={item.avatar} w={'1rem'} />
|
||||
<Box>{t(item.name as any)}</Box>
|
||||
</HStack>
|
||||
),
|
||||
value: item.id
|
||||
}))
|
||||
);
|
||||
|
||||
const priceUnit = useMemo(() => {
|
||||
if (isLLMModel || isEmbeddingModel) return '/ 1k Tokens';
|
||||
if (isTTSModel) return `/ 1k ${t('common:unit.character')}`;
|
||||
if (isSTTModel) return `/ 60 ${t('common:unit.seconds')}`;
|
||||
return '';
|
||||
return '';
|
||||
}, [isLLMModel, isEmbeddingModel, isTTSModel, t, isSTTModel]);
|
||||
|
||||
const { runAsync: updateModel, loading: updatingModel } = useRequest2(
|
||||
async (data: SystemModelItemType) => {
|
||||
return putSystemModel({
|
||||
model: data.model,
|
||||
metadata: data
|
||||
}).then(onSuccess);
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
onClose();
|
||||
},
|
||||
successToast: t('common:common.Success')
|
||||
}
|
||||
);
|
||||
|
||||
const [key, setKey] = useState(0);
|
||||
const { runAsync: loadDefaultConfig, loading: loadingDefaultConfig } = useRequest2(
|
||||
getSystemModelDefaultConfig,
|
||||
{
|
||||
onSuccess(res) {
|
||||
reset({
|
||||
...getValues(),
|
||||
...res
|
||||
});
|
||||
setTimeout(() => {
|
||||
setKey((prev) => prev + 1);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
iconSrc={'modal/edit'}
|
||||
title={t('account:model.edit_model')}
|
||||
isOpen
|
||||
onClose={onClose}
|
||||
maxW={['90vw', '80vw']}
|
||||
w={'100%'}
|
||||
h={'100%'}
|
||||
>
|
||||
<ModalBody>
|
||||
<Flex gap={4} key={key}>
|
||||
<TableContainer flex={'1'}>
|
||||
<Table>
|
||||
<Thead>
|
||||
<Tr color={'myGray.600'}>
|
||||
<Th fontSize={'xs'}>{t('account:model.param_name')}</Th>
|
||||
<Th fontSize={'xs'}></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.model_id')}</Box>
|
||||
<QuestionTip label={t('account:model.model_id_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
{isCustom ? (
|
||||
<Input {...register('model', { required: true })} {...InputStyles} />
|
||||
) : (
|
||||
modelData?.model
|
||||
)}
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>{t('common:model.provider')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<MySelect
|
||||
value={provider}
|
||||
onchange={(value) => setValue('provider', value)}
|
||||
list={providerList.current}
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.alias')}</Box>
|
||||
<QuestionTip label={t('account:model.alias_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Input {...register('name', { required: true })} {...InputStyles} />
|
||||
</Td>
|
||||
</Tr>
|
||||
{priceUnit && feConfigs?.isPlus && (
|
||||
<>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.charsPointsPrice')}</Box>
|
||||
<QuestionTip label={t('account:model.charsPointsPrice_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td>
|
||||
<Flex justify="flex-end">
|
||||
<HStack w={'100%'} maxW={'300px'}>
|
||||
<MyNumberInput
|
||||
flex={'1 0 0'}
|
||||
register={register}
|
||||
name={'charsPointsPrice'}
|
||||
step={0.01}
|
||||
/>
|
||||
<Box fontSize={'sm'}>{priceUnit}</Box>
|
||||
</HStack>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
{isLLMModel && (
|
||||
<>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.input_price')}</Box>
|
||||
<QuestionTip label={t('account:model.input_price_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td>
|
||||
<Flex justify="flex-end">
|
||||
<HStack w={'100%'} maxW={'300px'}>
|
||||
<MyNumberInput
|
||||
flex={'1 0 0'}
|
||||
register={register}
|
||||
name={'inputPrice'}
|
||||
step={0.01}
|
||||
/>
|
||||
<Box fontSize={'sm'}>{priceUnit}</Box>
|
||||
</HStack>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.output_price')}</Box>
|
||||
<QuestionTip label={t('account:model.output_price_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td>
|
||||
<Flex justify="flex-end">
|
||||
<HStack w={'100%'} maxW={'300px'}>
|
||||
<MyNumberInput
|
||||
flex={'1 0 0'}
|
||||
register={register}
|
||||
name={'outputPrice'}
|
||||
step={0.01}
|
||||
/>
|
||||
<Box fontSize={'sm'}>{priceUnit}</Box>
|
||||
</HStack>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{isLLMModel && (
|
||||
<>
|
||||
<Tr>
|
||||
<Td>{t('common:core.ai.Max context')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<MyNumberInput
|
||||
register={register}
|
||||
isRequired
|
||||
name="maxContext"
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>{t('account:model.max_quote')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<MyNumberInput
|
||||
register={register}
|
||||
isRequired
|
||||
name="quoteMaxToken"
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>{t('common:core.chat.response.module maxToken')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<MyNumberInput
|
||||
register={register}
|
||||
isRequired
|
||||
name="maxResponse"
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>{t('account:model.max_temperature')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<MyNumberInput
|
||||
register={register}
|
||||
isRequired
|
||||
name="maxTemperature"
|
||||
step={0.1}
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.show_top_p')}</Box>
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('showTopP')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.show_stop_sign')}</Box>
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('showStopSign')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>{t('account:model.response_format')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<JsonEditor
|
||||
value={JSON.stringify(getValues('responseFormatList'), null, 2)}
|
||||
resize
|
||||
onChange={(e) => {
|
||||
if (!e) {
|
||||
setValue('responseFormatList', []);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setValue('responseFormatList', JSON.parse(e));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}}
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
</>
|
||||
)}
|
||||
{isEmbeddingModel && (
|
||||
<>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.normalization')}</Box>
|
||||
<QuestionTip label={t('account:model.normalization_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('normalization')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.default_token')}</Box>
|
||||
<QuestionTip label={t('account:model.default_token_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<MyNumberInput
|
||||
register={register}
|
||||
isRequired
|
||||
name="defaultToken"
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>{t('common:core.ai.Max context')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<MyNumberInput
|
||||
register={register}
|
||||
isRequired
|
||||
name="maxToken"
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.defaultConfig')}</Box>
|
||||
<QuestionTip label={t('account:model.defaultConfig_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<JsonEditor
|
||||
value={JSON.stringify(getValues('defaultConfig'), null, 2)}
|
||||
onChange={(e) => {
|
||||
if (!e) {
|
||||
setValue('defaultConfig', {});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setValue('defaultConfig', JSON.parse(e));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}}
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
</>
|
||||
)}
|
||||
{isTTSModel && (
|
||||
<>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.voices')}</Box>
|
||||
<QuestionTip label={t('account:model.voices_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<JsonEditor
|
||||
value={JSON.stringify(getValues('voices'), null, 2)}
|
||||
onChange={(e) => {
|
||||
try {
|
||||
setValue('voices', JSON.parse(e));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}}
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
</>
|
||||
)}
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.request_url')}</Box>
|
||||
<QuestionTip label={t('account:model.request_url_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Input {...register('requestUrl')} {...InputStyles} />
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.request_auth')}</Box>
|
||||
<QuestionTip label={t('account:model.request_auth_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Input {...register('requestAuth')} {...InputStyles} />
|
||||
</Td>
|
||||
</Tr>
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
{isLLMModel && (
|
||||
<TableContainer flex={'1'}>
|
||||
<Table>
|
||||
<Thead>
|
||||
<Tr color={'myGray.600'}>
|
||||
<Th fontSize={'xs'}>{t('account:model.param_name')}</Th>
|
||||
<Th fontSize={'xs'}></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.tool_choice')}</Box>
|
||||
<QuestionTip label={t('account:model.tool_choice_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('toolChoice')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.function_call')}</Box>
|
||||
<QuestionTip label={t('account:model.function_call_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('functionCall')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.vision')}</Box>
|
||||
<QuestionTip label={t('account:model.vision_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('vision')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.reasoning')}</Box>
|
||||
<QuestionTip label={t('account:model.reasoning_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('reasoning')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
{feConfigs?.isPlus && (
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.censor')}</Box>
|
||||
<QuestionTip label={t('account:model.censor_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('censor')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
<Tr>
|
||||
<Td>{t('account:model.dataset_process')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('datasetProcess')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>{t('account:model.used_in_classify')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('usedInClassify')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>{t('account:model.used_in_extract_fields')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('usedInExtractFields')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>{t('account:model.used_in_tool_call')}</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<Flex justifyContent={'flex-end'}>
|
||||
<Switch {...register('usedInToolCall')} />
|
||||
</Flex>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.default_system_chat_prompt')}</Box>
|
||||
<QuestionTip label={t('account:model.default_system_chat_prompt_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<MyTextarea {...register('defaultSystemChatPrompt')} {...InputStyles} />
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.custom_cq_prompt')}</Box>
|
||||
<QuestionTip
|
||||
label={t('account:model.custom_cq_prompt_tip', { prompt: Prompt_CQJson })}
|
||||
/>
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<MyTextarea {...register('customCQPrompt')} {...InputStyles} />
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.custom_extract_prompt')}</Box>
|
||||
<QuestionTip
|
||||
label={t('account:model.custom_extract_prompt_tip', {
|
||||
prompt: Prompt_ExtractJson
|
||||
})}
|
||||
/>
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<MyTextarea {...register('customExtractPrompt')} {...InputStyles} />
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td>
|
||||
<HStack spacing={1}>
|
||||
<Box>{t('account:model.default_config')}</Box>
|
||||
<QuestionTip label={t('account:model.default_config_tip')} />
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign={'right'}>
|
||||
<JsonEditor
|
||||
value={JSON.stringify(getValues('defaultConfig'), null, 2)}
|
||||
resize
|
||||
onChange={(e) => {
|
||||
if (!e) {
|
||||
setValue('defaultConfig', {});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setValue('defaultConfig', JSON.parse(e));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}}
|
||||
{...InputStyles}
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)}
|
||||
</Flex>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
{!modelData.isCustom && (
|
||||
<Button
|
||||
isLoading={loadingDefaultConfig}
|
||||
variant={'whiteBase'}
|
||||
mr={4}
|
||||
onClick={() => loadDefaultConfig(modelData.model)}
|
||||
>
|
||||
{t('account:reset_default')}
|
||||
</Button>
|
||||
)}
|
||||
<Button variant={'whiteBase'} mr={4} onClick={onClose}>
|
||||
{t('common:common.Cancel')}
|
||||
</Button>
|
||||
<Button isLoading={updatingModel} onClick={handleSubmit(updateModel)}>
|
||||
{t('common:common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
);
|
||||
};
|
||||
|
||||
const JsonConfigModal = ({
|
||||
onClose,
|
||||
onSuccess
|
||||
|
||||
Reference in New Issue
Block a user