mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-03 13:38:00 +00:00
v4.6.9-alpha (#918)
Co-authored-by: Mufei <327958099@qq.com> Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import { IMG_BLOCK_KEY } from '@fastgpt/global/core/chat/constants';
|
||||
import { addDays } from 'date-fns';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
|
||||
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
|
||||
|
||||
enum FileTypeEnum {
|
||||
@@ -35,8 +36,12 @@ const MessageInput = ({
|
||||
isChatting,
|
||||
TextareaDom,
|
||||
showFileSelector = false,
|
||||
resetInputVal
|
||||
}: {
|
||||
resetInputVal,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
teamId,
|
||||
teamToken
|
||||
}: OutLinkChatAuthProps & {
|
||||
onChange?: (e: string) => void;
|
||||
onSendMessage: (e: string) => void;
|
||||
onStop: () => void;
|
||||
@@ -47,7 +52,6 @@ const MessageInput = ({
|
||||
}) => {
|
||||
const [, startSts] = useTransition();
|
||||
|
||||
const { shareId } = useRouter().query as { shareId?: string };
|
||||
const {
|
||||
isSpeaking,
|
||||
isTransCription,
|
||||
@@ -56,7 +60,7 @@ const MessageInput = ({
|
||||
speakingTimeString,
|
||||
renderAudioGraph,
|
||||
stream
|
||||
} = useSpeech({ shareId });
|
||||
} = useSpeech({ shareId, outLinkUid, teamId, teamToken });
|
||||
const { isPc } = useSystemStore();
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const { t } = useTranslation();
|
||||
@@ -82,7 +86,10 @@ const MessageInput = ({
|
||||
maxSize: 1024 * 1024 * 5,
|
||||
// 30 day expired.
|
||||
expiredTime: addDays(new Date(), 7),
|
||||
shareId
|
||||
shareId,
|
||||
outLinkUid,
|
||||
teamId,
|
||||
teamToken
|
||||
});
|
||||
setFileList((state) =>
|
||||
state.map((item) =>
|
||||
@@ -320,7 +327,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
|
||||
rows={1}
|
||||
height={'22px'}
|
||||
lineHeight={'22px'}
|
||||
maxHeight={'150px'}
|
||||
maxHeight={'50vh'}
|
||||
maxLength={-1}
|
||||
overflowY={'auto'}
|
||||
whiteSpace={'pre-wrap'}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { ModalBody, Box, useTheme } from '@chakra-ui/react';
|
||||
|
||||
import MyModal from '../MyModal';
|
||||
@@ -10,12 +10,12 @@ import RawSourceBox from '../core/dataset/RawSourceBox';
|
||||
const QuoteModal = ({
|
||||
rawSearch = [],
|
||||
onClose,
|
||||
isShare,
|
||||
showDetail,
|
||||
metadata
|
||||
}: {
|
||||
rawSearch: SearchDataResponseItemType[];
|
||||
onClose: () => void;
|
||||
isShare: boolean;
|
||||
showDetail: boolean;
|
||||
metadata?: {
|
||||
collectionId: string;
|
||||
sourceId?: string;
|
||||
@@ -57,7 +57,7 @@ const QuoteModal = ({
|
||||
}
|
||||
>
|
||||
<ModalBody>
|
||||
<QuoteList rawSearch={filterResults} isShare={isShare} />
|
||||
<QuoteList rawSearch={filterResults} showDetail={showDetail} />
|
||||
</ModalBody>
|
||||
</MyModal>
|
||||
</>
|
||||
@@ -68,10 +68,10 @@ export default QuoteModal;
|
||||
|
||||
export const QuoteList = React.memo(function QuoteList({
|
||||
rawSearch = [],
|
||||
isShare
|
||||
showDetail
|
||||
}: {
|
||||
rawSearch: SearchDataResponseItemType[];
|
||||
isShare: boolean;
|
||||
showDetail: boolean;
|
||||
}) {
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -88,7 +88,7 @@ export const QuoteList = React.memo(function QuoteList({
|
||||
_hover={{ '& .hover-data': { display: 'flex' } }}
|
||||
bg={i % 2 === 0 ? 'white' : 'myWhite.500'}
|
||||
>
|
||||
<QuoteItem quoteItem={item} canViewSource={!isShare} linkToDataset={!isShare} />
|
||||
<QuoteItem quoteItem={item} canViewSource={showDetail} linkToDataset={showDetail} />
|
||||
</Box>
|
||||
))}
|
||||
</>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d';
|
||||
import type { ChatItemType } from '@fastgpt/global/core/chat/type';
|
||||
import { Flex, BoxProps, useDisclosure, Image, useTheme, Box } from '@chakra-ui/react';
|
||||
import { Flex, BoxProps, useDisclosure, useTheme, Box } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
||||
@@ -20,10 +20,10 @@ const WholeResponseModal = dynamic(() => import('./WholeResponseModal'), { ssr:
|
||||
|
||||
const ResponseTags = ({
|
||||
responseData = [],
|
||||
isShare
|
||||
showDetail
|
||||
}: {
|
||||
responseData?: ChatHistoryItemResType[];
|
||||
isShare: boolean;
|
||||
showDetail: boolean;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { isPc } = useSystemStore();
|
||||
@@ -76,13 +76,13 @@ const ResponseTags = ({
|
||||
sourceName: item.sourceName,
|
||||
sourceId: item.sourceId,
|
||||
icon: getSourceNameIcon({ sourceId: item.sourceId, sourceName: item.sourceName }),
|
||||
canReadQuote: !isShare || strIsLink(item.sourceId),
|
||||
canReadQuote: showDetail || strIsLink(item.sourceId),
|
||||
collectionId: item.collectionId
|
||||
})),
|
||||
historyPreview: chatData?.historyPreview,
|
||||
runningTime: +responseData.reduce((sum, item) => sum + (item.runningTime || 0), 0).toFixed(2)
|
||||
};
|
||||
}, [isShare, responseData]);
|
||||
}, [showDetail, responseData]);
|
||||
|
||||
const TagStyles: BoxProps = {
|
||||
mr: 2,
|
||||
@@ -134,7 +134,7 @@ const ResponseTags = ({
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
{!isShare && (
|
||||
{showDetail && (
|
||||
<Flex alignItems={'center'} mt={3} flexWrap={'wrap'}>
|
||||
{quoteList.length > 0 && (
|
||||
<MyTooltip label="查看引用">
|
||||
@@ -187,7 +187,7 @@ const ResponseTags = ({
|
||||
{!!quoteModalData && (
|
||||
<QuoteModal
|
||||
{...quoteModalData}
|
||||
isShare={isShare}
|
||||
showDetail={showDetail}
|
||||
onClose={() => setQuoteModalData(undefined)}
|
||||
/>
|
||||
)}
|
||||
@@ -195,7 +195,11 @@ const ResponseTags = ({
|
||||
<ContextModal context={contextModalData} onClose={() => setContextModalData(undefined)} />
|
||||
)}
|
||||
{isOpenWholeModal && (
|
||||
<WholeResponseModal response={responseData} isShare={isShare} onClose={onCloseWholeModal} />
|
||||
<WholeResponseModal
|
||||
response={responseData}
|
||||
showDetail={showDetail}
|
||||
onClose={onCloseWholeModal}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
@@ -51,11 +51,11 @@ function Row({
|
||||
|
||||
const WholeResponseModal = ({
|
||||
response,
|
||||
isShare,
|
||||
showDetail,
|
||||
onClose
|
||||
}: {
|
||||
response: ChatHistoryItemResType[];
|
||||
isShare: boolean;
|
||||
showDetail: boolean;
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -78,7 +78,7 @@ const WholeResponseModal = ({
|
||||
}
|
||||
>
|
||||
<Flex h={'100%'} flexDirection={'column'}>
|
||||
<ResponseBox response={response} isShare={isShare} />
|
||||
<ResponseBox response={response} showDetail={showDetail} />
|
||||
</Flex>
|
||||
</MyModal>
|
||||
);
|
||||
@@ -88,10 +88,10 @@ export default WholeResponseModal;
|
||||
|
||||
const ResponseBox = React.memo(function ResponseBox({
|
||||
response,
|
||||
isShare
|
||||
showDetail
|
||||
}: {
|
||||
response: ChatHistoryItemResType[];
|
||||
isShare: boolean;
|
||||
showDetail: boolean;
|
||||
}) {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
@@ -142,10 +142,7 @@ const ResponseBox = React.memo(function ResponseBox({
|
||||
value={`${activeModule?.runningTime || 0}s`}
|
||||
/>
|
||||
<Row label={t('core.chat.response.module model')} value={activeModule?.model} />
|
||||
<Row
|
||||
label={t('support.wallet.usage.Chars length')}
|
||||
value={`${activeModule?.charsLength}`}
|
||||
/>
|
||||
<Row label={t('core.chat.response.module tokens')} value={`${activeModule?.tokens}`} />
|
||||
<Row label={t('core.chat.response.module query')} value={activeModule?.query} />
|
||||
<Row
|
||||
label={t('core.chat.response.context total length')}
|
||||
@@ -188,7 +185,7 @@ const ResponseBox = React.memo(function ResponseBox({
|
||||
{activeModule.quoteList && activeModule.quoteList.length > 0 && (
|
||||
<Row
|
||||
label={t('core.chat.response.module quoteList')}
|
||||
rawDom={<QuoteList isShare={isShare} rawSearch={activeModule.quoteList} />}
|
||||
rawDom={<QuoteList showDetail={showDetail} rawSearch={activeModule.quoteList} />}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@@ -280,7 +277,7 @@ const ResponseBox = React.memo(function ResponseBox({
|
||||
{activeModule?.pluginDetail && activeModule?.pluginDetail.length > 0 && (
|
||||
<Row
|
||||
label={t('core.chat.response.Plugin Resonse Detail')}
|
||||
rawDom={<ResponseBox response={activeModule.pluginDetail} isShare={isShare} />}
|
||||
rawDom={<ResponseBox response={activeModule.pluginDetail} showDetail={showDetail} />}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
@@ -68,6 +68,7 @@ import type { AppTTSConfigType, VariableItemType } from '@fastgpt/global/core/mo
|
||||
import MessageInput from './MessageInput';
|
||||
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import ChatBoxDivider from '../core/chat/Divider';
|
||||
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
|
||||
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
|
||||
|
||||
@@ -106,7 +107,7 @@ const MessageCardStyle: BoxProps = {
|
||||
maxW: ['calc(100% - 25px)', 'calc(100% - 40px)']
|
||||
};
|
||||
|
||||
type Props = {
|
||||
type Props = OutLinkChatAuthProps & {
|
||||
feedbackType?: `${FeedbackTypeEnum}`;
|
||||
showMarkIcon?: boolean; // admin mark dataset
|
||||
showVoiceIcon?: boolean;
|
||||
@@ -120,9 +121,6 @@ type Props = {
|
||||
// not chat test params
|
||||
appId?: string;
|
||||
chatId?: string;
|
||||
shareId?: string;
|
||||
shareTeamId?: string;
|
||||
outLinkUid?: string;
|
||||
|
||||
onUpdateVariable?: (e: Record<string, any>) => void;
|
||||
onStartChat?: (e: StartChatFnProps) => Promise<{
|
||||
@@ -147,8 +145,9 @@ const ChatBox = (
|
||||
appId,
|
||||
chatId,
|
||||
shareId,
|
||||
shareTeamId,
|
||||
outLinkUid,
|
||||
teamId,
|
||||
teamToken,
|
||||
onUpdateVariable,
|
||||
onStartChat,
|
||||
onDelMessage
|
||||
@@ -288,7 +287,10 @@ const ChatBox = (
|
||||
const result = await postQuestionGuide(
|
||||
{
|
||||
messages: adaptChat2GptMessages({ messages: history, reserveId: false }).slice(-6),
|
||||
shareId
|
||||
shareId,
|
||||
outLinkUid,
|
||||
teamId,
|
||||
teamToken
|
||||
},
|
||||
abortSignal
|
||||
);
|
||||
@@ -300,7 +302,7 @@ const ChatBox = (
|
||||
}
|
||||
} catch (error) {}
|
||||
},
|
||||
[questionGuide, shareId]
|
||||
[questionGuide, shareId, outLinkUid, teamId, teamToken]
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -398,22 +400,20 @@ const ChatBox = (
|
||||
};
|
||||
})
|
||||
);
|
||||
if (!shareTeamId) {
|
||||
setTimeout(() => {
|
||||
createQuestionGuide({
|
||||
history: newChatList.map((item, i) =>
|
||||
i === newChatList.length - 1
|
||||
? {
|
||||
...item,
|
||||
value: responseText
|
||||
}
|
||||
: item
|
||||
)
|
||||
});
|
||||
generatingScroll();
|
||||
isPc && TextareaDom.current?.focus();
|
||||
}, 100);
|
||||
}
|
||||
setTimeout(() => {
|
||||
createQuestionGuide({
|
||||
history: newChatList.map((item, i) =>
|
||||
i === newChatList.length - 1
|
||||
? {
|
||||
...item,
|
||||
value: responseText
|
||||
}
|
||||
: item
|
||||
)
|
||||
});
|
||||
generatingScroll();
|
||||
isPc && TextareaDom.current?.focus();
|
||||
}, 100);
|
||||
} catch (err: any) {
|
||||
toast({
|
||||
title: t(getErrText(err, 'core.chat.error.Chat error')),
|
||||
@@ -622,6 +622,7 @@ const ChatBox = (
|
||||
{/* control icon */}
|
||||
<Flex w={'100%'} alignItems={'center'} justifyContent={'flex-end'}>
|
||||
<ChatControllerComponent
|
||||
isChatting={isChatting}
|
||||
chat={item}
|
||||
onDelete={
|
||||
onDelMessage
|
||||
@@ -654,12 +655,17 @@ const ChatBox = (
|
||||
<ChatAvatar src={appAvatar} type={'AI'} />
|
||||
{/* control icon */}
|
||||
<ChatControllerComponent
|
||||
isChatting={isChatting}
|
||||
ml={2}
|
||||
chat={item}
|
||||
setChatHistory={setChatHistory}
|
||||
display={index === chatHistory.length - 1 && isChatting ? 'none' : 'flex'}
|
||||
showVoiceIcon={showVoiceIcon}
|
||||
ttsConfig={ttsConfig}
|
||||
shareId={shareId}
|
||||
outLinkUid={outLinkUid}
|
||||
teamId={teamId}
|
||||
teamToken={teamToken}
|
||||
onDelete={
|
||||
onDelMessage
|
||||
? () => {
|
||||
@@ -829,7 +835,10 @@ const ChatBox = (
|
||||
isChatting={index === chatHistory.length - 1 && isChatting}
|
||||
/>
|
||||
|
||||
<ResponseTags responseData={item.responseData} isShare={!!shareId} />
|
||||
<ResponseTags
|
||||
responseData={item.responseData}
|
||||
showDetail={!shareId && !teamId}
|
||||
/>
|
||||
|
||||
{/* custom feedback */}
|
||||
{item.customFeedbacks && item.customFeedbacks.length > 0 && (
|
||||
@@ -909,6 +918,10 @@ const ChatBox = (
|
||||
TextareaDom={TextareaDom}
|
||||
resetInputVal={resetInputVal}
|
||||
showFileSelector={showFileSelector}
|
||||
shareId={shareId}
|
||||
outLinkUid={outLinkUid}
|
||||
teamId={teamId}
|
||||
teamToken={teamToken}
|
||||
/>
|
||||
)}
|
||||
{/* user feedback modal */}
|
||||
@@ -1236,6 +1249,7 @@ function Empty() {
|
||||
}
|
||||
|
||||
const ChatControllerComponent = React.memo(function ChatControllerComponent({
|
||||
isChatting,
|
||||
chat,
|
||||
setChatHistory,
|
||||
display,
|
||||
@@ -1249,8 +1263,13 @@ const ChatControllerComponent = React.memo(function ChatControllerComponent({
|
||||
onAddUserDislike,
|
||||
onAddUserLike,
|
||||
ml,
|
||||
mr
|
||||
}: {
|
||||
mr,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
teamId,
|
||||
teamToken
|
||||
}: OutLinkChatAuthProps & {
|
||||
isChatting: boolean;
|
||||
chat: ChatSiteItemType;
|
||||
setChatHistory?: React.Dispatch<React.SetStateAction<ChatSiteItemType[]>>;
|
||||
showVoiceIcon?: boolean;
|
||||
@@ -1267,7 +1286,11 @@ const ChatControllerComponent = React.memo(function ChatControllerComponent({
|
||||
const { t } = useTranslation();
|
||||
const { copyData } = useCopyData();
|
||||
const { audioLoading, audioPlaying, hasAudio, playAudio, cancelAudio } = useAudioPlay({
|
||||
ttsConfig
|
||||
ttsConfig,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
teamId,
|
||||
teamToken
|
||||
});
|
||||
const controlIconStyle = {
|
||||
w: '14px',
|
||||
@@ -1296,7 +1319,7 @@ const ChatControllerComponent = React.memo(function ChatControllerComponent({
|
||||
onClick={() => copyData(chat.value)}
|
||||
/>
|
||||
</MyTooltip>
|
||||
{!!onDelete && (
|
||||
{!!onDelete && !isChatting && (
|
||||
<>
|
||||
{onRetry && (
|
||||
<MyTooltip label={t('core.chat.retry')}>
|
||||
|
Reference in New Issue
Block a user