From 29c95d24ae7951855aa5537b93cf33aad210b65f Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Mon, 24 Apr 2023 09:50:56 +0800 Subject: [PATCH] perf: model data code --- next.config.js | 5 +- src/api/model.ts | 2 +- src/constants/model.ts | 4 +- src/pages/_error.tsx | 15 +++ .../model/detail/components/ModelDataCard.tsx | 98 ++++++++----------- src/pages/model/detail/index.tsx | 53 ++-------- 6 files changed, 67 insertions(+), 110 deletions(-) create mode 100644 src/pages/_error.tsx diff --git a/next.config.js b/next.config.js index 3838fb5cf..8722ceb28 100644 --- a/next.config.js +++ b/next.config.js @@ -1,11 +1,8 @@ /** @type {import('next').NextConfig} */ -const path = require('path'); -const isDev = process.env.NODE_ENV === 'development'; - const nextConfig = { output: 'standalone', - reactStrictMode: false, + reactStrictMode: true, compress: true, webpack(config) { config.module.rules = config.module.rules.concat([ diff --git a/src/api/model.ts b/src/api/model.ts index a6ed10c57..d00a70a3d 100644 --- a/src/api/model.ts +++ b/src/api/model.ts @@ -1,5 +1,5 @@ import { GET, POST, DELETE, PUT } from './request'; -import type { ModelSchema, ModelDataSchema, ModelSplitDataSchema } from '@/types/mongoSchema'; +import type { ModelSchema, ModelDataSchema } from '@/types/mongoSchema'; import { ModelUpdateParams } from '@/types/model'; import { TrainingItemType } from '../types/training'; import { RequestPaging } from '../types/index'; diff --git a/src/constants/model.ts b/src/constants/model.ts index 6956bbbf5..1d6a67383 100644 --- a/src/constants/model.ts +++ b/src/constants/model.ts @@ -1,4 +1,4 @@ -import type { ModelDataType, ModelSchema } from '@/types/mongoSchema'; +import type { ModelSchema } from '@/types/mongoSchema'; export enum ModelDataStatusEnum { ready = 'ready', @@ -120,7 +120,7 @@ export const ModelVectorSearchModeMap: Record< export const defaultModel: ModelSchema = { _id: '', userId: '', - name: '', + name: 'modelName', avatar: '', status: ModelStatusEnum.pending, updateTime: Date.now(), diff --git a/src/pages/_error.tsx b/src/pages/_error.tsx new file mode 100644 index 000000000..ebf703d66 --- /dev/null +++ b/src/pages/_error.tsx @@ -0,0 +1,15 @@ +function Error({ statusCode }: { statusCode: number }) { + return ( +

+ {statusCode ? `An error ${statusCode} occurred on server` : 'An error occurred on client'} +

+ ); +} + +Error.getInitialProps = ({ res, err }: { res: any; err: any }) => { + const statusCode = res ? res.statusCode : err ? err.statusCode : 404; + console.log(err); + return { statusCode }; +}; + +export default Error; diff --git a/src/pages/model/detail/components/ModelDataCard.tsx b/src/pages/model/detail/components/ModelDataCard.tsx index f070ce2e6..4d30d176a 100644 --- a/src/pages/model/detail/components/ModelDataCard.tsx +++ b/src/pages/model/detail/components/ModelDataCard.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useState, useRef } from 'react'; import { Box, TableContainer, @@ -19,7 +19,6 @@ import { Input } from '@chakra-ui/react'; import type { BoxProps } from '@chakra-ui/react'; -import type { ModelSchema } from '@/types/mongoSchema'; import type { ModelDataItemType } from '@/types/model'; import { ModelDataStatusMap } from '@/constants/model'; import { usePagination } from '@/hooks/usePagination'; @@ -34,19 +33,23 @@ import { useLoading } from '@/hooks/useLoading'; import { fileDownload } from '@/utils/file'; import dynamic from 'next/dynamic'; import { useMutation, useQuery } from '@tanstack/react-query'; -import type { FormData as InputDataType } from './InputDataModal'; import Papa from 'papaparse'; +import InputModal, { FormData as InputDataType } from './InputDataModal'; -const InputModel = dynamic(() => import('./InputDataModal')); -const SelectFileModel = dynamic(() => import('./SelectFileModal')); -const SelectUrlModel = dynamic(() => import('./SelectUrlModal')); +const SelectFileModal = dynamic(() => import('./SelectFileModal')); const SelectCsvModal = dynamic(() => import('./SelectCsvModal')); -let lastSearch = ''; - -const ModelDataCard = ({ model }: { model: ModelSchema }) => { +const ModelDataCard = ({ modelId }: { modelId: string }) => { const { Loading, setIsLoading } = useLoading(); + const lastSearch = useRef(''); const [searchText, setSearchText] = useState(''); + const tdStyles = useRef({ + fontSize: 'xs', + maxW: '500px', + whiteSpace: 'pre-wrap', + maxH: '250px', + overflowY: 'auto' + }); const { data: modelDataList, isLoading, @@ -58,7 +61,7 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { api: getModelDataList, pageSize: 10, params: { - modelId: model._id, + modelId, searchText } }); @@ -70,19 +73,20 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { onOpen: onOpenSelectFileModal, onClose: onCloseSelectFileModal } = useDisclosure(); - const { - isOpen: isOpenSelectUrlModal, - onOpen: onOpenSelectUrlModal, - onClose: onCloseSelectUrlModal - } = useDisclosure(); const { isOpen: isOpenSelectCsvModal, onOpen: onOpenSelectCsvModal, onClose: onCloseSelectCsvModal } = useDisclosure(); - const { data: splitDataLen, refetch } = useQuery(['getModelSplitDataList'], () => - getModelSplitDataListLen(model._id) + const { data: splitDataLen = 0, refetch } = useQuery( + ['getModelSplitDataList'], + () => getModelSplitDataListLen(modelId), + { + onError(err) { + console.log(err); + } + } ); const refetchData = useCallback( @@ -94,8 +98,8 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { ); // 获取所有的数据,并导出 json - const { mutate: onclickExport, isLoading: isLoadingExport } = useMutation({ - mutationFn: () => getExportDataList(model._id), + const { mutate: onclickExport, isLoading: isLoadingExport = false } = useMutation({ + mutationFn: () => getExportDataList(modelId), onSuccess(res) { try { setIsLoading(true); @@ -112,17 +116,12 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { error; } setIsLoading(false); + }, + onError(err) { + console.log(err); } }); - const tdStyles: BoxProps = { - fontSize: 'xs', - maxW: '500px', - whiteSpace: 'pre-wrap', - maxH: '250px', - overflowY: 'auto' - }; - return ( <> @@ -150,7 +149,7 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { > 导出 - + 导入 @@ -166,17 +165,13 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { 手动输入 文本/文件拆分 - {/* 网站内容拆分 */} csv 问答对导入 - {/* 拆分数据提示 */} - {!!(splitDataLen && splitDataLen > 0) && ( - {splitDataLen}条数据正在拆分... - )} - + {splitDataLen > 0 && {splitDataLen}条数据正在拆分...} + { placeholder="搜索相关问题和答案,回车确认" onChange={(e) => setSearchText(e.target.value)} onBlur={() => { - if (searchText === lastSearch) return; + if (searchText === lastSearch.current) return; getData(1); - lastSearch = searchText; + lastSearch.current = searchText; }} onKeyDown={(e) => { - if (searchText === lastSearch) return; + if (searchText === lastSearch.current) return; if (e.key === 'Enter') { getData(1); - lastSearch = searchText; + lastSearch.current = searchText; } }} /> @@ -203,7 +198,7 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { - + @@ -213,10 +208,10 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { {modelDataList.map((item) => (
匹配内容(问题){'匹配内容(问题)'} 对应答案 状态 操作
- {item.q} + {item.q} - {item.a || '-'} + {item.a || '-'} {ModelDataStatusMap[item.status]} @@ -258,33 +253,22 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { {editInputData !== undefined && ( - setEditInputData(undefined)} onSuccess={refetchData} /> )} {isOpenSelectFileModal && ( - )} - {isOpenSelectUrlModal && ( - - )} {isOpenSelectCsvModal && ( - + )} ); diff --git a/src/pages/model/detail/index.tsx b/src/pages/model/detail/index.tsx index 2803c85e5..0e7a18586 100644 --- a/src/pages/model/detail/index.tsx +++ b/src/pages/model/detail/index.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState, useRef, useMemo, useEffect } from 'react'; +import React, { useCallback, useState, useMemo, useEffect } from 'react'; import { useRouter } from 'next/router'; import { getModelById, delModelById, putModelTrainingStatus, putModelById } from '@/api/model'; import type { ModelSchema } from '@/types/mongoSchema'; @@ -8,16 +8,16 @@ 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 { useQuery } from '@tanstack/react-query'; import dynamic from 'next/dynamic'; +const ModelEditForm = dynamic(() => import('./components/ModelEditForm')); const ModelDataCard = dynamic(() => import('./components/ModelDataCard')); const ModelDetail = ({ modelId }: { modelId: string }) => { const { toast } = useToast(); const router = useRouter(); - const { isPc, media } = useScreen(); + const { isPc } = useScreen(); const { setLoading } = useGlobalStore(); const [model, setModel] = useState(defaultModel); @@ -76,36 +76,6 @@ const ModelDetail = ({ modelId }: { modelId: string }) => { setLoading(false); }, [setLoading, router, modelId]); - /* 上传数据集,触发微调 */ - // const startTraining = useCallback( - // async (e: React.ChangeEvent) => { - // if (!modelId || !e.target.files || e.target.files?.length === 0) return; - // setLoading(true); - // try { - // const file = e.target.files[0]; - // const formData = new FormData(); - // formData.append('file', file); - // await postTrainModel(modelId, formData); - - // toast({ - // title: '开始训练...', - // status: 'success' - // }); - - // // 重新获取模型 - // loadModel(); - // } catch (err: any) { - // toast({ - // title: err?.message || '上传文件失败', - // status: 'error' - // }); - // console.log('error->', err); - // } - // setLoading(false); - // }, - // [setLoading, loadModel, modelId, toast] - // ); - /* 点击更新模型状态 */ const handleClickUpdateStatus = useCallback(async () => { if (!model || model.status !== ModelStatusEnum.training) return; @@ -236,21 +206,12 @@ const ModelDetail = ({ modelId }: { modelId: string }) => { )} - + - {canTrain && model._id && ( - - + {canTrain && !!model._id && ( + + )}