mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-30 18:48:55 +00:00
4.6.5- CoreferenceResolution Module (#631)
This commit is contained in:
@@ -26,6 +26,43 @@ const QuoteModal = ({
|
||||
isShare: boolean;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<MyModal
|
||||
isOpen={true}
|
||||
onClose={onClose}
|
||||
h={['90vh', '80vh']}
|
||||
isCentered
|
||||
minW={['90vw', '600px']}
|
||||
iconSrc="/imgs/modal/quote.svg"
|
||||
title={
|
||||
<Box>
|
||||
{t('core.chat.Quote Amount', { amount: rawSearch.length })}
|
||||
<Box fontSize={'sm'} color={'myGray.500'} fontWeight={'normal'}>
|
||||
{t('core.chat.quote.Quote Tip')}
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<ModalBody whiteSpace={'pre-wrap'} textAlign={'justify'} wordBreak={'break-all'}>
|
||||
<QuoteList rawSearch={rawSearch} isShare={isShare} />
|
||||
</ModalBody>
|
||||
</MyModal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default QuoteModal;
|
||||
|
||||
export const QuoteList = React.memo(function QuoteList({
|
||||
rawSearch = [],
|
||||
isShare
|
||||
}: {
|
||||
rawSearch: SearchDataResponseItemType[];
|
||||
isShare: boolean;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { isPc } = useSystemStore();
|
||||
const theme = useTheme();
|
||||
const { toast } = useToast();
|
||||
@@ -60,124 +97,104 @@ const QuoteModal = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<MyModal
|
||||
isOpen={true}
|
||||
onClose={onClose}
|
||||
h={['90vh', '80vh']}
|
||||
isCentered
|
||||
minW={['90vw', '600px']}
|
||||
iconSrc="/imgs/modal/quote.svg"
|
||||
title={
|
||||
<Box>
|
||||
{t('core.chat.Quote Amount', { amount: rawSearch.length })}
|
||||
<Box fontSize={'sm'} color={'myGray.500'} fontWeight={'normal'}>
|
||||
{t('core.chat.quote.Quote Tip')}
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<ModalBody whiteSpace={'pre-wrap'} textAlign={'justify'} wordBreak={'break-all'}>
|
||||
{rawSearch.map((item, i) => (
|
||||
<Box
|
||||
key={i}
|
||||
flex={'1 0 0'}
|
||||
p={2}
|
||||
borderRadius={'lg'}
|
||||
border={theme.borders.base}
|
||||
_notLast={{ mb: 2 }}
|
||||
position={'relative'}
|
||||
overflow={'hidden'}
|
||||
_hover={{ '& .hover-data': { display: 'flex' } }}
|
||||
bg={i % 2 === 0 ? 'white' : 'myWhite.500'}
|
||||
>
|
||||
<Flex alignItems={'flex-end'} mb={3} fontSize={'sm'}>
|
||||
<RawSourceText
|
||||
fontWeight={'bold'}
|
||||
color={'black'}
|
||||
sourceName={item.sourceName}
|
||||
sourceId={item.sourceId}
|
||||
canView={!isShare}
|
||||
/>
|
||||
<Box flex={1} />
|
||||
{!isShare && (
|
||||
<Link
|
||||
as={NextLink}
|
||||
className="hover-data"
|
||||
display={'none'}
|
||||
alignItems={'center'}
|
||||
color={'blue.500'}
|
||||
href={`/dataset/detail?datasetId=${item.datasetId}¤tTab=dataCard&collectionId=${item.collectionId}`}
|
||||
>
|
||||
{t('core.dataset.Go Dataset')}
|
||||
<MyIcon name={'common/rightArrowLight'} w={'10px'} />
|
||||
</Link>
|
||||
)}
|
||||
</Flex>
|
||||
{rawSearch.map((item, i) => (
|
||||
<Box
|
||||
key={i}
|
||||
flex={'1 0 0'}
|
||||
p={2}
|
||||
borderRadius={'lg'}
|
||||
border={theme.borders.base}
|
||||
_notLast={{ mb: 2 }}
|
||||
position={'relative'}
|
||||
overflow={'hidden'}
|
||||
_hover={{ '& .hover-data': { display: 'flex' } }}
|
||||
bg={i % 2 === 0 ? 'white' : 'myWhite.500'}
|
||||
>
|
||||
<Flex alignItems={'flex-end'} mb={3} fontSize={'sm'}>
|
||||
<RawSourceText
|
||||
fontWeight={'bold'}
|
||||
color={'black'}
|
||||
sourceName={item.sourceName}
|
||||
sourceId={item.sourceId}
|
||||
canView={!isShare}
|
||||
/>
|
||||
<Box flex={1} />
|
||||
{!isShare && (
|
||||
<Link
|
||||
as={NextLink}
|
||||
className="hover-data"
|
||||
display={'none'}
|
||||
alignItems={'center'}
|
||||
color={'blue.500'}
|
||||
href={`/dataset/detail?datasetId=${item.datasetId}¤tTab=dataCard&collectionId=${item.collectionId}`}
|
||||
>
|
||||
{t('core.dataset.Go Dataset')}
|
||||
<MyIcon name={'common/rightArrowLight'} w={'10px'} />
|
||||
</Link>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
<Box color={'black'}>{item.q}</Box>
|
||||
<Box color={'myGray.600'}>{item.a}</Box>
|
||||
{!isShare && (
|
||||
<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} py={'1px'} px={3} borderRadius={'3px'}>
|
||||
# {item.id}
|
||||
</Flex>
|
||||
</MyTooltip>
|
||||
)}
|
||||
<MyTooltip label={t('core.dataset.Quote Length')}>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name="common/text/t" w={'14px'} mr={1} color={'myGray.500'} />
|
||||
{item.q.length + (item.a?.length || 0)}
|
||||
</Flex>
|
||||
</MyTooltip>
|
||||
{!isShare && item.score && (
|
||||
<MyTooltip label={t('core.dataset.Similarity')}>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'kbTest'} w={'12px'} />
|
||||
<Progress
|
||||
mx={2}
|
||||
w={['60px', '90px']}
|
||||
value={item.score * 100}
|
||||
size="sm"
|
||||
borderRadius={'20px'}
|
||||
colorScheme="myGray"
|
||||
border={theme.borders.base}
|
||||
/>
|
||||
<Box>{item.score.toFixed(4)}</Box>
|
||||
</Flex>
|
||||
</MyTooltip>
|
||||
)}
|
||||
<Box flex={1} />
|
||||
{item.id && (
|
||||
<MyTooltip label={t('core.dataset.data.Edit')}>
|
||||
<Box
|
||||
bg={'rgba(255,255,255,0.9)'}
|
||||
alignItems={'center'}
|
||||
justifyContent={'center'}
|
||||
boxShadow={'-10px 0 10px rgba(255,255,255,1)'}
|
||||
>
|
||||
<MyIcon
|
||||
name={'edit'}
|
||||
w={['16px', '18px']}
|
||||
h={['16px', '18px']}
|
||||
cursor={'pointer'}
|
||||
color={'myGray.600'}
|
||||
_hover={{
|
||||
color: 'blue.600'
|
||||
}}
|
||||
onClick={() => onclickEdit(item)}
|
||||
/>
|
||||
</Box>
|
||||
</MyTooltip>
|
||||
)}
|
||||
</Flex>
|
||||
<Box color={'black'}>{item.q}</Box>
|
||||
<Box color={'myGray.600'}>{item.a}</Box>
|
||||
{!isShare && (
|
||||
<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} py={'1px'} px={3} borderRadius={'3px'}>
|
||||
# {item.id}
|
||||
</Flex>
|
||||
</MyTooltip>
|
||||
)}
|
||||
</Box>
|
||||
))}
|
||||
</ModalBody>
|
||||
<Loading fixed={false} />
|
||||
</MyModal>
|
||||
<MyTooltip label={t('core.dataset.Quote Length')}>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name="common/text/t" w={'14px'} mr={1} color={'myGray.500'} />
|
||||
{item.q.length + (item.a?.length || 0)}
|
||||
</Flex>
|
||||
</MyTooltip>
|
||||
{!isShare && item.score && (
|
||||
<MyTooltip label={t('core.dataset.Similarity')}>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'kbTest'} w={'12px'} />
|
||||
<Progress
|
||||
mx={2}
|
||||
w={['60px', '90px']}
|
||||
value={item.score * 100}
|
||||
size="sm"
|
||||
borderRadius={'20px'}
|
||||
colorScheme="myGray"
|
||||
border={theme.borders.base}
|
||||
/>
|
||||
<Box>{item.score.toFixed(4)}</Box>
|
||||
</Flex>
|
||||
</MyTooltip>
|
||||
)}
|
||||
<Box flex={1} />
|
||||
{item.id && (
|
||||
<MyTooltip label={t('core.dataset.data.Edit')}>
|
||||
<Box
|
||||
bg={'rgba(255,255,255,0.9)'}
|
||||
alignItems={'center'}
|
||||
justifyContent={'center'}
|
||||
boxShadow={'-10px 0 10px rgba(255,255,255,1)'}
|
||||
>
|
||||
<MyIcon
|
||||
name={'edit'}
|
||||
w={['16px', '18px']}
|
||||
h={['16px', '18px']}
|
||||
cursor={'pointer'}
|
||||
color={'myGray.600'}
|
||||
_hover={{
|
||||
color: 'blue.600'
|
||||
}}
|
||||
onClick={() => onclickEdit(item)}
|
||||
/>
|
||||
</Box>
|
||||
</MyTooltip>
|
||||
)}
|
||||
</Flex>
|
||||
)}
|
||||
</Box>
|
||||
))}
|
||||
{editInputData && editInputData.id && (
|
||||
<InputDataModal
|
||||
onClose={() => setEditInputData(undefined)}
|
||||
@@ -191,8 +208,7 @@ const QuoteModal = ({
|
||||
collectionId={editInputData.collectionId}
|
||||
/>
|
||||
)}
|
||||
<Loading fixed={false} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default QuoteModal;
|
||||
});
|
||||
|
@@ -222,7 +222,11 @@ const ResponseTags = ({
|
||||
<ContextModal context={contextModalData} onClose={() => setContextModalData(undefined)} />
|
||||
)}
|
||||
{isOpenWholeModal && (
|
||||
<WholeResponseModal response={responseData} onClose={onCloseWholeModal} />
|
||||
<WholeResponseModal
|
||||
response={responseData}
|
||||
isShare={isShare}
|
||||
onClose={onCloseWholeModal}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
</>
|
||||
|
@@ -3,13 +3,14 @@ import { Box, useTheme, Flex, Image } from '@chakra-ui/react';
|
||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { moduleTemplatesFlat } from '@/web/core/modules/template/system';
|
||||
import Tabs from '../Tabs';
|
||||
|
||||
import Tabs from '../Tabs';
|
||||
import MyModal from '../MyModal';
|
||||
import MyTooltip from '../MyTooltip';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import Markdown from '../Markdown';
|
||||
import { QuoteList } from './QuoteModal';
|
||||
import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constant';
|
||||
|
||||
function Row({
|
||||
@@ -37,7 +38,9 @@ function Row({
|
||||
fontSize={'sm'}
|
||||
{...(isCodeBlock
|
||||
? { transform: 'translateY(-3px)' }
|
||||
: { px: 3, py: 1, border: theme.borders.base })}
|
||||
: value
|
||||
? { px: 3, py: 1, border: theme.borders.base }
|
||||
: {})}
|
||||
>
|
||||
{value && <Markdown source={strValue} />}
|
||||
{rawDom}
|
||||
@@ -48,13 +51,51 @@ function Row({
|
||||
|
||||
const WholeResponseModal = ({
|
||||
response,
|
||||
isShare,
|
||||
onClose
|
||||
}: {
|
||||
response: ChatHistoryItemResType[];
|
||||
isShare: boolean;
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
isCentered
|
||||
isOpen={true}
|
||||
onClose={onClose}
|
||||
h={['90vh', '80vh']}
|
||||
minW={['90vw', '600px']}
|
||||
iconSrc="/imgs/modal/wholeRecord.svg"
|
||||
title={
|
||||
<Flex alignItems={'center'}>
|
||||
{t('chat.Complete Response')}
|
||||
<MyTooltip label={'从左往右,为各个模块的响应顺序'}>
|
||||
<QuestionOutlineIcon ml={2} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
}
|
||||
>
|
||||
<Flex h={'100%'} flexDirection={'column'}>
|
||||
<ResponseBox response={response} isShare={isShare} />
|
||||
</Flex>
|
||||
</MyModal>
|
||||
);
|
||||
};
|
||||
|
||||
export default WholeResponseModal;
|
||||
|
||||
const ResponseBox = React.memo(function ResponseBox({
|
||||
response,
|
||||
isShare
|
||||
}: {
|
||||
response: ChatHistoryItemResType[];
|
||||
isShare: boolean;
|
||||
}) {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const list = useMemo(
|
||||
() =>
|
||||
response.map((item, i) => ({
|
||||
@@ -83,145 +124,129 @@ const WholeResponseModal = ({
|
||||
const activeModule = useMemo(() => response[Number(currentTab)], [currentTab, response]);
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
isCentered
|
||||
isOpen={true}
|
||||
onClose={onClose}
|
||||
h={['90vh', '80vh']}
|
||||
w={['90vw', '500px']}
|
||||
iconSrc="/imgs/modal/wholeRecord.svg"
|
||||
title={
|
||||
<Flex alignItems={'center'}>
|
||||
{t('chat.Complete Response')}
|
||||
<MyTooltip label={'从左往右,为各个模块的响应顺序'}>
|
||||
<QuestionOutlineIcon ml={2} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
}
|
||||
>
|
||||
<Flex h={'100%'} flexDirection={'column'}>
|
||||
<Box>
|
||||
<Tabs list={list} activeId={currentTab} onChange={setCurrentTab} />
|
||||
</Box>
|
||||
<Box py={2} px={4} flex={'1 0 0'} overflow={'auto'}>
|
||||
<Row label={t('core.chat.response.module name')} value={t(activeModule.moduleName)} />
|
||||
{activeModule?.price !== undefined && (
|
||||
<Row
|
||||
label={t('core.chat.response.module price')}
|
||||
value={`¥${formatPrice(activeModule?.price)}`}
|
||||
/>
|
||||
)}
|
||||
<>
|
||||
<Box>
|
||||
<Tabs list={list} activeId={currentTab} onChange={setCurrentTab} />
|
||||
</Box>
|
||||
<Box py={2} px={4} flex={'1 0 0'} overflow={'auto'}>
|
||||
<Row label={t('core.chat.response.module name')} value={t(activeModule.moduleName)} />
|
||||
{activeModule?.price !== undefined && (
|
||||
<Row
|
||||
label={t('core.chat.response.module time')}
|
||||
value={`${activeModule?.runningTime || 0}s`}
|
||||
label={t('core.chat.response.module price')}
|
||||
value={`¥${formatPrice(activeModule?.price)}`}
|
||||
/>
|
||||
<Row label={t('core.chat.response.module tokens')} value={`${activeModule?.tokens}`} />
|
||||
<Row label={t('core.chat.response.module model')} value={activeModule?.model} />
|
||||
<Row label={t('core.chat.response.module query')} value={activeModule?.query} />
|
||||
)}
|
||||
<Row
|
||||
label={t('core.chat.response.module time')}
|
||||
value={`${activeModule?.runningTime || 0}s`}
|
||||
/>
|
||||
<Row label={t('core.chat.response.module tokens')} value={`${activeModule?.tokens}`} />
|
||||
<Row label={t('core.chat.response.module model')} value={activeModule?.model} />
|
||||
<Row label={t('core.chat.response.module query')} value={activeModule?.query} />
|
||||
<Row
|
||||
label={t('core.chat.response.context total length')}
|
||||
value={activeModule?.contextTotalLen}
|
||||
/>
|
||||
|
||||
{/* ai chat */}
|
||||
<Row label={t('core.chat.response.module temperature')} value={activeModule?.temperature} />
|
||||
<Row label={t('core.chat.response.module maxToken')} value={activeModule?.maxToken} />
|
||||
<Row
|
||||
label={t('core.chat.response.module historyPreview')}
|
||||
rawDom={
|
||||
activeModule.historyPreview ? (
|
||||
<Box px={3} py={2} border={theme.borders.base} borderRadius={'md'}>
|
||||
{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>
|
||||
))}
|
||||
</Box>
|
||||
) : (
|
||||
''
|
||||
)
|
||||
}
|
||||
/>
|
||||
{activeModule.quoteList && activeModule.quoteList.length > 0 && (
|
||||
<Row
|
||||
label={t('core.chat.response.context total length')}
|
||||
value={activeModule?.contextTotalLen}
|
||||
label={t('core.chat.response.module quoteList')}
|
||||
rawDom={<QuoteList isShare={isShare} rawSearch={activeModule.quoteList} />}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* ai chat */}
|
||||
{/* dataset search */}
|
||||
{activeModule?.searchMode && (
|
||||
<Row
|
||||
label={t('core.chat.response.module temperature')}
|
||||
value={activeModule?.temperature}
|
||||
label={t('core.dataset.search.search mode')}
|
||||
// @ts-ignore
|
||||
value={t(DatasetSearchModeMap[activeModule.searchMode]?.title)}
|
||||
/>
|
||||
<Row label={t('core.chat.response.module maxToken')} value={activeModule?.maxToken} />
|
||||
)}
|
||||
<Row label={t('core.chat.response.module similarity')} value={activeModule?.similarity} />
|
||||
<Row label={t('core.chat.response.module limit')} value={activeModule?.limit} />
|
||||
|
||||
{/* classify question */}
|
||||
<Row
|
||||
label={t('core.chat.response.module cq')}
|
||||
value={(() => {
|
||||
if (!activeModule?.cqList) return '';
|
||||
return activeModule.cqList.map((item) => `* ${item.value}`).join('\n');
|
||||
})()}
|
||||
/>
|
||||
<Row label={t('core.chat.response.module cq result')} value={activeModule?.cqResult} />
|
||||
|
||||
{/* extract */}
|
||||
<Row
|
||||
label={t('core.chat.response.module extract description')}
|
||||
value={activeModule?.extractDescription}
|
||||
/>
|
||||
{activeModule?.extractResult && (
|
||||
<Row
|
||||
label={t('core.chat.response.module historyPreview')}
|
||||
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>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
''
|
||||
)
|
||||
}
|
||||
label={t('core.chat.response.module extract result')}
|
||||
value={`~~~json\n${JSON.stringify(activeModule?.extractResult, null, 2)}`}
|
||||
/>
|
||||
{activeModule.quoteList && activeModule.quoteList.length > 0 && (
|
||||
<Row
|
||||
label={t('core.chat.response.module quoteList')}
|
||||
value={`~~~json\n${JSON.stringify(activeModule.quoteList, null, 2)}`}
|
||||
/>
|
||||
)}
|
||||
)}
|
||||
|
||||
{/* dataset search */}
|
||||
{activeModule?.searchMode && (
|
||||
<Row
|
||||
label={t('core.dataset.search.search mode')}
|
||||
// @ts-ignore
|
||||
value={t(DatasetSearchModeMap[activeModule.searchMode]?.title)}
|
||||
/>
|
||||
)}
|
||||
<Row label={t('core.chat.response.module similarity')} value={activeModule?.similarity} />
|
||||
<Row label={t('core.chat.response.module limit')} value={activeModule?.limit} />
|
||||
|
||||
{/* classify question */}
|
||||
{/* http */}
|
||||
{activeModule?.body && (
|
||||
<Row
|
||||
label={t('core.chat.response.module cq')}
|
||||
value={(() => {
|
||||
if (!activeModule?.cqList) return '';
|
||||
return activeModule.cqList.map((item) => `* ${item.value}`).join('\n');
|
||||
})()}
|
||||
label={t('core.chat.response.module http body')}
|
||||
value={`~~~json\n${JSON.stringify(activeModule?.body, null, 2)}`}
|
||||
/>
|
||||
<Row label={t('core.chat.response.module cq result')} value={activeModule?.cqResult} />
|
||||
|
||||
{/* extract */}
|
||||
)}
|
||||
{activeModule?.httpResult && (
|
||||
<Row
|
||||
label={t('core.chat.response.module extract description')}
|
||||
value={activeModule?.extractDescription}
|
||||
label={t('core.chat.response.module http result')}
|
||||
value={`~~~json\n${JSON.stringify(activeModule?.httpResult, null, 2)}`}
|
||||
/>
|
||||
{activeModule?.extractResult && (
|
||||
<Row
|
||||
label={t('core.chat.response.module extract result')}
|
||||
value={`~~~json\n${JSON.stringify(activeModule?.extractResult, null, 2)}`}
|
||||
/>
|
||||
)}
|
||||
)}
|
||||
|
||||
{/* http */}
|
||||
{activeModule?.body && (
|
||||
<Row
|
||||
label={t('core.chat.response.module http body')}
|
||||
value={`~~~json\n${JSON.stringify(activeModule?.body, null, 2)}`}
|
||||
/>
|
||||
)}
|
||||
{activeModule?.httpResult && (
|
||||
<Row
|
||||
label={t('core.chat.response.module http result')}
|
||||
value={`~~~json\n${JSON.stringify(activeModule?.httpResult, null, 2)}`}
|
||||
/>
|
||||
)}
|
||||
{/* plugin */}
|
||||
{activeModule?.pluginDetail && activeModule?.pluginDetail.length > 0 && (
|
||||
<Row
|
||||
label={t('core.chat.response.Plugin Resonse Detail')}
|
||||
rawDom={<ResponseBox response={activeModule.pluginDetail} isShare={isShare} />}
|
||||
/>
|
||||
)}
|
||||
{activeModule?.pluginOutput && (
|
||||
<Row
|
||||
label={t('core.chat.response.plugin output')}
|
||||
value={`~~~json\n${JSON.stringify(activeModule?.pluginOutput, null, 2)}`}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* plugin */}
|
||||
{activeModule?.pluginOutput && (
|
||||
<Row
|
||||
label={t('core.chat.response.plugin output')}
|
||||
value={`~~~json\n${JSON.stringify(activeModule?.pluginOutput, null, 2)}`}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* text editor */}
|
||||
<Row label={t('core.chat.response.text output')} value={activeModule?.textOutput} />
|
||||
</Box>
|
||||
</Flex>
|
||||
</MyModal>
|
||||
{/* text output */}
|
||||
<Row label={t('core.chat.response.text output')} value={activeModule?.textOutput} />
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WholeResponseModal;
|
||||
});
|
||||
|
@@ -349,7 +349,13 @@ const ChatBox = (
|
||||
responseText,
|
||||
isNewChat = false
|
||||
} = await onStartChat({
|
||||
chatList: newChatList,
|
||||
chatList: newChatList.map((item) => ({
|
||||
dataId: item.dataId,
|
||||
obj: item.obj,
|
||||
value: item.value,
|
||||
status: item.status,
|
||||
moduleName: item.moduleName
|
||||
})),
|
||||
messages,
|
||||
controller: abortSignal,
|
||||
generatingMessage,
|
||||
@@ -386,7 +392,7 @@ const ChatBox = (
|
||||
}, 100);
|
||||
} catch (err: any) {
|
||||
toast({
|
||||
title: getErrText(err, '聊天出错了~'),
|
||||
title: t(getErrText(err, 'core.chat.error.Chat error')),
|
||||
status: 'error',
|
||||
duration: 5000,
|
||||
isClosable: true
|
||||
@@ -419,7 +425,8 @@ const ChatBox = (
|
||||
generatingMessage,
|
||||
createQuestionGuide,
|
||||
generatingScroll,
|
||||
isPc
|
||||
isPc,
|
||||
t
|
||||
]
|
||||
);
|
||||
|
||||
|
@@ -39,7 +39,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
||||
const router = useRouter();
|
||||
const { colorMode, setColorMode } = useColorMode();
|
||||
const { Loading } = useLoading();
|
||||
const { loading, setScreenWidth, isPc, loadGitStar } = useSystemStore();
|
||||
const { loading, setScreenWidth, isPc } = useSystemStore();
|
||||
const { userInfo } = useUserStore();
|
||||
|
||||
const isChatPage = useMemo(
|
||||
@@ -61,12 +61,11 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
||||
window.addEventListener('resize', resize);
|
||||
|
||||
resize();
|
||||
loadGitStar();
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', resize);
|
||||
};
|
||||
}, [loadGitStar, setScreenWidth]);
|
||||
}, [setScreenWidth]);
|
||||
|
||||
const { data: unread = 0 } = useQuery(['getUnreadCount'], getUnreadCount, {
|
||||
enabled: !!userInfo && !!feConfigs.isPlus,
|
||||
|
@@ -346,7 +346,7 @@
|
||||
width: 100%;
|
||||
|
||||
* {
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
pre {
|
||||
|
@@ -19,49 +19,51 @@ type Props = TextareaProps & {
|
||||
// variables: string[];
|
||||
};
|
||||
|
||||
const PromptTextarea = (props: Props) => {
|
||||
const ModalTextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const TextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const PromptTextarea = React.forwardRef<HTMLTextAreaElement, Props>(
|
||||
function PromptTextarea(props, ref) {
|
||||
const ModalTextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const TextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { title = t('core.app.edit.Prompt Editor'), value, ...childProps } = props;
|
||||
const { t } = useTranslation();
|
||||
const { title = t('core.app.edit.Prompt Editor'), ...childProps } = props;
|
||||
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Editor textareaRef={TextareaRef} {...childProps} onOpenModal={onOpen} />
|
||||
{isOpen && (
|
||||
<MyModal iconSrc="/imgs/modal/edit.svg" title={title} isOpen onClose={onClose}>
|
||||
<ModalBody>
|
||||
<Editor
|
||||
textareaRef={ModalTextareaRef}
|
||||
{...childProps}
|
||||
minH={'300px'}
|
||||
maxH={'auto'}
|
||||
minW={['100%', '512px']}
|
||||
/>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (ModalTextareaRef.current && TextareaRef.current) {
|
||||
TextareaRef.current.value = ModalTextareaRef.current.value;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Editor textareaRef={TextareaRef} {...childProps} onOpenModal={onOpen} />
|
||||
{isOpen && (
|
||||
<MyModal iconSrc="/imgs/modal/edit.svg" title={title} isOpen onClose={onClose}>
|
||||
<ModalBody>
|
||||
<Editor
|
||||
textareaRef={ModalTextareaRef}
|
||||
{...childProps}
|
||||
minH={'300px'}
|
||||
maxH={'auto'}
|
||||
minW={['100%', '512px']}
|
||||
/>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (ModalTextareaRef.current && TextareaRef.current) {
|
||||
TextareaRef.current.value = ModalTextareaRef.current.value;
|
||||
}
|
||||
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{t('common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{t('common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default PromptTextarea;
|
||||
export default React.memo(PromptTextarea);
|
||||
|
||||
const Editor = React.memo(function Editor({
|
||||
onOpenModal,
|
||||
@@ -75,7 +77,7 @@ const Editor = React.memo(function Editor({
|
||||
|
||||
return (
|
||||
<Box h={'100%'} w={'100%'} position={'relative'}>
|
||||
<Textarea ref={textareaRef} wordBreak={'break-all'} maxW={'100%'} {...props} />
|
||||
<Textarea ref={textareaRef} textAlign={'justify'} maxW={'100%'} {...props} />
|
||||
{onOpenModal && (
|
||||
<Box
|
||||
zIndex={1}
|
||||
|
@@ -1,5 +1,11 @@
|
||||
import React from 'react';
|
||||
import { SmoothStepEdge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath } from 'reactflow';
|
||||
import {
|
||||
BezierEdge,
|
||||
getBezierPath,
|
||||
EdgeLabelRenderer,
|
||||
EdgeProps,
|
||||
getSmoothStepPath
|
||||
} from 'reactflow';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import MyIcon from '@/components/Icon';
|
||||
|
||||
@@ -21,7 +27,7 @@ const ButtonEdge = (
|
||||
style = {}
|
||||
} = props;
|
||||
|
||||
const [edgePath, labelX, labelY] = getSmoothStepPath({
|
||||
const [edgePath, labelX, labelY] = getBezierPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition,
|
||||
@@ -42,7 +48,7 @@ const ButtonEdge = (
|
||||
|
||||
return (
|
||||
<>
|
||||
<SmoothStepEdge {...props} style={edgeStyle} />
|
||||
<BezierEdge {...props} style={edgeStyle} />
|
||||
<EdgeLabelRenderer>
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
|
@@ -14,7 +14,7 @@ import 'reactflow/dist/style.css';
|
||||
import type { ModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||
|
||||
const NodeSimple = dynamic(() => import('./components/nodes/NodeSimple'));
|
||||
const nodeTypes = {
|
||||
const nodeTypes: Record<`${FlowNodeTypeEnum}`, any> = {
|
||||
[FlowNodeTypeEnum.userGuide]: dynamic(() => import('./components/nodes/NodeUserGuide')),
|
||||
[FlowNodeTypeEnum.variable]: dynamic(() => import('./components/nodes/abandon/NodeVariable')),
|
||||
[FlowNodeTypeEnum.questionInput]: dynamic(() => import('./components/nodes/NodeQuestionInput')),
|
||||
@@ -28,7 +28,8 @@ const nodeTypes = {
|
||||
[FlowNodeTypeEnum.runApp]: NodeSimple,
|
||||
[FlowNodeTypeEnum.pluginInput]: dynamic(() => import('./components/nodes/NodePluginInput')),
|
||||
[FlowNodeTypeEnum.pluginOutput]: dynamic(() => import('./components/nodes/NodePluginOutput')),
|
||||
[FlowNodeTypeEnum.pluginModule]: NodeSimple
|
||||
[FlowNodeTypeEnum.pluginModule]: NodeSimple,
|
||||
[FlowNodeTypeEnum.cfr]: NodeSimple
|
||||
};
|
||||
const edgeTypes = {
|
||||
[EDGE_TYPE]: ButtonEdge
|
||||
|
@@ -1,14 +1,16 @@
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { FlowNodeOutputTargetItemType } from '@fastgpt/global/core/module/node/type';
|
||||
import { FlowModuleItemType, ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { type Node, type Edge } from 'reactflow';
|
||||
|
||||
export function flowNode2Modules({
|
||||
export const flowNode2Modules = ({
|
||||
nodes,
|
||||
edges
|
||||
}: {
|
||||
nodes: Node<FlowModuleItemType, string | undefined>[];
|
||||
edges: Edge<any>[];
|
||||
}) {
|
||||
}) => {
|
||||
const modules: ModuleItemType[] = nodes.map((item) => ({
|
||||
moduleId: item.data.moduleId,
|
||||
name: item.data.name,
|
||||
@@ -48,4 +50,19 @@ export function flowNode2Modules({
|
||||
});
|
||||
|
||||
return modules;
|
||||
}
|
||||
};
|
||||
|
||||
export const filterExportModules = (modules: ModuleItemType[]) => {
|
||||
modules.forEach((module) => {
|
||||
// dataset - remove select dataset value
|
||||
if (module.flowType === FlowNodeTypeEnum.datasetSearchNode) {
|
||||
module.inputs.forEach((item) => {
|
||||
if (item.key === ModuleInputKeyEnum.datasetSelectList) {
|
||||
item.value = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return JSON.stringify(modules, null, 2);
|
||||
};
|
||||
|
Reference in New Issue
Block a user