4.6.4-alpha (#582)

This commit is contained in:
Archer
2023-12-08 15:01:11 +08:00
committed by GitHub
parent 54d52d8d25
commit b58249fc3a
66 changed files with 962 additions and 527 deletions

View File

@@ -69,78 +69,85 @@ const MessageInput = ({
maxCount: 10
});
const uploadFile = async (file: FileItemType) => {
if (file.type === FileTypeEnum.image) {
try {
const src = await compressImgFileAndUpload({
file: file.rawFile,
maxW: 4329,
maxH: 4329,
maxSize: 1024 * 1024 * 5,
// 30 day expired.
expiredTime: addDays(new Date(), 30)
});
setFileList((state) =>
state.map((item) =>
item.id === file.id
? {
...item,
src: `${location.origin}${src}`
}
: item
)
);
} catch (error) {
setFileList((state) => state.filter((item) => item.id !== file.id));
console.log(error);
const uploadFile = useCallback(
async (file: FileItemType) => {
if (file.type === FileTypeEnum.image) {
try {
const src = await compressImgFileAndUpload({
file: file.rawFile,
maxW: 4329,
maxH: 4329,
maxSize: 1024 * 1024 * 5,
// 30 day expired.
expiredTime: addDays(new Date(), 30),
shareId
});
setFileList((state) =>
state.map((item) =>
item.id === file.id
? {
...item,
src: `${location.origin}${src}`
}
: item
)
);
} catch (error) {
setFileList((state) => state.filter((item) => item.id !== file.id));
console.log(error);
toast({
status: 'error',
title: t('common.Upload File Failed')
});
toast({
status: 'error',
title: t('common.Upload File Failed')
});
}
}
}
};
const onSelectFile = useCallback(async (files: File[]) => {
if (!files || files.length === 0) {
return;
}
const loadFiles = await Promise.all(
files.map(
(file) =>
new Promise<FileItemType>((resolve, reject) => {
if (file.type.includes('image')) {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const item = {
},
[shareId, t, toast]
);
const onSelectFile = useCallback(
async (files: File[]) => {
if (!files || files.length === 0) {
return;
}
const loadFiles = await Promise.all(
files.map(
(file) =>
new Promise<FileItemType>((resolve, reject) => {
if (file.type.includes('image')) {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const item = {
id: nanoid(),
rawFile: file,
type: FileTypeEnum.image,
name: file.name,
icon: reader.result as string
};
uploadFile(item);
resolve(item);
};
reader.onerror = () => {
reject(reader.error);
};
} else {
resolve({
id: nanoid(),
rawFile: file,
type: FileTypeEnum.image,
type: FileTypeEnum.file,
name: file.name,
icon: reader.result as string
};
uploadFile(item);
resolve(item);
};
reader.onerror = () => {
reject(reader.error);
};
} else {
resolve({
id: nanoid(),
rawFile: file,
type: FileTypeEnum.file,
name: file.name,
icon: 'pdf'
});
}
})
)
);
icon: 'pdf'
});
}
})
)
);
setFileList((state) => [...state, ...loadFiles]);
}, []);
setFileList((state) => [...state, ...loadFiles]);
},
[uploadFile]
);
const handleSend = useCallback(async () => {
const textareaValue = TextareaDom.current?.value || '';

View File

@@ -12,12 +12,21 @@ import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
import Markdown from '../Markdown';
import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constant';
function Row({ label, value }: { label: string; value?: string | number }) {
function Row({
label,
value,
rawDom
}: {
label: string;
value?: string | number;
rawDom?: React.ReactNode;
}) {
const theme = useTheme();
const val = value || rawDom;
const strValue = `${value}`;
const isCodeBlock = strValue.startsWith('~~~json');
return value !== undefined && value !== '' && value !== 'undefined' ? (
return val !== undefined && val !== '' && val !== 'undefined' ? (
<Box mb={3}>
<Box fontSize={['sm', 'md']} mb={isCodeBlock ? 0 : 1} flex={'0 0 90px'}>
{label}:
@@ -29,7 +38,8 @@ function Row({ label, value }: { label: string; value?: string | number }) {
? { transform: 'translateY(-3px)' }
: { px: 3, py: 1, border: theme.borders.base })}
>
<Markdown source={strValue} />
{value && <Markdown source={strValue} />}
{rawDom}
</Box>
</Box>
) : null;
@@ -113,12 +123,28 @@ const WholeResponseModal = ({
<Row label={t('chat.response.module maxToken')} value={activeModule?.maxToken} />
<Row
label={t('chat.response.module historyPreview')}
value={(() => {
if (!activeModule?.historyPreview) return '';
return activeModule.historyPreview
.map((item, i) => `**${item.obj}**\n${item.value}`)
.join('\n\n---\n\n');
})()}
rawDom={
activeModule.historyPreview ? (
<>
{activeModule.historyPreview?.map((item, i) => (
<Box
key={i}
_notLast={{
borderBottom: '1px solid',
borderBottomColor: 'myWhite.700',
mb: 2
}}
pb={2}
>
<Box fontWeight={'bold'}>{item.obj}</Box>
<Box whiteSpace={'pre-wrap'}>{item.value}</Box>
</Box>
))}
</>
) : (
''
)
}
/>
{activeModule.quoteList && activeModule.quoteList.length > 0 && (
<Row

View File

@@ -30,7 +30,7 @@ import {
Textarea
} from '@chakra-ui/react';
import { feConfigs } from '@/web/common/system/staticData';
import { eventBus } from '@/web/common/utils/eventbus';
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
import { adaptChat2GptMessages } from '@fastgpt/global/core/chat/adapt';
import { useMarkdown } from '@/web/common/hooks/useMarkdown';
import { ModuleItemType } from '@fastgpt/global/core/module/type.d';
@@ -48,7 +48,7 @@ import type { AdminMarkType } from './SelectMarkCollection';
import MyIcon from '@/components/Icon';
import Avatar from '@/components/Avatar';
import Markdown from '@/components/Markdown';
import Markdown, { CodeClassName } from '@/components/Markdown';
import MySelect from '@/components/Select';
import MyTooltip from '../MyTooltip';
import ChatBoxDivider from '@/components/core/chat/Divider';
@@ -64,6 +64,7 @@ import { splitGuideModule } from '@fastgpt/global/core/module/utils';
import type { AppTTSConfigType } from '@fastgpt/global/core/module/type.d';
import MessageInput from './MessageInput';
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
@@ -132,6 +133,7 @@ const ChatBox = (
const ChatBoxRef = useRef<HTMLDivElement>(null);
const theme = useTheme();
const router = useRouter();
const { shareId } = router.query as { shareId?: string };
const { t } = useTranslation();
const { toast } = useToast();
const { isPc, setLoading } = useSystemStore();
@@ -258,7 +260,7 @@ const ChatBox = (
const result = await postQuestionGuide(
{
messages: adaptChat2GptMessages({ messages: history, reserveId: false }).slice(-6),
shareId: router.query.shareId as string
shareId
},
abortSignal
);
@@ -270,7 +272,7 @@ const ChatBox = (
}
} catch (error) {}
},
[questionGuide, scrollToBottom, router.query.shareId]
[questionGuide, scrollToBottom, shareId]
);
/**
@@ -323,7 +325,6 @@ const ChatBox = (
setTimeout(() => {
scrollToBottom();
}, 100);
try {
// create abort obj
const abortSignal = new AbortController();
@@ -518,16 +519,22 @@ const ChatBox = (
}
};
window.addEventListener('message', windowMessage);
eventBus.on('guideClick', ({ text }: { text: string }) => {
eventBus.on(EventNameEnum.sendQuestion, ({ text }: { text: string }) => {
if (!text) return;
handleSubmit((data) => sendPrompt(data, text))();
});
eventBus.on(EventNameEnum.editQuestion, ({ text }: { text: string }) => {
if (!text) return;
resetInputVal(text);
});
return () => {
eventBus.off('guideClick');
eventBus.off(EventNameEnum.sendQuestion);
eventBus.off(EventNameEnum.editQuestion);
window.removeEventListener('message', windowMessage);
};
}, [handleSubmit, sendPrompt]);
}, [handleSubmit, resetInputVal, sendPrompt]);
return (
<Flex flexDirection={'column'} h={'100%'}>
@@ -757,40 +764,30 @@ const ChatBox = (
<Box textAlign={'left'} mt={['6px', 2]}>
<Card bg={'white'} {...MessageCardStyle}>
<Markdown
source={item.value}
source={(() => {
const text = item.value as string;
// replace quote tag: [source1] 标识第一个来源需要提取数字1从而去数组里查找来源
const quoteReg = /\[source:(.+)\]/g;
const replaceText = text.replace(quoteReg, `[QUOTE SIGN]($1)`);
// question guide
if (
index === chatHistory.length - 1 &&
!isChatting &&
questionGuides.length > 0
) {
return `${replaceText}\n\`\`\`${
CodeClassName.questionGuide
}\n${JSON.stringify(questionGuides)}`;
}
return replaceText;
})()}
isChatting={index === chatHistory.length - 1 && isChatting}
/>
<ResponseTags responseData={item.responseData} />
{/* question guide */}
{index === chatHistory.length - 1 &&
!isChatting &&
questionGuides.length > 0 && (
<Box mt={2}>
<ChatBoxDivider
icon="core/chat/QGFill"
text={t('chat.Question Guide Tips')}
/>
<Flex alignItems={'center'} flexWrap={'wrap'} gap={2}>
{questionGuides.map((item) => (
<Button
key={item}
borderRadius={'md'}
variant={'outline'}
colorScheme={'gray'}
size={'xs'}
whiteSpace={'pre-wrap'}
h={'auto'}
py={1}
onClick={() => {
resetInputVal(item);
}}
>
{item}
</Button>
))}
</Flex>
</Box>
)}
{/* admin mark content */}
{showMarkIcon && item.adminFeedback && (
<Box>