feat: 模型介绍和温度调整。完善聊天页提示
This commit is contained in:
@@ -1,21 +1,29 @@
|
||||
import React, { useCallback, useState, useEffect, useRef, useMemo } from 'react';
|
||||
import React, { useCallback, useState, useRef, useMemo, useEffect } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { getModelById, delModelById, postTrainModel, putModelTrainingStatus } from '@/api/model';
|
||||
import {
|
||||
getModelById,
|
||||
delModelById,
|
||||
postTrainModel,
|
||||
putModelTrainingStatus,
|
||||
putModelById
|
||||
} from '@/api/model';
|
||||
import { getChatSiteId } from '@/api/chat';
|
||||
import type { ModelType } from '@/types/model';
|
||||
import type { ModelSchema } from '@/types/mongoSchema';
|
||||
import { Card, Box, Flex, Button, Tag, Grid } from '@chakra-ui/react';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { useConfirm } from '@/hooks/useConfirm';
|
||||
import { formatModelStatus, ModelStatusEnum, OpenAiList } from '@/constants/model';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { formatModelStatus, ModelStatusEnum, ModelList, defaultModel } from '@/constants/model';
|
||||
import { useGlobalStore } from '@/store/global';
|
||||
import { useScreen } from '@/hooks/useScreen';
|
||||
import ModelEditForm from './components/ModelEditForm';
|
||||
import Icon from '@/components/Iconfont';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
const Training = dynamic(() => import('./components/Training'));
|
||||
|
||||
const ModelDetail = () => {
|
||||
const ModelDetail = ({ modelId }: { modelId: string }) => {
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const { isPc, media } = useScreen();
|
||||
@@ -24,33 +32,35 @@ const ModelDetail = () => {
|
||||
content: '确认删除该模型?'
|
||||
});
|
||||
const SelectFileDom = useRef<HTMLInputElement>(null);
|
||||
|
||||
const { modelId } = router.query as { modelId: string };
|
||||
const [model, setModel] = useState<ModelType>();
|
||||
const [model, setModel] = useState<ModelSchema>(defaultModel);
|
||||
const formHooks = useForm<ModelSchema>({
|
||||
defaultValues: model
|
||||
});
|
||||
|
||||
const canTrain = useMemo(() => {
|
||||
const openai = OpenAiList.find((item) => item.model === model?.service.modelName);
|
||||
return openai && openai.canTraining === true;
|
||||
const openai = ModelList[model.service.company].find(
|
||||
(item) => item.model === model?.service.modelName
|
||||
);
|
||||
return openai && openai.trainName;
|
||||
}, [model]);
|
||||
|
||||
/* 加载模型数据 */
|
||||
const loadModel = useCallback(async () => {
|
||||
if (!modelId) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await getModelById(modelId as string);
|
||||
const res = await getModelById(modelId);
|
||||
console.log(res);
|
||||
res.security.expiredTime /= 60 * 60 * 1000;
|
||||
setModel(res);
|
||||
formHooks.reset(res);
|
||||
} catch (err) {
|
||||
console.log('error->', err);
|
||||
}
|
||||
setLoading(false);
|
||||
}, [modelId, setLoading]);
|
||||
return null;
|
||||
}, [formHooks, modelId, setLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
loadModel();
|
||||
router.prefetch('/chat');
|
||||
}, [loadModel, modelId, router]);
|
||||
useQuery([modelId], loadModel);
|
||||
|
||||
/* 点击删除 */
|
||||
const handleDelModel = useCallback(async () => {
|
||||
@@ -71,7 +81,6 @@ const ModelDetail = () => {
|
||||
|
||||
/* 点前往聊天预览页 */
|
||||
const handlePreviewChat = useCallback(async () => {
|
||||
if (!model) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
const chatId = await getChatSiteId(model._id);
|
||||
@@ -131,6 +140,65 @@ const ModelDetail = () => {
|
||||
setLoading(false);
|
||||
}, [model, setLoading, loadModel, toast]);
|
||||
|
||||
// 提交保存模型修改
|
||||
const saveSubmitSuccess = useCallback(
|
||||
async (data: ModelSchema) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await putModelById(data._id, {
|
||||
name: data.name,
|
||||
systemPrompt: data.systemPrompt,
|
||||
intro: data.intro,
|
||||
temperature: data.temperature,
|
||||
service: data.service,
|
||||
security: data.security
|
||||
});
|
||||
toast({
|
||||
title: '更新成功',
|
||||
status: 'success'
|
||||
});
|
||||
} catch (err) {
|
||||
console.log('error->', err);
|
||||
toast({
|
||||
title: err as string,
|
||||
status: 'success'
|
||||
});
|
||||
}
|
||||
setLoading(false);
|
||||
},
|
||||
[setLoading, toast]
|
||||
);
|
||||
// 提交保存表单失败
|
||||
const saveSubmitError = useCallback(() => {
|
||||
// deep search message
|
||||
const deepSearch = (obj: any): string => {
|
||||
if (!obj) return '提交表单错误';
|
||||
if (!!obj.message) {
|
||||
return obj.message;
|
||||
}
|
||||
return deepSearch(Object.values(obj)[0]);
|
||||
};
|
||||
toast({
|
||||
title: deepSearch(formHooks.formState.errors),
|
||||
status: 'error',
|
||||
duration: 4000,
|
||||
isClosable: true
|
||||
});
|
||||
}, [formHooks.formState.errors, toast]);
|
||||
|
||||
useEffect(() => {
|
||||
router.prefetch('/chat');
|
||||
|
||||
window.onbeforeunload = (e) => {
|
||||
e.preventDefault();
|
||||
e.returnValue = '内容已修改,确认离开页面吗?';
|
||||
};
|
||||
|
||||
return () => {
|
||||
window.onbeforeunload = null;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 头部 */}
|
||||
@@ -138,50 +206,48 @@ const ModelDetail = () => {
|
||||
{isPc ? (
|
||||
<Flex alignItems={'center'}>
|
||||
<Box fontSize={'xl'} fontWeight={'bold'}>
|
||||
{model?.name || '模型'} 配置
|
||||
{model.name}
|
||||
</Box>
|
||||
{!!model && (
|
||||
<Tag
|
||||
ml={2}
|
||||
variant="solid"
|
||||
colorScheme={formatModelStatus[model.status].colorTheme}
|
||||
cursor={model.status === ModelStatusEnum.training ? 'pointer' : 'default'}
|
||||
onClick={handleClickUpdateStatus}
|
||||
>
|
||||
{formatModelStatus[model.status].text}
|
||||
</Tag>
|
||||
)}
|
||||
<Tag
|
||||
ml={2}
|
||||
variant="solid"
|
||||
colorScheme={formatModelStatus[model.status].colorTheme}
|
||||
cursor={model.status === ModelStatusEnum.training ? 'pointer' : 'default'}
|
||||
onClick={handleClickUpdateStatus}
|
||||
>
|
||||
{formatModelStatus[model.status].text}
|
||||
</Tag>
|
||||
<Box flex={1} />
|
||||
<Button variant={'outline'} onClick={handlePreviewChat}>
|
||||
对话体验
|
||||
</Button>
|
||||
<Button ml={4} onClick={formHooks.handleSubmit(saveSubmitSuccess, saveSubmitError)}>
|
||||
保存修改
|
||||
</Button>
|
||||
</Flex>
|
||||
) : (
|
||||
<>
|
||||
<Flex alignItems={'center'}>
|
||||
<Box as={'h3'} fontSize={'xl'} fontWeight={'bold'} flex={1}>
|
||||
{model?.name || '模型'} 配置
|
||||
{model?.name}
|
||||
</Box>
|
||||
{!!model && (
|
||||
<Tag ml={2} colorScheme={formatModelStatus[model.status].colorTheme}>
|
||||
{formatModelStatus[model.status].text}
|
||||
</Tag>
|
||||
)}
|
||||
<Tag ml={2} colorScheme={formatModelStatus[model.status].colorTheme}>
|
||||
{formatModelStatus[model.status].text}
|
||||
</Tag>
|
||||
</Flex>
|
||||
<Box mt={4} textAlign={'right'}>
|
||||
<Button variant={'outline'} onClick={handlePreviewChat}>
|
||||
对话体验
|
||||
</Button>
|
||||
<Button ml={4} onClick={formHooks.handleSubmit(saveSubmitSuccess, saveSubmitError)}>
|
||||
保存修改
|
||||
</Button>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
{/* 基本信息编辑 */}
|
||||
<Box mt={5}>
|
||||
<ModelEditForm model={model} />
|
||||
</Box>
|
||||
{/* 其他配置 */}
|
||||
<Grid mt={5} gridTemplateColumns={media('1fr 1fr', '1fr')} gridGap={5}>
|
||||
<ModelEditForm formHooks={formHooks} />
|
||||
<Card p={4}>{!!model && <Training model={model} />}</Card>
|
||||
<Card p={4}>
|
||||
<Box fontWeight={'bold'} fontSize={'lg'}>
|
||||
@@ -241,6 +307,8 @@ const ModelDetail = () => {
|
||||
</Flex>
|
||||
</Card>
|
||||
</Grid>
|
||||
|
||||
{/* 文件选择 */}
|
||||
<Box position={'absolute'} w={0} h={0} overflow={'hidden'}>
|
||||
<input ref={SelectFileDom} type="file" accept=".jsonl" onChange={startTraining} />
|
||||
</Box>
|
||||
@@ -250,3 +318,11 @@ const ModelDetail = () => {
|
||||
};
|
||||
|
||||
export default ModelDetail;
|
||||
|
||||
export async function getServerSideProps(context: any) {
|
||||
const modelId = context.query?.modelId || '';
|
||||
|
||||
return {
|
||||
props: { modelId }
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user