This commit is contained in:
Archer
2023-10-30 13:26:42 +08:00
committed by GitHub
parent 008d0af010
commit 60ee160131
216 changed files with 4429 additions and 2229 deletions

View File

@@ -77,13 +77,7 @@ const QuoteModal = ({
</>
}
>
<ModalBody
pt={0}
whiteSpace={'pre-wrap'}
textAlign={'justify'}
wordBreak={'break-all'}
fontSize={'sm'}
>
<ModalBody pt={0} whiteSpace={'pre-wrap'} textAlign={'justify'} wordBreak={'break-all'}>
{rawSearch.map((item, i) => (
<Box
key={i}
@@ -95,11 +89,18 @@ const QuoteModal = ({
position={'relative'}
overflow={'hidden'}
_hover={{ '& .hover-data': { display: 'flex' } }}
bg={i % 2 === 0 ? 'white' : 'myWhite.500'}
>
{!isShare && (
<Flex alignItems={'flex-end'} mb={3} color={'myGray.500'}>
<RawSourceText sourceName={item.sourceName} sourceId={item.sourceId} />
<Box flex={1} />
<Flex alignItems={'flex-end'} mb={3} fontSize={'sm'}>
<RawSourceText
fontWeight={'bold'}
color={'black'}
sourceName={item.sourceName}
sourceId={item.sourceId}
addr={!isShare}
/>
<Box flex={1} />
{!isShare && (
<Link
as={NextLink}
className="hover-data"
@@ -111,13 +112,13 @@ const QuoteModal = ({
{t('core.dataset.Go Dataset')}
<MyIcon name={'rightArrowLight'} w={'10px'} />
</Link>
</Flex>
)}
)}
</Flex>
<Box color={'black'}>{item.q}</Box>
<Box color={'black'}>{item.a}</Box>
<Box color={'myGray.600'}>{item.a}</Box>
{!isShare && (
<Flex alignItems={'center'} mt={3} gap={4} color={'myGray.500'}>
<Flex alignItems={'center'} fontSize={'sm'} mt={3} gap={4} color={'myGray.500'}>
{isPc && (
<MyTooltip label={t('core.dataset.data.id')}>
<Flex border={theme.borders.base} px={3} borderRadius={'md'}>

View File

@@ -1,19 +1,22 @@
import React, { useMemo, useState } from 'react';
import { ChatHistoryItemResType, ChatItemType } from '@/types/chat';
import { Flex, BoxProps, useDisclosure } from '@chakra-ui/react';
import { Flex, BoxProps, useDisclosure, Image, useTheme } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
import dynamic from 'next/dynamic';
import Tag from '../Tag';
import MyTooltip from '../MyTooltip';
import { FlowModuleTypeEnum } from '@/constants/flow';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
import ChatBoxDivider from '@/components/core/chat/Divider';
const QuoteModal = dynamic(() => import('./QuoteModal'), { ssr: false });
const ContextModal = dynamic(() => import('./ContextModal'), { ssr: false });
const WholeResponseModal = dynamic(() => import('./WholeResponseModal'), { ssr: false });
const ResponseTags = ({ responseData = [] }: { responseData?: ChatHistoryItemResType[] }) => {
const theme = useTheme();
const { isPc } = useSystemStore();
const { t } = useTranslation();
const [quoteModalData, setQuoteModalData] = useState<SearchDataResponseItemType[]>();
@@ -27,18 +30,36 @@ const ResponseTags = ({ responseData = [] }: { responseData?: ChatHistoryItemRes
const {
chatAccount,
quoteList = [],
sourceList = [],
historyPreview = [],
runningTime = 0
} = useMemo(() => {
const chatData = responseData.find((item) => item.moduleType === FlowModuleTypeEnum.chatNode);
const chatData = responseData.find((item) => item.moduleType === FlowNodeTypeEnum.chatNode);
const quoteList = responseData
.filter((item) => item.moduleType === FlowNodeTypeEnum.chatNode)
.map((item) => item.quoteList)
.flat()
.filter((item) => item) as SearchDataResponseItemType[];
const sourceList = quoteList.reduce(
(acc: Record<string, SearchDataResponseItemType[]>, cur) => {
if (!acc[cur.sourceName]) {
acc[cur.sourceName] = [cur];
}
return acc;
},
{}
);
return {
chatAccount: responseData.filter((item) => item.moduleType === FlowModuleTypeEnum.chatNode)
chatAccount: responseData.filter((item) => item.moduleType === FlowNodeTypeEnum.chatNode)
.length,
quoteList: responseData
.filter((item) => item.moduleType === FlowModuleTypeEnum.chatNode)
.map((item) => item.quoteList)
quoteList,
sourceList: Object.values(sourceList)
.flat()
.filter((item) => item) as SearchDataResponseItemType[],
.map((item) => ({
sourceName: item.sourceName,
icon: getSourceNameIcon({ sourceId: item.sourceId, sourceName: item.sourceName })
})),
historyPreview: chatData?.historyPreview,
runningTime: +responseData.reduce((sum, item) => sum + (item.runningTime || 0), 0).toFixed(2)
};
@@ -50,64 +71,93 @@ const ResponseTags = ({ responseData = [] }: { responseData?: ChatHistoryItemRes
};
return responseData.length === 0 ? null : (
<Flex alignItems={'center'} mt={2} flexWrap={'wrap'}>
{quoteList.length > 0 && (
<MyTooltip label="查看引用">
<Tag
colorSchema="blue"
cursor={'pointer'}
{...TagStyles}
onClick={() => setQuoteModalData(quoteList)}
>
{quoteList.length}
</Tag>
</MyTooltip>
)}
{chatAccount === 1 && (
<>
{sourceList.length > 0 && (
<>
{historyPreview.length > 0 && (
<MyTooltip label={'点击查看完整对话记录'}>
<Tag
colorSchema="green"
<ChatBoxDivider icon="core/chat/quoteFill" text={t('chat.Quote')} />
<Flex alignItems={'center'} flexWrap={'wrap'} gap={2}>
{sourceList.map((item) => (
<Flex
key={item.sourceName}
alignItems={'center'}
flexWrap={'wrap'}
fontSize={'sm'}
cursor={'pointer'}
{...TagStyles}
onClick={() => setContextModalData(historyPreview)}
border={theme.borders.sm}
py={1}
px={2}
borderRadius={'md'}
_hover={{
bg: 'myBlue.100'
}}
onClick={() => setQuoteModalData(quoteList)}
>
{historyPreview.length}
</Tag>
</MyTooltip>
)}
<Image src={item.icon} alt={''} mr={1} w={'12px'} />
{item.sourceName}
</Flex>
))}
</Flex>
</>
)}
{chatAccount > 1 && (
<Tag colorSchema="blue" {...TagStyles}>
AI
</Tag>
)}
<Flex alignItems={'center'} mt={2} flexWrap={'wrap'}>
{quoteList.length > 0 && (
<MyTooltip label="查看引用">
<Tag
colorSchema="blue"
cursor={'pointer'}
{...TagStyles}
onClick={() => setQuoteModalData(quoteList)}
>
{quoteList.length}
</Tag>
</MyTooltip>
)}
{chatAccount === 1 && (
<>
{historyPreview.length > 0 && (
<MyTooltip label={'点击查看完整对话记录'}>
<Tag
colorSchema="green"
cursor={'pointer'}
{...TagStyles}
onClick={() => setContextModalData(historyPreview)}
>
{historyPreview.length}
</Tag>
</MyTooltip>
)}
</>
)}
{chatAccount > 1 && (
<Tag colorSchema="blue" {...TagStyles}>
AI
</Tag>
)}
{isPc && runningTime > 0 && (
<MyTooltip label={'模块运行时间和'}>
<Tag colorSchema="purple" cursor={'default'} {...TagStyles}>
{runningTime}s
{isPc && runningTime > 0 && (
<MyTooltip label={'模块运行时间和'}>
<Tag colorSchema="purple" cursor={'default'} {...TagStyles}>
{runningTime}s
</Tag>
</MyTooltip>
)}
<MyTooltip label={'点击查看完整响应'}>
<Tag colorSchema="gray" cursor={'pointer'} {...TagStyles} onClick={onOpenWholeModal}>
{t('chat.Complete Response')}
</Tag>
</MyTooltip>
)}
<MyTooltip label={'点击查看完整响应'}>
<Tag colorSchema="gray" cursor={'pointer'} {...TagStyles} onClick={onOpenWholeModal}>
{t('chat.Complete Response')}
</Tag>
</MyTooltip>
{!!quoteModalData && (
<QuoteModal rawSearch={quoteModalData} onClose={() => setQuoteModalData(undefined)} />
)}
{!!contextModalData && (
<ContextModal context={contextModalData} onClose={() => setContextModalData(undefined)} />
)}
{isOpenWholeModal && (
<WholeResponseModal response={responseData} onClose={onCloseWholeModal} />
)}
</Flex>
{!!quoteModalData && (
<QuoteModal rawSearch={quoteModalData} onClose={() => setQuoteModalData(undefined)} />
)}
{!!contextModalData && (
<ContextModal context={contextModalData} onClose={() => setContextModalData(undefined)} />
)}
{isOpenWholeModal && (
<WholeResponseModal response={responseData} onClose={onCloseWholeModal} />
)}
</Flex>
</>
);
};

View File

@@ -32,7 +32,7 @@ function Row({ label, value }: { label: string; value?: string | number | React.
) : null;
}
const ResponseModal = ({
const WholeResponseModal = ({
response,
onClose
}: {
@@ -50,6 +50,7 @@ const ResponseModal = ({
<Image
mr={2}
src={
item.moduleLogo ||
ModuleTemplatesFlat.find((template) => item.moduleType === template.flowType)?.logo
}
alt={''}
@@ -192,10 +193,22 @@ const ResponseModal = ({
}
})()}
/>
{/* plugin */}
<Row
label={t('chat.response.plugin output')}
value={(() => {
try {
return JSON.stringify(activeModule?.pluginOutput, null, 2);
} catch (error) {
return '';
}
})()}
/>
</Box>
</Flex>
</MyModal>
);
};
export default ResponseModal;
export default WholeResponseModal;

View File

@@ -35,7 +35,7 @@ import { feConfigs } from '@/web/common/system/staticData';
import { eventBus } from '@/web/common/utils/eventbus';
import { adaptChat2GptMessages } from '@/utils/common/adapt/message';
import { useMarkdown } from '@/web/common/hooks/useMarkdown';
import { AppModuleItemType } from '@/types/app';
import { ModuleItemType } from '@fastgpt/global/core/module/type.d';
import { VariableInputEnum } from '@/constants/app';
import { useForm } from 'react-hook-form';
import type { MessageItemType } from '@/types/core/chat/type';
@@ -54,6 +54,7 @@ import Avatar from '@/components/Avatar';
import Markdown from '@/components/Markdown';
import MySelect from '@/components/Select';
import MyTooltip from '../MyTooltip';
import ChatBoxDivider from '@/components/core/chat/Divider';
import dynamic from 'next/dynamic';
const ResponseTags = dynamic(() => import('./ResponseTags'));
const FeedbackModal = dynamic(() => import('./FeedbackModal'));
@@ -99,7 +100,7 @@ type Props = {
showEmptyIntro?: boolean;
appAvatar?: string;
userAvatar?: string;
userGuideModule?: AppModuleItemType;
userGuideModule?: ModuleItemType;
active?: boolean;
onUpdateVariable?: (e: Record<string, any>) => void;
onStartChat?: (e: StartChatFnProps) => Promise<{
@@ -488,7 +489,7 @@ const ChatBox = (
return {
bg: colorMap[chatContent.status] || colorMap.loading,
name: t(chatContent.moduleName || 'Running')
name: t(chatContent.moduleName || 'common.Loading')
};
}, [chatHistory, isChatting, t]);
/* style end */
@@ -496,6 +497,7 @@ const ChatBox = (
// page change and abort request
useEffect(() => {
isNewChatReplace.current = false;
setQuestionGuide([]);
return () => {
chatController.current?.abort('leave');
if (!isNewChatReplace.current) {
@@ -750,38 +752,28 @@ const ChatBox = (
{index === chatHistory.length - 1 &&
!isChatting &&
questionGuides.length > 0 && (
<Flex
mt={2}
borderTop={theme.borders.sm}
alignItems={'center'}
flexWrap={'wrap'}
>
<Box
color={'myGray.500'}
mt={2}
mr={2}
fontSize={'sm'}
fontStyle={'italic'}
>
{t('chat.Question Guide Tips')}
</Box>
{questionGuides.map((item) => (
<Button
mt={2}
key={item}
mr="2"
borderRadius={'md'}
variant={'outline'}
colorScheme={'gray'}
size={'xs'}
onClick={() => {
resetInputVal(item);
}}
>
{item}
</Button>
))}
</Flex>
<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'}
onClick={() => {
resetInputVal(item);
}}
>
{item}
</Button>
))}
</Flex>
</Box>
)}
{/* admin mark content */}
{showMarkIcon && item.adminFeedback && (