import React, { useState, useCallback } from 'react'; import { Box, Flex, Button, Modal, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, ModalBody, Input, Textarea } from '@chakra-ui/react'; import { useToast } from '@/hooks/useToast'; import { useSelectFile } from '@/hooks/useSelectFile'; import { encode } from 'gpt-token-utils'; import { useConfirm } from '@/hooks/useConfirm'; import { readTxtContent, readPdfContent, readDocContent } from '@/utils/tools'; import { useMutation } from '@tanstack/react-query'; import { postModelDataSplitData } from '@/api/model'; import { formatPrice } from '@/utils/user'; const fileExtension = '.txt,.doc,.docx,.pdf,.md'; const SelectFileModal = ({ onClose, onSuccess, modelId }: { onClose: () => void; onSuccess: () => void; modelId: string; }) => { const [selecting, setSelecting] = useState(false); const { toast } = useToast(); const [prompt, setPrompt] = useState(''); const { File, onOpen } = useSelectFile({ fileType: fileExtension, multiple: true }); const [fileText, setFileText] = useState(''); const { openConfirm, ConfirmChild } = useConfirm({ content: '确认导入该文件,需要一定时间进行拆解,该任务无法终止!如果余额不足,任务讲被终止。' }); const onSelectFile = useCallback( async (e: File[]) => { setSelecting(true); try { const fileTexts = ( await Promise.all( e.map((file) => { // @ts-ignore const extension = file?.name?.split('.').pop().toLowerCase(); switch (extension) { case 'txt': case 'md': return readTxtContent(file); case 'pdf': return readPdfContent(file); case 'doc': case 'docx': return readDocContent(file); default: return ''; } }) ) ) .join(' ') .replace(/(\\n|\n)+/g, '\n'); setFileText(fileTexts); } catch (error: any) { console.log(error); toast({ title: typeof error === 'string' ? error : '解析文件失败', status: 'error' }); } setSelecting(false); }, [setSelecting, toast] ); const { mutate, isLoading } = useMutation({ mutationFn: async () => { if (!fileText) return; await postModelDataSplitData({ modelId, text: fileText, prompt: `下面是${prompt || '一段长文本'}` }); toast({ title: '导入数据成功,需要一段拆解和训练', status: 'success' }); onClose(); onSuccess(); }, onError() { toast({ title: '导入文件失败', status: 'error' }); } }); return ( 文件导入 支持 {fileExtension} 文件。模型会自动对文本进行 QA 拆分,需要较长训练时间,拆分需要消耗 tokens,账号余额不足时,未拆分的数据会被删除。 一共 {encode(fileText).length} 个tokens,大约 {formatPrice(encode(fileText).length * 4)} 元 下面是 setPrompt(e.target.value)} size={'sm'} />