4.6.7 first pr (#726)

This commit is contained in:
Archer
2024-01-10 23:35:04 +08:00
committed by GitHub
parent 414b693303
commit 006ad17c6a
186 changed files with 2996 additions and 1838 deletions

View File

@@ -32,16 +32,17 @@ import { useRouter } from 'next/router';
import MyIcon from '@fastgpt/web/components/common/Icon';
import MyInput from '@/components/MyInput';
import { useLoading } from '@/web/common/hooks/useLoading';
import InputDataModal, { RawSourceText, type InputDataType } from '../components/InputDataModal';
import InputDataModal from '../components/InputDataModal';
import RawSourceBox from '@/components/core/dataset/RawSourceBox';
import type { DatasetDataListItemType } from '@/global/core/dataset/type.d';
import { TabEnum } from '..';
import { useUserStore } from '@/web/support/user/useUserStore';
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
import { getDefaultIndex } from '@fastgpt/global/core/dataset/utils';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import {
DatasetCollectionTypeMap,
DatasetCollectionTrainingTypeMap
TrainingModeEnum,
TrainingTypeMap
} from '@fastgpt/global/core/dataset/constant';
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
import { formatFileSize } from '@fastgpt/global/common/file/tools';
@@ -90,7 +91,7 @@ const DataCard = () => {
}
});
const [editInputData, setEditInputData] = useState<InputDataType>();
const [editDataId, setEditDataId] = useState<string>();
// get first page data
const getFirstData = useCallback(
@@ -154,7 +155,7 @@ const DataCard = () => {
},
{
label: t('core.dataset.collection.metadata.Training Type'),
value: t(DatasetCollectionTrainingTypeMap[collection.trainingType]?.label)
value: t(TrainingTypeMap[collection.trainingType]?.label)
},
{
label: t('core.dataset.collection.metadata.Chunk Size'),
@@ -193,7 +194,7 @@ const DataCard = () => {
/>
<Flex className="textEllipsis" flex={'1 0 0'} mr={[3, 5]} alignItems={'center'}>
<Box lineHeight={1.2}>
<RawSourceText
<RawSourceBox
sourceName={collection?.name}
sourceId={collection?.fileId || collection?.rawLink}
fontSize={['md', 'lg']}
@@ -216,10 +217,7 @@ const DataCard = () => {
size={['sm', 'md']}
onClick={() => {
if (!collection) return;
setEditInputData({
q: '',
indexes: [getDefaultIndex({ dataId: `${Date.now()}` })]
});
setEditDataId('');
}}
>
{t('dataset.Insert Data')}
@@ -297,12 +295,7 @@ const DataCard = () => {
}}
onClick={() => {
if (!collection) return;
setEditInputData({
id: item._id,
q: item.q,
a: item.a,
indexes: item.indexes
});
setEditDataId(item._id);
}}
>
<Flex zIndex={1} alignItems={'center'} justifyContent={'space-between'}>
@@ -424,11 +417,11 @@ const DataCard = () => {
</Flex>
)}
{editInputData !== undefined && collection && (
{editDataId !== undefined && collection && (
<InputDataModal
collectionId={collection._id}
defaultValue={editInputData}
onClose={() => setEditInputData(undefined)}
dataId={editDataId}
onClose={() => setEditDataId(undefined)}
onSuccess={() => getData(pageNum)}
onDelete={() => getData(pageNum)}
/>

View File

@@ -4,14 +4,8 @@ import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
import { useToast } from '@/web/common/hooks/useToast';
import { splitText2Chunks } from '@fastgpt/global/common/string/textSplitter';
import { simpleText } from '@fastgpt/global/common/string/tools';
import {
fileDownload,
readCsvContent,
readPdfContent,
readDocContent
} from '@/web/common/file/utils';
import { readFileRawText, readMdFile, readHtmlFile } from '@fastgpt/web/common/file/read';
import { getUploadMdImgController, uploadFiles } from '@/web/common/file/controller';
import { fileDownload, readCsvContent } from '@/web/common/file/utils';
import { getUploadBase64ImgController, uploadFiles } from '@/web/common/file/controller';
import { Box, Flex, useDisclosure, type BoxProps } from '@chakra-ui/react';
import React, { DragEvent, useCallback, useState } from 'react';
import { useTranslation } from 'next-i18next';
@@ -25,6 +19,8 @@ import { countPromptTokens } from '@fastgpt/global/common/string/tiktoken';
import { DatasetCollectionTypeEnum } from '@fastgpt/global/core/dataset/constant';
import type { PushDatasetDataChunkProps } from '@fastgpt/global/core/dataset/api.d';
import { UrlFetchResponse } from '@fastgpt/global/common/file/api.d';
import { readFileRawContent } from '@fastgpt/web/common/file/read/index';
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
const UrlFetchModal = dynamic(() => import('./UrlFetchModal'));
const CreateFileModal = dynamic(() => import('./CreateFileModal'));
@@ -168,36 +164,22 @@ const FileSelect = ({
}
// parse and upload files
let text = await (async () => {
switch (extension) {
case 'txt':
return readFileRawText(file);
case 'md':
return readMdFile({
file,
uploadImgController: (base64Img) =>
getUploadMdImgController({ base64Img, metadata: { fileId } })
});
case 'html':
return readHtmlFile({
file,
uploadImgController: (base64Img) =>
getUploadMdImgController({ base64Img, metadata: { fileId } })
});
case 'pdf':
return readPdfContent(file);
case 'docx':
return readDocContent(file, {
let { rawText } = await readFileRawContent({
file,
uploadBase64Controller: (base64Img) =>
getUploadBase64ImgController({
base64Img,
type: MongoImageTypeEnum.docImage,
metadata: {
fileId
});
}
return '';
})();
}
})
});
if (text) {
text = simpleText(text);
if (rawText) {
rawText = simpleText(rawText);
const { chunks, tokens } = splitText2Chunks({
text,
text: rawText,
chunkLen,
overlapRatio,
customReg: customSplitChar ? [customSplitChar] : []
@@ -207,7 +189,7 @@ const FileSelect = ({
id: nanoid(),
filename: file.name,
icon,
rawText: text,
rawText,
tokens,
type: DatasetCollectionTypeEnum.file,
fileId,

View File

@@ -10,10 +10,7 @@ const CsvImport = dynamic(() => import('./Csv'), {});
import MyModal from '@/components/MyModal';
import Provider from './Provider';
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
import {
DatasetCollectionTrainingModeEnum,
TrainingModeEnum
} from '@fastgpt/global/core/dataset/constant';
import { TrainingModeEnum } from '@fastgpt/global/core/dataset/constant';
export enum ImportTypeEnum {
chunk = 'chunk',
@@ -46,24 +43,21 @@ const ImportData = ({
chunkOverlapRatio: 0.2,
inputPrice: vectorModel?.inputPrice || 0,
outputPrice: 0,
mode: TrainingModeEnum.chunk,
collectionTrainingType: DatasetCollectionTrainingModeEnum.chunk
collectionTrainingType: TrainingModeEnum.chunk
},
[ImportTypeEnum.qa]: {
defaultChunkLen: agentModel?.maxContext * 0.55 || 8000,
chunkOverlapRatio: 0,
inputPrice: agentModel?.inputPrice || 0,
outputPrice: agentModel?.outputPrice || 0,
mode: TrainingModeEnum.qa,
collectionTrainingType: DatasetCollectionTrainingModeEnum.qa
collectionTrainingType: TrainingModeEnum.qa
},
[ImportTypeEnum.csv]: {
defaultChunkLen: 0,
chunkOverlapRatio: 0,
inputPrice: vectorModel?.inputPrice || 0,
outputPrice: 0,
mode: TrainingModeEnum.chunk,
collectionTrainingType: DatasetCollectionTrainingModeEnum.manual
collectionTrainingType: TrainingModeEnum.chunk
}
};
return map[importType];

View File

@@ -16,10 +16,7 @@ import { splitText2Chunks } from '@fastgpt/global/common/string/textSplitter';
import { hashStr } from '@fastgpt/global/common/string/tools';
import { useToast } from '@/web/common/hooks/useToast';
import { getErrText } from '@fastgpt/global/common/error/utils';
import {
DatasetCollectionTrainingModeEnum,
TrainingModeEnum
} from '@fastgpt/global/core/dataset/constant';
import { TrainingModeEnum } from '@fastgpt/global/core/dataset/constant';
import { Box, Flex, Image, useTheme } from '@chakra-ui/react';
import { CloseIcon } from '@chakra-ui/icons';
import DeleteIcon, { hoverDeleteStyles } from '@fastgpt/web/components/common/Icon/delete';
@@ -104,7 +101,6 @@ const Provider = ({
parentId,
inputPrice,
outputPrice,
mode,
collectionTrainingType,
vectorModel,
agentModel,
@@ -118,8 +114,7 @@ const Provider = ({
parentId: string;
inputPrice: number;
outputPrice: number;
mode: `${TrainingModeEnum}`;
collectionTrainingType: `${DatasetCollectionTrainingModeEnum}`;
collectionTrainingType: `${TrainingModeEnum}`;
vectorModel: string;
agentModel: string;
defaultChunkLen: number;
@@ -147,14 +142,14 @@ const Provider = ({
const totalTokens = useMemo(() => files.reduce((sum, file) => sum + file.tokens, 0), [files]);
const price = useMemo(() => {
if (mode === TrainingModeEnum.qa) {
if (collectionTrainingType === TrainingModeEnum.qa) {
const inputTotal = totalTokens * inputPrice;
const outputTotal = totalTokens * 0.5 * outputPrice;
return formatModelPrice2Read(inputTotal + outputTotal);
}
return formatModelPrice2Read(totalTokens * inputPrice);
}, [inputPrice, mode, outputPrice, totalTokens]);
}, [collectionTrainingType, inputPrice, outputPrice, totalTokens]);
/*
start upload data
@@ -169,7 +164,7 @@ const Provider = ({
for await (const file of files) {
// create training bill
const billId = await postCreateTrainingBill({
name: t('dataset.collections.Create Training Data', { filename: file.filename }),
name: file.filename,
vectorModel,
agentModel
});
@@ -180,11 +175,15 @@ const Provider = ({
parentId,
name: file.filename,
type: file.type,
trainingType: collectionTrainingType,
chunkSize: chunkLen,
chunkSplitter: customSplitChar,
qaPrompt: collectionTrainingType === TrainingModeEnum.qa ? prompt : '',
fileId: file.fileId,
rawLink: file.rawLink,
chunkSize: chunkLen,
trainingType: collectionTrainingType,
qaPrompt: mode === TrainingModeEnum.qa ? prompt : '',
rawTextLength: file.rawText.length,
hashRawText: hashStr(file.rawText),
metadata: file.metadata
@@ -195,8 +194,8 @@ const Provider = ({
const { insertLen } = await chunksUpload({
collectionId,
billId,
trainingMode: collectionTrainingType,
chunks,
mode,
onUploading: (insertLen) => {
setSuccessChunks((state) => state + insertLen);
},

View File

@@ -1,10 +1,9 @@
import React, { useCallback, useState, useMemo } from 'react';
import React, { useState, useMemo } from 'react';
import { useRouter } from 'next/router';
import { Box, Flex, Button, IconButton, Input, Textarea } from '@chakra-ui/react';
import { DeleteIcon } from '@chakra-ui/icons';
import { delDatasetById } from '@/web/core/dataset/api';
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
import { useToast } from '@/web/common/hooks/useToast';
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
import { useConfirm } from '@/web/common/hooks/useConfirm';
import { useForm } from 'react-hook-form';
@@ -17,6 +16,7 @@ import PermissionRadio from '@/components/support/permission/Radio';
import MySelect from '@/components/Select';
import { qaModelList } from '@/web/common/system/staticData';
import { useRequest } from '@/web/common/hooks/useRequest';
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
const Info = ({ datasetId }: { datasetId: string }) => {
const { t } = useTranslation();
@@ -70,6 +70,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
const file = e[0];
if (!file) return Promise.resolve(null);
return compressImgFileAndUpload({
type: MongoImageTypeEnum.datasetAvatar,
file,
maxW: 300,
maxH: 300

View File

@@ -1,44 +1,38 @@
import React, { useMemo, useState } from 'react';
import { Box, Flex, Button, Textarea, BoxProps, Image, useTheme, Grid } from '@chakra-ui/react';
import { Box, Flex, Button, Textarea, useTheme, Grid } from '@chakra-ui/react';
import { useFieldArray, useForm } from 'react-hook-form';
import {
postInsertData2Dataset,
putDatasetDataById,
delOneDatasetDataById,
getDatasetCollectionById
getDatasetCollectionById,
getDatasetDataItemById
} from '@/web/core/dataset/api';
import { useToast } from '@/web/common/hooks/useToast';
import { getErrText } from '@fastgpt/global/common/error/utils';
import MyIcon from '@fastgpt/web/components/common/Icon';
import MyModal from '@/components/MyModal';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'next-i18next';
import { getFileAndOpen } from '@/web/core/dataset/utils';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useRequest } from '@/web/common/hooks/useRequest';
import { countPromptTokens } from '@fastgpt/global/common/string/tiktoken';
import { useConfirm } from '@/web/common/hooks/useConfirm';
import { getDefaultIndex, getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
import { feConfigs, vectorModelList } from '@/web/common/system/staticData';
import { getDefaultIndex } from '@fastgpt/global/core/dataset/utils';
import { vectorModelList } from '@/web/common/system/staticData';
import { DatasetDataIndexTypeEnum } from '@fastgpt/global/core/dataset/constant';
import { DatasetDataIndexItemType } from '@fastgpt/global/core/dataset/type';
import SideTabs from '@/components/SideTabs';
import { useLoading } from '@/web/common/hooks/useLoading';
import DeleteIcon from '@fastgpt/web/components/common/Icon/delete';
import { defaultCollectionDetail } from '@/constants/dataset';
import { getDocPath } from '@/web/common/system/doc';
import RawSourceBox from '@/components/core/dataset/RawSourceBox';
import MyBox from '@/components/common/MyBox';
import { getErrText } from '@fastgpt/global/common/error/utils';
export type RawSourceTextProps = BoxProps & {
sourceName?: string;
sourceId?: string;
canView?: boolean;
};
export type InputDataType = {
id?: string;
q: string;
a?: string;
a: string;
indexes: (Omit<DatasetDataIndexItemType, 'dataId'> & {
dataId?: string; // pg data id
})[];
@@ -53,26 +47,25 @@ enum TabEnum {
const InputDataModal = ({
collectionId,
dataId,
defaultValue,
onClose,
onSuccess,
onDelete
}: {
collectionId: string;
defaultValue: InputDataType;
dataId?: string;
defaultValue?: { q: string; a?: string };
onClose: () => void;
onSuccess: (data: InputDataType) => void;
onSuccess: (data: InputDataType & { dataId: string }) => void;
onDelete?: () => void;
}) => {
const { t } = useTranslation();
const theme = useTheme();
const { toast } = useToast();
const { Loading } = useLoading();
const [currentTab, setCurrentTab] = useState(TabEnum.content);
const { register, handleSubmit, reset, control } = useForm<InputDataType>({
defaultValues: defaultValue
});
const { register, handleSubmit, reset, control } = useForm<InputDataType>();
const {
fields: indexes,
append: appendIndexes,
@@ -89,14 +82,15 @@ const InputDataModal = ({
id: TabEnum.index,
icon: 'kbTest'
},
...(defaultValue.id
...(dataId
? [{ label: t('dataset.data.edit.Delete'), id: TabEnum.delete, icon: 'delete' }]
: []),
{ label: t('dataset.data.edit.Course'), id: TabEnum.doc, icon: 'common/courseLight' }
];
const { ConfirmModal, openConfirm } = useConfirm({
content: t('dataset.data.Delete Tip')
content: t('dataset.data.Delete Tip'),
type: 'delete'
});
const { data: collection = defaultCollectionDetail } = useQuery(
@@ -105,6 +99,37 @@ const InputDataModal = ({
return getDatasetCollectionById(collectionId);
}
);
const { isFetching: isFetchingData } = useQuery(
['getDatasetDataItemById', dataId],
() => {
if (dataId) return getDatasetDataItemById(dataId);
return null;
},
{
onSuccess(res) {
if (res) {
reset({
q: res.q,
a: res.a,
indexes: res.indexes
});
} else if (defaultValue) {
reset({
q: defaultValue.q,
a: defaultValue.a,
indexes: [getDefaultIndex({ dataId: `${Date.now()}` })]
});
}
},
onError(err) {
toast({
status: 'error',
title: getErrText(err)
});
onClose();
}
}
);
const maxToken = useMemo(() => {
const vectorModel =
@@ -130,7 +155,7 @@ const InputDataModal = ({
const data = { ...e };
data.id = await postInsertData2Dataset({
const dataId = await postInsertData2Dataset({
collectionId: collection._id,
q: e.q,
a: e.a,
@@ -140,7 +165,10 @@ const InputDataModal = ({
)
});
return data;
return {
...data,
dataId
};
},
successToast: t('dataset.data.Input Success Tip'),
onSuccess(e) {
@@ -158,17 +186,18 @@ const InputDataModal = ({
// update
const { mutate: onUpdateData, isLoading: isUpdating } = useRequest({
mutationFn: async (e: InputDataType) => {
if (!e.id) return e;
if (!dataId) return e;
// not exactly same
await putDatasetDataById({
id: e.id,
q: e.q,
a: e.a,
indexes: e.indexes
id: dataId,
...e
});
return e;
return {
dataId,
...e
};
},
successToast: t('dataset.data.Update Success Tip'),
errorToast: t('common.error.unKnow'),
@@ -180,8 +209,8 @@ const InputDataModal = ({
// delete
const { mutate: onDeleteData, isLoading: isDeleting } = useRequest({
mutationFn: () => {
if (!onDelete || !defaultValue.id) return Promise.resolve(null);
return delOneDatasetDataById(defaultValue.id);
if (!onDelete || !dataId) return Promise.resolve(null);
return delOneDatasetDataById(dataId);
},
onSuccess() {
if (!onDelete) return;
@@ -192,13 +221,16 @@ const InputDataModal = ({
errorToast: t('common.error.unKnow')
});
const loading = useMemo(() => isImporting || isUpdating, [isImporting, isUpdating]);
const isLoading = useMemo(
() => isImporting || isUpdating || isFetchingData || isDeleting,
[isImporting, isUpdating, isFetchingData, isDeleting]
);
return (
<MyModal isOpen={true} isCentered w={'90vw'} maxW={'1440px'} h={'90vh'}>
<Flex h={'100%'}>
<MyBox isLoading={isLoading} display={'flex'} h={'100%'}>
<Box p={5} borderRight={theme.borders.base}>
<RawSourceText
<RawSourceBox
w={'200px'}
className="textEllipsis3"
whiteSpace={'pre-wrap'}
@@ -224,7 +256,7 @@ const InputDataModal = ({
<Flex flexDirection={'column'} py={3} flex={1} h={'100%'}>
<Box fontSize={'lg'} px={5} fontWeight={'bold'} mb={4}>
{currentTab === TabEnum.content && (
<>{defaultValue.id ? t('dataset.data.Update Data') : t('dataset.data.Input Data')}</>
<>{dataId ? t('dataset.data.Update Data') : t('dataset.data.Input Data')}</>
)}
{currentTab === TabEnum.index && <> {t('dataset.data.Index Edit')}</>}
</Box>
@@ -351,82 +383,24 @@ const InputDataModal = ({
)}
</Box>
<Flex justifyContent={'flex-end'} px={5} mt={4}>
<Button variant={'whitePrimary'} mr={3} isLoading={loading} onClick={onClose}>
<Button variant={'whiteBase'} mr={3} onClick={onClose}>
{t('common.Close')}
</Button>
<MyTooltip label={collection.canWrite ? '' : t('dataset.data.Can not edit')}>
<Button
isDisabled={!collection.canWrite}
isLoading={loading}
// @ts-ignore
onClick={handleSubmit(defaultValue.id ? onUpdateData : sureImportData)}
onClick={handleSubmit(dataId ? onUpdateData : sureImportData)}
>
{defaultValue.id ? t('common.Confirm Update') : t('common.Confirm Import')}
{dataId ? t('common.Confirm Update') : t('common.Confirm Import')}
</Button>
</MyTooltip>
</Flex>
</Flex>
</Flex>
</MyBox>
<ConfirmModal />
<Loading fixed={false} loading={isDeleting} />
</MyModal>
);
};
export default InputDataModal;
export function RawSourceText({
sourceId,
sourceName = '',
canView = true,
...props
}: RawSourceTextProps) {
const { t } = useTranslation();
const { toast } = useToast();
const { setLoading } = useSystemStore();
const canPreview = useMemo(() => !!sourceId && canView, [canView, sourceId]);
const icon = useMemo(() => getSourceNameIcon({ sourceId, sourceName }), [sourceId, sourceName]);
return (
<MyTooltip
label={canPreview ? t('file.Click to view file') || '' : ''}
shouldWrapChildren={false}
>
<Box
color={'myGray.600'}
display={'inline-flex'}
whiteSpace={'nowrap'}
{...(canPreview
? {
cursor: 'pointer',
textDecoration: 'underline',
onClick: async () => {
setLoading(true);
try {
await getFileAndOpen(sourceId as string);
} catch (error) {
toast({
title: t(getErrText(error, 'error.fileNotFound')),
status: 'error'
});
}
setLoading(false);
}
}
: {})}
{...props}
>
<Image src={icon} alt="" w={['14px', '16px']} mr={2} />
<Box
maxW={['200px', '300px']}
className={props.className ?? 'textEllipsis'}
wordBreak={'break-all'}
>
{sourceName || t('common.UnKnow Source')}
</Box>
</Box>
</MyTooltip>
);
}
export default React.memo(InputDataModal);

View File

@@ -233,7 +233,7 @@ const Test = ({ datasetId }: { datasetId: string }) => {
h={'100%'}
resize={'none'}
variant={'unstyled'}
maxLength={datasetDetail.vectorModel.maxToken}
maxLength={datasetDetail.vectorModel?.maxToken}
placeholder={t('core.dataset.test.Test Text Placeholder')}
onFocus={() => setIsFocus(true)}
{...register('inputText', {
@@ -314,7 +314,7 @@ const Test = ({ datasetId }: { datasetId: string }) => {
</Box>
</Box>
{/* result show */}
<Box p={4} h={['auto', '100%']} overflow={'overlay'} flex={'1 0 0'}>
<Box p={4} h={['auto', '100%']} overflow={'overlay'} flex={'1 0 0'} bg={'white'}>
<TestResults datasetTestItem={datasetTestItem} />
</Box>
@@ -384,6 +384,9 @@ const TestHistories = React.memo(function TestHistories({
}}
cursor={'pointer'}
fontSize={'sm'}
{...(item.id === datasetTestItem?.id && {
bg: 'primary.50'
})}
onClick={() => setDatasetTestItem(item)}
>
<Box flex={'0 0 80px'}>

View File

@@ -16,8 +16,6 @@ import { serviceSideProps } from '@/web/common/utils/i18n';
import { useTranslation } from 'next-i18next';
import { getTrainingQueueLen } from '@/web/core/dataset/api';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { feConfigs } from '@/web/common/system/staticData';
import Script from 'next/script';
import CollectionCard from './components/CollectionCard';
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
@@ -29,6 +27,7 @@ import {
} from '@fastgpt/global/core/dataset/constant';
import { useConfirm } from '@/web/common/hooks/useConfirm';
import { useRequest } from '@/web/common/hooks/useRequest';
import DatasetTypeTag from '@/components/core/dataset/DatasetTypeTag';
const DataCard = dynamic(() => import('./components/DataCard'), {
ssr: false
@@ -150,50 +149,47 @@ const Detail = ({ datasetId, currentTab }: { datasetId: string; currentTab: `${T
{isPc ? (
<Flex
flexDirection={'column'}
p={4}
py={4}
h={'100%'}
flex={'0 0 200px'}
borderRight={theme.borders.base}
>
<Flex mb={4} alignItems={'center'}>
<Avatar src={datasetDetail.avatar} w={'34px'} borderRadius={'md'} />
<Box ml={2}>
<Box fontWeight={'bold'}>{datasetDetail.name}</Box>
</Box>
</Flex>
{DatasetTypeMap[datasetDetail.type] && (
<Flex alignItems={'center'} pl={2}>
<MyIcon
name={DatasetTypeMap[datasetDetail.type]?.icon as any}
mr={1}
w={'16px'}
/>
<Box flex={1}>{t(DatasetTypeMap[datasetDetail.type]?.label)}</Box>
{datasetDetail.type === DatasetTypeEnum.websiteDataset &&
datasetDetail.status === DatasetStatusEnum.active && (
<MyTooltip label={t('core.dataset.website.Start Sync')}>
<MyIcon
mt={1}
name={'common/refreshLight'}
w={'12px'}
color={'myGray.500'}
cursor={'pointer'}
onClick={() =>
openConfirmSync(
onUpdateDatasetWebsiteConfig,
undefined,
t('core.dataset.website.Confirm Create Tips')
)()
}
/>
</MyTooltip>
)}
<Box px={4} borderBottom={'1px'} borderColor={'myGray.200'} pb={4} mb={4}>
<Flex mb={4} alignItems={'center'}>
<Avatar src={datasetDetail.avatar} w={'34px'} borderRadius={'md'} />
<Box ml={2}>
<Box fontWeight={'bold'}>{datasetDetail.name}</Box>
</Box>
</Flex>
)}
{DatasetTypeMap[datasetDetail.type] && (
<Flex alignItems={'center'} pl={2} justifyContent={'space-between'}>
<DatasetTypeTag type={datasetDetail.type} />
{datasetDetail.type === DatasetTypeEnum.websiteDataset &&
datasetDetail.status === DatasetStatusEnum.active && (
<MyTooltip label={t('core.dataset.website.Start Sync')}>
<MyIcon
mt={1}
name={'common/refreshLight'}
w={'12px'}
color={'myGray.500'}
cursor={'pointer'}
onClick={() =>
openConfirmSync(
onUpdateDatasetWebsiteConfig,
undefined,
t('core.dataset.website.Confirm Create Tips')
)()
}
/>
</MyTooltip>
)}
</Flex>
)}
</Box>
<SideTabs
px={4}
flex={1}
mx={'auto'}
mt={3}
w={'100%'}
list={tabList}
activeId={currentTab}
@@ -201,7 +197,7 @@ const Detail = ({ datasetId, currentTab }: { datasetId: string; currentTab: `${T
setCurrentTab(e);
}}
/>
<Box>
<Box px={4}>
<Box mb={3}>
<Box fontSize={'sm'}>
{t('core.dataset.training.Agent queue')}({agentTrainingMap.tip})
@@ -229,6 +225,7 @@ const Detail = ({ datasetId, currentTab }: { datasetId: string; currentTab: `${T
/>
</Box>
</Box>
<Flex
alignItems={'center'}
cursor={'pointer'}

View File

@@ -19,6 +19,7 @@ import { useTranslation } from 'next-i18next';
import MyRadio from '@/components/common/MyRadio';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constant';
import { feConfigs } from '@/web/common/system/staticData';
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: string }) => {
const { t } = useTranslation();
@@ -49,6 +50,7 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
if (!file) return;
try {
const src = await compressImgFileAndUpload({
type: MongoImageTypeEnum.datasetAvatar,
file,
maxW: 300,
maxH: 300
@@ -62,7 +64,7 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
});
}
},
[setValue, toast]
[setValue, t, toast]
);
/* create a new kb and router to it */

View File

@@ -22,7 +22,7 @@ import {
putDatasetById,
postCreateDataset
} from '@/web/core/dataset/api';
import { checkTeamExportDatasetLimit } from '@/web/support/user/api';
import { checkTeamExportDatasetLimit } from '@/web/support/user/team/api';
import { useTranslation } from 'next-i18next';
import Avatar from '@/components/Avatar';
import MyIcon from '@fastgpt/web/components/common/Icon';
@@ -44,6 +44,7 @@ import PermissionIconText from '@/components/support/permission/IconText';
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
import { DatasetItemType } from '@fastgpt/global/core/dataset/type';
import ParentPaths from '@/components/common/ParentPaths';
import DatasetTypeTag from '@/components/core/dataset/DatasetTypeTag';
const CreateModal = dynamic(() => import('./component/CreateModal'), { ssr: false });
const MoveModal = dynamic(() => import('./component/MoveModal'), { ssr: false });
@@ -409,8 +410,9 @@ const Kb = () => {
<Box flex={1}>
<PermissionIconText permission={dataset.permission} color={'myGray.600'} />
</Box>
<MyIcon mr={1} name={dataset.icon as any} w={'12px'} />
<Box color={'myGray.500'}>{t(dataset.label)}</Box>
{dataset.type !== DatasetTypeEnum.folder && (
<DatasetTypeTag type={dataset.type} py={1} px={2} />
)}
</Flex>
</Box>
))}