mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-15 23:55:36 +00:00
feat: 模型数据管理
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
"react-hook-form": "^7.43.1",
|
||||
"react-markdown": "^8.0.5",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"redis": "^4.6.5",
|
||||
"rehype-katex": "^6.0.2",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-math": "^5.1.1",
|
||||
|
95
pnpm-lock.yaml
generated
95
pnpm-lock.yaml
generated
@@ -47,6 +47,7 @@ specifiers:
|
||||
react-hook-form: ^7.43.1
|
||||
react-markdown: ^8.0.5
|
||||
react-syntax-highlighter: ^15.5.0
|
||||
redis: ^4.6.5
|
||||
rehype-katex: ^6.0.2
|
||||
remark-gfm: ^3.0.1
|
||||
remark-math: ^5.1.1
|
||||
@@ -87,6 +88,7 @@ dependencies:
|
||||
react-hook-form: registry.npmmirror.com/react-hook-form/7.43.1_react@18.2.0
|
||||
react-markdown: registry.npmmirror.com/react-markdown/8.0.5_pmekkgnqduwlme35zpnqhenc34
|
||||
react-syntax-highlighter: registry.npmmirror.com/react-syntax-highlighter/15.5.0_react@18.2.0
|
||||
redis: registry.npmmirror.com/redis/4.6.5
|
||||
rehype-katex: registry.npmmirror.com/rehype-katex/6.0.2
|
||||
remark-gfm: registry.npmmirror.com/remark-gfm/3.0.1
|
||||
remark-math: registry.npmmirror.com/remark-math/5.1.1
|
||||
@@ -4504,6 +4506,72 @@ packages:
|
||||
version: 2.11.6
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@redis/bloom/1.2.0_@redis+client@1.5.6:
|
||||
resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@redis/bloom/-/bloom-1.2.0.tgz}
|
||||
id: registry.npmmirror.com/@redis/bloom/1.2.0
|
||||
name: '@redis/bloom'
|
||||
version: 1.2.0
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': registry.npmmirror.com/@redis/client/1.5.6
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@redis/client/1.5.6:
|
||||
resolution: {integrity: sha512-dFD1S6je+A47Lj22jN/upVU2fj4huR7S9APd7/ziUXsIXDL+11GPYti4Suv5y8FuXaN+0ZG4JF+y1houEJ7ToA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@redis/client/-/client-1.5.6.tgz}
|
||||
name: '@redis/client'
|
||||
version: 1.5.6
|
||||
engines: {node: '>=14'}
|
||||
dependencies:
|
||||
cluster-key-slot: registry.npmmirror.com/cluster-key-slot/1.1.2
|
||||
generic-pool: registry.npmmirror.com/generic-pool/3.9.0
|
||||
yallist: registry.npmmirror.com/yallist/4.0.0
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@redis/graph/1.1.0_@redis+client@1.5.6:
|
||||
resolution: {integrity: sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@redis/graph/-/graph-1.1.0.tgz}
|
||||
id: registry.npmmirror.com/@redis/graph/1.1.0
|
||||
name: '@redis/graph'
|
||||
version: 1.1.0
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': registry.npmmirror.com/@redis/client/1.5.6
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@redis/json/1.0.4_@redis+client@1.5.6:
|
||||
resolution: {integrity: sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@redis/json/-/json-1.0.4.tgz}
|
||||
id: registry.npmmirror.com/@redis/json/1.0.4
|
||||
name: '@redis/json'
|
||||
version: 1.0.4
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': registry.npmmirror.com/@redis/client/1.5.6
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@redis/search/1.1.2_@redis+client@1.5.6:
|
||||
resolution: {integrity: sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@redis/search/-/search-1.1.2.tgz}
|
||||
id: registry.npmmirror.com/@redis/search/1.1.2
|
||||
name: '@redis/search'
|
||||
version: 1.1.2
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': registry.npmmirror.com/@redis/client/1.5.6
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@redis/time-series/1.0.4_@redis+client@1.5.6:
|
||||
resolution: {integrity: sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@redis/time-series/-/time-series-1.0.4.tgz}
|
||||
id: registry.npmmirror.com/@redis/time-series/1.0.4
|
||||
name: '@redis/time-series'
|
||||
version: 1.0.4
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': registry.npmmirror.com/@redis/client/1.5.6
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@rushstack/eslint-patch/1.2.0:
|
||||
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz}
|
||||
name: '@rushstack/eslint-patch'
|
||||
@@ -5562,6 +5630,13 @@ packages:
|
||||
version: 0.0.1
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/cluster-key-slot/1.1.2:
|
||||
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz}
|
||||
name: cluster-key-slot
|
||||
version: 1.1.2
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/color-convert/1.9.3:
|
||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz}
|
||||
name: color-convert
|
||||
@@ -6799,6 +6874,13 @@ packages:
|
||||
version: 1.2.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/generic-pool/3.9.0:
|
||||
resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/generic-pool/-/generic-pool-3.9.0.tgz}
|
||||
name: generic-pool
|
||||
version: 3.9.0
|
||||
engines: {node: '>= 4'}
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/gensync/1.0.0-beta.2:
|
||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz}
|
||||
name: gensync
|
||||
@@ -9367,6 +9449,19 @@ packages:
|
||||
picomatch: registry.npmmirror.com/picomatch/2.3.1
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/redis/4.6.5:
|
||||
resolution: {integrity: sha512-O0OWA36gDQbswOdUuAhRL6mTZpHFN525HlgZgDaVNgCJIAZR3ya06NTESb0R+TUZ+BFaDpz6NnnVvoMx9meUFg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/redis/-/redis-4.6.5.tgz}
|
||||
name: redis
|
||||
version: 4.6.5
|
||||
dependencies:
|
||||
'@redis/bloom': registry.npmmirror.com/@redis/bloom/1.2.0_@redis+client@1.5.6
|
||||
'@redis/client': registry.npmmirror.com/@redis/client/1.5.6
|
||||
'@redis/graph': registry.npmmirror.com/@redis/graph/1.1.0_@redis+client@1.5.6
|
||||
'@redis/json': registry.npmmirror.com/@redis/json/1.0.4_@redis+client@1.5.6
|
||||
'@redis/search': registry.npmmirror.com/@redis/search/1.1.2_@redis+client@1.5.6
|
||||
'@redis/time-series': registry.npmmirror.com/@redis/time-series/1.0.4_@redis+client@1.5.6
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/refractor/3.6.0:
|
||||
resolution: {integrity: sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/refractor/-/refractor-3.6.0.tgz}
|
||||
name: refractor
|
||||
|
@@ -2,6 +2,9 @@ import { GET, POST, DELETE, PUT } from './request';
|
||||
import type { ModelSchema } from '@/types/mongoSchema';
|
||||
import { ModelUpdateParams } from '@/types/model';
|
||||
import { TrainingItemType } from '../types/training';
|
||||
import { PagingData } from '@/types';
|
||||
import { RequestPaging } from '../types/index';
|
||||
import { Obj2Query } from '@/utils/tools';
|
||||
|
||||
export const getMyModels = () => GET<ModelSchema[]>('/model/list');
|
||||
|
||||
@@ -16,13 +19,30 @@ export const putModelById = (id: string, data: ModelUpdateParams) =>
|
||||
PUT(`/model/update?modelId=${id}`, data);
|
||||
|
||||
export const postTrainModel = (id: string, form: FormData) =>
|
||||
POST(`/model/train?modelId=${id}`, form, {
|
||||
POST(`/model/train/train?modelId=${id}`, form, {
|
||||
headers: {
|
||||
'content-type': 'multipart/form-data'
|
||||
}
|
||||
});
|
||||
|
||||
export const putModelTrainingStatus = (id: string) => PUT(`/model/putTrainStatus?modelId=${id}`);
|
||||
export const putModelTrainingStatus = (id: string) =>
|
||||
PUT(`/model/train/putTrainStatus?modelId=${id}`);
|
||||
|
||||
export const getModelTrainings = (id: string) =>
|
||||
GET<TrainingItemType[]>(`/model/getTrainings?modelId=${id}`);
|
||||
GET<TrainingItemType[]>(`/model/train/getTrainings?modelId=${id}`);
|
||||
|
||||
/* 模型 data */
|
||||
|
||||
type GetModelDataListProps = RequestPaging & {
|
||||
modelId: string;
|
||||
};
|
||||
export const getModelDataList = (props: GetModelDataListProps) =>
|
||||
GET(`/model/data/getModelData?${Obj2Query(props)}`);
|
||||
|
||||
export const postModelData = (data: { modelId: string; data: { q: string; a: string }[] }) =>
|
||||
POST(`/model/data/pushModelData`, data);
|
||||
|
||||
export const putModelDataById = (data: { modelId: string; answer: string }) =>
|
||||
PUT('/model/data/putModelData', data);
|
||||
export const DelOneModelData = (modelId: string) =>
|
||||
DELETE(`/model/data/delModelDataById?modelId=${modelId}`);
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import type { ServiceName } from '@/types/mongoSchema';
|
||||
import { ModelSchema } from '../types/mongoSchema';
|
||||
import type { ServiceName, ModelDataType, ModelSchema } from '@/types/mongoSchema';
|
||||
|
||||
export enum ChatModelNameEnum {
|
||||
GPT35 = 'gpt-3.5-turbo',
|
||||
@@ -76,6 +75,12 @@ export const formatModelStatus = {
|
||||
}
|
||||
};
|
||||
|
||||
export const ModelDataStatusMap: Record<ModelDataType, string> = {
|
||||
0: '训练完成',
|
||||
1: '等待训练',
|
||||
2: '训练中'
|
||||
};
|
||||
|
||||
export const defaultModel: ModelSchema = {
|
||||
_id: '',
|
||||
userId: '',
|
||||
|
@@ -8,7 +8,7 @@ export const usePaging = <T = any>({
|
||||
pageSize = 10,
|
||||
params = {}
|
||||
}: {
|
||||
api: (data: any) => Promise<PagingData<T>>;
|
||||
api: (data: any) => any;
|
||||
pageSize?: number;
|
||||
params?: Record<string, any>;
|
||||
}) => {
|
||||
@@ -30,7 +30,7 @@ export const usePaging = <T = any>({
|
||||
setRequesting(true);
|
||||
|
||||
try {
|
||||
const res = await api({
|
||||
const res: PagingData<T> = await api({
|
||||
pageNum: num,
|
||||
pageSize,
|
||||
...params
|
||||
|
@@ -14,6 +14,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
pageNum: string;
|
||||
pageSize: string;
|
||||
};
|
||||
|
||||
const { authorization } = req.headers;
|
||||
|
||||
pageNum = +pageNum;
|
||||
@@ -41,7 +42,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
.limit(pageSize);
|
||||
|
||||
jsonRes(res, {
|
||||
data
|
||||
data: {
|
||||
pageNum,
|
||||
pageSize,
|
||||
data,
|
||||
total: await ModelData.countDocuments({
|
||||
modelId,
|
||||
userId
|
||||
})
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
|
86
src/pages/model/components/ModelDataCard.tsx
Normal file
86
src/pages/model/components/ModelDataCard.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import React, { useEffect, useCallback, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
TableContainer,
|
||||
Table,
|
||||
Thead,
|
||||
Tbody,
|
||||
Tr,
|
||||
Th,
|
||||
Td,
|
||||
IconButton,
|
||||
Flex,
|
||||
Button
|
||||
} from '@chakra-ui/react';
|
||||
import type { ModelSchema } from '@/types/mongoSchema';
|
||||
import { ModelDataSchema } from '@/types/mongoSchema';
|
||||
import { ModelDataStatusMap } from '@/constants/model';
|
||||
import { usePaging } from '@/hooks/usePaging';
|
||||
import ScrollData from '@/components/ScrollData';
|
||||
import { getModelDataList } from '@/api/model';
|
||||
import { DeleteIcon } from '@chakra-ui/icons';
|
||||
|
||||
const ModelDataCard = ({ model }: { model: ModelSchema }) => {
|
||||
const {
|
||||
nextPage,
|
||||
isLoadAll,
|
||||
requesting,
|
||||
data: dataList,
|
||||
total
|
||||
} = usePaging<ModelDataSchema>({
|
||||
api: getModelDataList,
|
||||
pageSize: 10,
|
||||
params: {
|
||||
modelId: model._id
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex>
|
||||
<Box fontWeight={'bold'} fontSize={'lg'} flex={1}>
|
||||
模型数据: {total}组
|
||||
</Box>
|
||||
<Button size={'sm'}>导入</Button>
|
||||
</Flex>
|
||||
<ScrollData
|
||||
flex={'1 0 0'}
|
||||
h={0}
|
||||
px={6}
|
||||
mt={3}
|
||||
isLoadAll={isLoadAll}
|
||||
requesting={requesting}
|
||||
nextPage={nextPage}
|
||||
fontSize={'xs'}
|
||||
whiteSpace={'pre-wrap'}
|
||||
>
|
||||
<TableContainer mt={4}>
|
||||
<Table variant={'simple'}>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>Question</Th>
|
||||
<Th>Text</Th>
|
||||
<Th>Status</Th>
|
||||
<Th></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{dataList.map((item) => (
|
||||
<Tr key={item._id}>
|
||||
<Td>{item.q}</Td>
|
||||
<Td>{item.a}</Td>
|
||||
<Td>{ModelDataStatusMap[item.status]}</Td>
|
||||
<Td>
|
||||
<IconButton icon={<DeleteIcon />} aria-label={'delete'} />
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</ScrollData>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModelDataCard;
|
@@ -11,13 +11,26 @@ import {
|
||||
SliderFilledTrack,
|
||||
SliderThumb,
|
||||
SliderMark,
|
||||
Tooltip
|
||||
Tooltip,
|
||||
Button
|
||||
} from '@chakra-ui/react';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import type { ModelSchema } from '@/types/mongoSchema';
|
||||
import { UseFormReturn } from 'react-hook-form';
|
||||
import { modelList } from '@/constants/model';
|
||||
import { formatPrice } from '@/utils/user';
|
||||
import { useConfirm } from '@/hooks/useConfirm';
|
||||
|
||||
const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn<ModelSchema> }) => {
|
||||
const ModelEditForm = ({
|
||||
formHooks,
|
||||
handleDelModel
|
||||
}: {
|
||||
formHooks: UseFormReturn<ModelSchema>;
|
||||
handleDelModel: () => void;
|
||||
}) => {
|
||||
const { openConfirm, ConfirmChild } = useConfirm({
|
||||
content: '确认删除该模型?'
|
||||
});
|
||||
const { register, setValue, getValues } = formHooks;
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
|
||||
@@ -29,7 +42,7 @@ const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn<ModelSchema> })
|
||||
</Flex>
|
||||
<FormControl mt={4}>
|
||||
<Flex alignItems={'center'}>
|
||||
<Box flex={'0 0 50px'} w={0}>
|
||||
<Box flex={'0 0 80px'} w={0}>
|
||||
名称:
|
||||
</Box>
|
||||
<Input
|
||||
@@ -39,7 +52,36 @@ const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn<ModelSchema> })
|
||||
></Input>
|
||||
</Flex>
|
||||
</FormControl>
|
||||
<FormControl mt={4}>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Box flex={'0 0 80px'} w={0}>
|
||||
底层模型:
|
||||
</Box>
|
||||
<Box>{getValues('service.modelName')}</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Box flex={'0 0 80px'} w={0}>
|
||||
价格:
|
||||
</Box>
|
||||
<Box>
|
||||
{formatPrice(
|
||||
modelList.find((item) => item.model === getValues('service.modelName'))?.price || 0,
|
||||
1000
|
||||
)}
|
||||
元/1K tokens(包括上下文和回答)
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex mt={5} alignItems={'center'}>
|
||||
<Box flex={'0 0 80px'}>删除:</Box>
|
||||
<Button
|
||||
colorScheme={'gray'}
|
||||
variant={'outline'}
|
||||
size={'sm'}
|
||||
onClick={openConfirm(handleDelModel)}
|
||||
>
|
||||
删除模型
|
||||
</Button>
|
||||
</Flex>
|
||||
{/* <FormControl mt={4}>
|
||||
<Box mb={1}>介绍:</Box>
|
||||
<Textarea
|
||||
rows={5}
|
||||
@@ -47,7 +89,7 @@ const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn<ModelSchema> })
|
||||
{...register('intro')}
|
||||
placeholder={'模型的介绍,仅做展示,不影响模型的效果'}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormControl> */}
|
||||
</Card>
|
||||
<Card p={4}>
|
||||
<Box fontWeight={'bold'}>模型效果</Box>
|
||||
@@ -202,6 +244,7 @@ const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn<ModelSchema> })
|
||||
</Flex>
|
||||
</FormControl>
|
||||
</Card> */}
|
||||
<ConfirmChild />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -11,36 +11,34 @@ import { getChatSiteId } from '@/api/chat';
|
||||
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 { 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 Icon from '@/components/Iconfont';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import dynamic from 'next/dynamic';
|
||||
// import dynamic from 'next/dynamic';
|
||||
import ModelDataCard from './components/ModelDataCard';
|
||||
|
||||
const Training = dynamic(() => import('./components/Training'));
|
||||
// const Training = dynamic(() => import('./components/Training'));
|
||||
|
||||
const ModelDetail = ({ modelId }: { modelId: string }) => {
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const { isPc, media } = useScreen();
|
||||
const { setLoading } = useGlobalStore();
|
||||
const { openConfirm, ConfirmChild } = useConfirm({
|
||||
content: '确认删除该模型?'
|
||||
});
|
||||
|
||||
const SelectFileDom = useRef<HTMLInputElement>(null);
|
||||
const [model, setModel] = useState<ModelSchema>(defaultModel);
|
||||
const formHooks = useForm<ModelSchema>({
|
||||
defaultValues: model
|
||||
});
|
||||
|
||||
const canTrain = useMemo(() => {
|
||||
const openai = modelList.find((item) => item.model === model?.service.modelName);
|
||||
return openai && openai.trainName;
|
||||
}, [model]);
|
||||
// const canTrain = useMemo(() => {
|
||||
// const openai = modelList.find((item) => item.model === model?.service.modelName);
|
||||
// return openai && openai.trainName;
|
||||
// }, [model]);
|
||||
|
||||
/* 加载模型数据 */
|
||||
const loadModel = useCallback(async () => {
|
||||
@@ -250,79 +248,15 @@ const ModelDetail = ({ modelId }: { modelId: string }) => {
|
||||
)}
|
||||
</Card>
|
||||
<Grid mt={5} gridTemplateColumns={media('1fr 1fr', '1fr')} gridGap={5}>
|
||||
<ModelEditForm formHooks={formHooks} />
|
||||
<ModelEditForm formHooks={formHooks} handleDelModel={handleDelModel} />
|
||||
|
||||
{canTrain && (
|
||||
{/* {canTrain && (
|
||||
<Card p={4}>
|
||||
<Training model={model} />
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<Card p={4}>
|
||||
<Box fontWeight={'bold'} fontSize={'lg'}>
|
||||
神奇操作
|
||||
</Box>
|
||||
<Flex mt={5} alignItems={'center'}>
|
||||
<Box flex={'0 0 80px'}>模型微调:</Box>
|
||||
<Button
|
||||
size={'sm'}
|
||||
onClick={() => {
|
||||
SelectFileDom.current?.click();
|
||||
}}
|
||||
title={!canTrain ? '模型不支持微调' : ''}
|
||||
isDisabled={!canTrain}
|
||||
>
|
||||
上传数据集
|
||||
</Button>
|
||||
<Flex
|
||||
as={'a'}
|
||||
href="/TrainingTemplate.jsonl"
|
||||
download
|
||||
ml={5}
|
||||
cursor={'pointer'}
|
||||
alignItems={'center'}
|
||||
color={'blue.500'}
|
||||
>
|
||||
<Icon name={'icon-yunxiazai'} color={'#3182ce'} />
|
||||
下载模板
|
||||
</Flex>
|
||||
</Flex>
|
||||
{/* 提示 */}
|
||||
<Box mt={3} py={3} color={'blackAlpha.600'}>
|
||||
<Box as={'li'} lineHeight={1.9}>
|
||||
暂时需要使用自己的openai key
|
||||
</Box>
|
||||
<Box as={'li'} lineHeight={1.9}>
|
||||
可以使用
|
||||
<Box
|
||||
as={'span'}
|
||||
fontWeight={'bold'}
|
||||
textDecoration={'underline'}
|
||||
color={'blackAlpha.800'}
|
||||
mx={2}
|
||||
cursor={'pointer'}
|
||||
onClick={() => router.push('/data/list')}
|
||||
>
|
||||
数据拆分
|
||||
</Box>
|
||||
功能,从任意文本中提取数据集。
|
||||
</Box>
|
||||
<Box as={'li'} lineHeight={1.9}>
|
||||
每行包括一个 prompt 和一个 completion
|
||||
</Box>
|
||||
<Box as={'li'} lineHeight={1.9}>
|
||||
prompt 必须以 {'</s>'} 结尾
|
||||
</Box>
|
||||
<Box as={'li'} lineHeight={1.9}>
|
||||
completion 开头必须有一个空格,必须以 {'</s>'} 结尾
|
||||
</Box>
|
||||
</Box>
|
||||
<Flex mt={5} alignItems={'center'}>
|
||||
<Box flex={'0 0 80px'}>删除模型:</Box>
|
||||
<Button colorScheme={'red'} size={'sm'} onClick={openConfirm(handleDelModel)}>
|
||||
删除模型
|
||||
</Button>
|
||||
</Flex>
|
||||
)} */}
|
||||
<Card p={4} height={'400px'} gridColumnStart={1} gridColumnEnd={3}>
|
||||
{model._id && <ModelDataCard model={model} />}
|
||||
</Card>
|
||||
</Grid>
|
||||
|
||||
@@ -330,7 +264,6 @@ const ModelDetail = ({ modelId }: { modelId: string }) => {
|
||||
<Box position={'absolute'} w={0} h={0} overflow={'hidden'}>
|
||||
<input ref={SelectFileDom} type="file" accept=".jsonl" onChange={startTraining} />
|
||||
</Box>
|
||||
<ConfirmChild />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateQA } from './events/generateQA';
|
||||
import { generateAbstract } from './events/generateAbstract';
|
||||
import { connectRedis } from './redis';
|
||||
|
||||
/**
|
||||
* 连接 MongoDB 数据库
|
||||
@@ -28,6 +29,7 @@ export async function connectToDatabase(): Promise<void> {
|
||||
|
||||
generateQA();
|
||||
generateAbstract();
|
||||
// connectRedis();
|
||||
}
|
||||
|
||||
export * from './models/authCode';
|
||||
|
74
src/service/redis.ts
Normal file
74
src/service/redis.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { createClient, SchemaFieldTypes } from 'redis';
|
||||
|
||||
export const connectRedis = async () => {
|
||||
// 断开了,重连
|
||||
if (global.redisClient && !global.redisClient.isOpen) {
|
||||
await global.redisClient.disconnect();
|
||||
} else if (global.redisClient) {
|
||||
// 没断开,不再连接
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
global.redisClient = createClient({
|
||||
url: 'redis://:121914yu@120.76.193.200:8100'
|
||||
});
|
||||
|
||||
global.redisClient.on('error', (err) => {
|
||||
console.log('Redis Client Error', err);
|
||||
global.redisClient = null;
|
||||
});
|
||||
global.redisClient.on('end', () => {
|
||||
global.redisClient = null;
|
||||
});
|
||||
global.redisClient.on('ready', () => {
|
||||
console.log('redis connected');
|
||||
});
|
||||
|
||||
await global.redisClient.connect();
|
||||
|
||||
// 0 - 测试库,1 - 正式
|
||||
await global.redisClient.select(0);
|
||||
|
||||
// 创建索引
|
||||
await global.redisClient.ft.create(
|
||||
'vec:question',
|
||||
{
|
||||
'$.vector': SchemaFieldTypes.VECTOR,
|
||||
'$.modelId': {
|
||||
type: SchemaFieldTypes.TEXT,
|
||||
AS: 'modelId'
|
||||
},
|
||||
'$.userId': {
|
||||
type: SchemaFieldTypes.TEXT,
|
||||
AS: 'userId'
|
||||
},
|
||||
'$.status': {
|
||||
type: SchemaFieldTypes.NUMERIC,
|
||||
AS: 'status'
|
||||
}
|
||||
},
|
||||
{
|
||||
ON: 'JSON',
|
||||
PREFIX: 'fastgpt:modeldata'
|
||||
}
|
||||
);
|
||||
|
||||
// await global.redisClient.json.set('fastgpt:modeldata:1', '$', {
|
||||
// vector: [],
|
||||
// modelId: 'daf',
|
||||
// userId: 'adfd',
|
||||
// q: 'fasf',
|
||||
// a: 'afasf',
|
||||
// status: 0,
|
||||
// createTime: new Date()
|
||||
// });
|
||||
// const value = await global.redisClient.get('fastgpt:modeldata:1');
|
||||
|
||||
// console.log(value);
|
||||
} catch (error) {
|
||||
console.log(error, '==');
|
||||
global.redisClient = null;
|
||||
return Promise.reject('redis 连接失败');
|
||||
}
|
||||
};
|
2
src/types/index.d.ts
vendored
2
src/types/index.d.ts
vendored
@@ -1,7 +1,9 @@
|
||||
import type { Mongoose } from 'mongoose';
|
||||
import type { RedisClientType } from 'redis';
|
||||
|
||||
declare global {
|
||||
var mongodb: Mongoose | string | null;
|
||||
var redisClient: RedisClientType | null;
|
||||
var generatingQA: boolean;
|
||||
var generatingAbstract: boolean;
|
||||
var QRCode: any;
|
||||
|
3
src/types/mongoSchema.d.ts
vendored
3
src/types/mongoSchema.d.ts
vendored
@@ -51,11 +51,12 @@ export interface ModelPopulate extends ModelSchema {
|
||||
userId: UserModelSchema;
|
||||
}
|
||||
|
||||
export type ModelDataType = 0 | 1 | 2;
|
||||
export interface ModelDataSchema {
|
||||
_id: string;
|
||||
q: string;
|
||||
a: string;
|
||||
status: 0 | 1 | 2;
|
||||
status: ModelDataType;
|
||||
createTime: Date;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user