mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
whole response modal
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
"Output Field Settings": "Output Field Settings"
|
||||
},
|
||||
"chat": {
|
||||
"Complete Response": "Complete Response",
|
||||
"Confirm to clear history": "Confirm to clear history?",
|
||||
"Exit Chat": "Exit",
|
||||
"History": "History",
|
||||
|
@@ -16,6 +16,7 @@
|
||||
"Output Field Settings": "输出字段编辑"
|
||||
},
|
||||
"chat": {
|
||||
"Complete Response": "完整响应",
|
||||
"Confirm to clear history": "确认清空该应用的聊天记录?",
|
||||
"Exit Chat": "退出聊天",
|
||||
"History": "记录",
|
||||
|
@@ -1,14 +1,17 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { ChatModuleEnum } from '@/constants/chat';
|
||||
import { ChatHistoryItemResType, ChatItemType, QuoteItemType } from '@/types/chat';
|
||||
import { Flex, BoxProps } from '@chakra-ui/react';
|
||||
import { Flex, BoxProps, useDisclosure } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGlobalStore } from '@/store/global';
|
||||
import dynamic from 'next/dynamic';
|
||||
import Tag from '../Tag';
|
||||
import MyTooltip from '../MyTooltip';
|
||||
const QuoteModal = dynamic(() => import('./QuoteModal'), { ssr: false });
|
||||
const ContextModal = dynamic(() => import('./ContextModal'), { ssr: false });
|
||||
const WholeResponseModal = dynamic(() => import('./WholeResponseModal'), { ssr: false });
|
||||
|
||||
const ResponseDetailModal = ({
|
||||
const ResponseTags = ({
|
||||
chatId,
|
||||
contentId,
|
||||
responseData = []
|
||||
@@ -17,28 +20,30 @@ const ResponseDetailModal = ({
|
||||
contentId?: string;
|
||||
responseData?: ChatHistoryItemResType[];
|
||||
}) => {
|
||||
const { isPc } = useGlobalStore();
|
||||
const { t } = useTranslation();
|
||||
const [quoteModalData, setQuoteModalData] = useState<QuoteItemType[]>();
|
||||
const [contextModalData, setContextModalData] = useState<ChatItemType[]>();
|
||||
const {
|
||||
isOpen: isOpenWholeModal,
|
||||
onOpen: onOpenWholeModal,
|
||||
onClose: onCloseWholeModal
|
||||
} = useDisclosure();
|
||||
|
||||
const {
|
||||
tokens = 0,
|
||||
quoteList = [],
|
||||
completeMessages = []
|
||||
completeMessages = [],
|
||||
tokens = 0
|
||||
} = useMemo(() => {
|
||||
const chatData = responseData.find((item) => item.moduleName === ChatModuleEnum.AIChat);
|
||||
if (!chatData) return {};
|
||||
return {
|
||||
tokens: chatData.tokens,
|
||||
quoteList: chatData.quoteList,
|
||||
completeMessages: chatData.completeMessages
|
||||
completeMessages: chatData.completeMessages,
|
||||
tokens: responseData.reduce((sum, item) => sum + (item.tokens || 0), 0)
|
||||
};
|
||||
}, [responseData]);
|
||||
|
||||
const isEmpty = useMemo(
|
||||
() => quoteList.length === 0 && completeMessages.length === 0 && tokens === 0,
|
||||
[completeMessages.length, quoteList.length, tokens]
|
||||
);
|
||||
|
||||
const updateQuote = useCallback(async (quoteId: string, sourceText: string) => {}, []);
|
||||
|
||||
const TagStyles: BoxProps = {
|
||||
@@ -46,7 +51,7 @@ const ResponseDetailModal = ({
|
||||
bg: 'transparent'
|
||||
};
|
||||
|
||||
return isEmpty ? null : (
|
||||
return (
|
||||
<Flex alignItems={'center'} mt={2} flexWrap={'wrap'}>
|
||||
{quoteList.length > 0 && (
|
||||
<MyTooltip label="查看引用">
|
||||
@@ -72,11 +77,17 @@ const ResponseDetailModal = ({
|
||||
</Tag>
|
||||
</MyTooltip>
|
||||
)}
|
||||
{tokens > 0 && (
|
||||
<Tag colorSchema="gray" cursor={'default'} {...TagStyles}>
|
||||
{tokens}tokens
|
||||
{isPc && tokens > 0 && (
|
||||
<Tag colorSchema="purple" cursor={'default'} {...TagStyles}>
|
||||
{tokens}Tokens
|
||||
</Tag>
|
||||
)}
|
||||
<MyTooltip label={'点击查看完整响应值'}>
|
||||
<Tag colorSchema="gray" cursor={'pointer'} {...TagStyles} onClick={onOpenWholeModal}>
|
||||
{t('chat.Complete Response')}
|
||||
</Tag>
|
||||
</MyTooltip>
|
||||
|
||||
{!!quoteModalData && (
|
||||
<QuoteModal
|
||||
rawSearch={quoteModalData}
|
||||
@@ -87,8 +98,11 @@ const ResponseDetailModal = ({
|
||||
{!!contextModalData && (
|
||||
<ContextModal context={contextModalData} onClose={() => setContextModalData(undefined)} />
|
||||
)}
|
||||
{isOpenWholeModal && (
|
||||
<WholeResponseModal response={responseData} onClose={onCloseWholeModal} />
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResponseDetailModal;
|
||||
export default ResponseTags;
|
71
client/src/components/ChatBox/WholeResponseModal.tsx
Normal file
71
client/src/components/ChatBox/WholeResponseModal.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { Box, ModalBody, useTheme, ModalHeader, Flex } from '@chakra-ui/react';
|
||||
import type { ChatHistoryItemResType } from '@/types/chat';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import MyModal from '../MyModal';
|
||||
import MyTooltip from '../MyTooltip';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
|
||||
const ResponseModal = ({
|
||||
response,
|
||||
onClose
|
||||
}: {
|
||||
response: ChatHistoryItemResType[];
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
|
||||
const formatResponse = useMemo(
|
||||
() =>
|
||||
response.map((item) => {
|
||||
const copy = { ...item };
|
||||
delete copy.completeMessages;
|
||||
delete copy.quoteList;
|
||||
return copy;
|
||||
}),
|
||||
[response]
|
||||
);
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
isOpen={true}
|
||||
onClose={onClose}
|
||||
h={['90vh', '80vh']}
|
||||
minW={['90vw', '600px']}
|
||||
title={
|
||||
<Flex alignItems={'center'}>
|
||||
{t('chat.Complete Response')}
|
||||
<MyTooltip
|
||||
label={
|
||||
'moduleName: 模型名\nprice: 价格,倍率:100000\nmodel?: 模型名\ntokens?: token 消耗\n\nanswer?: 回答内容\nquestion?: 问题\ntemperature?: 温度\nmaxToken?: 最大 tokens\n\nsimilarity?: 相似度\nlimit?: 单次搜索结果\n\ncqList?: 问题分类列表\ncqResult?: 分类结果\n\nextractDescription?: 内容提取描述\nextractResult?: 提取结果'
|
||||
}
|
||||
>
|
||||
<QuestionOutlineIcon ml={2} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
}
|
||||
isCentered
|
||||
>
|
||||
<ModalBody>
|
||||
{formatResponse.map((item, i) => (
|
||||
<Box
|
||||
key={i}
|
||||
p={2}
|
||||
pt={[0, 2]}
|
||||
borderRadius={'lg'}
|
||||
border={theme.borders.base}
|
||||
_notLast={{ mb: 2 }}
|
||||
position={'relative'}
|
||||
whiteSpace={'pre-wrap'}
|
||||
>
|
||||
{JSON.stringify(item, null, 2)}
|
||||
</Box>
|
||||
))}
|
||||
</ModalBody>
|
||||
</MyModal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResponseModal;
|
@@ -47,7 +47,7 @@ import Markdown from '@/components/Markdown';
|
||||
import MySelect from '@/components/Select';
|
||||
import MyTooltip from '../MyTooltip';
|
||||
import dynamic from 'next/dynamic';
|
||||
const ResponseDetailModal = dynamic(() => import('./ResponseDetailModal'));
|
||||
const ResponseTags = dynamic(() => import('./ResponseTags'));
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
@@ -678,7 +678,7 @@ const ChatBox = (
|
||||
source={item.value}
|
||||
isChatting={index === chatHistory.length - 1 && isChatting}
|
||||
/>
|
||||
<ResponseDetailModal
|
||||
<ResponseTags
|
||||
chatId={chatId}
|
||||
contentId={item._id}
|
||||
responseData={item.responseData}
|
||||
|
@@ -3,7 +3,7 @@ import { Flex, type FlexProps } from '@chakra-ui/react';
|
||||
|
||||
interface Props extends FlexProps {
|
||||
children: React.ReactNode | React.ReactNode[];
|
||||
colorSchema?: 'blue' | 'green' | 'gray';
|
||||
colorSchema?: 'blue' | 'green' | 'gray' | 'purple';
|
||||
}
|
||||
|
||||
const Tag = ({ children, colorSchema = 'blue', ...props }: Props) => {
|
||||
@@ -19,6 +19,11 @@ const Tag = ({ children, colorSchema = 'blue', ...props }: Props) => {
|
||||
bg: '#f8fff8',
|
||||
color: '#67c13b'
|
||||
},
|
||||
purple: {
|
||||
borderColor: '#A558C9',
|
||||
bg: '#F6EEFA',
|
||||
color: '#A558C9'
|
||||
},
|
||||
gray: {
|
||||
borderColor: '#979797',
|
||||
bg: '#F7F7F7',
|
||||
|
Reference in New Issue
Block a user