mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
4.8.11 perf (#2768)
* perf: watch local * perf: dataset list ui * perf: Check workflow invalid edges in saved * remove log * perf: Forbid touch scale * perf: rename dataset process * feat: support child app unstream mode * feat: Dispatch child app will record detail * feat: Save childApp run log * fix: share page init error * perf: chatId reset
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
"charsPointsPrice": 0, // n积分/1k token(商业版)
|
||||
"censor": false, // 是否开启敏感校验(商业版)
|
||||
"vision": true, // 是否支持图片输入
|
||||
"datasetProcess": true, // 是否设置为知识库处理模型(QA),务必保证至少有一个为true,否则知识库会报错
|
||||
"datasetProcess": true, // 是否设置为文本理解模型(QA),务必保证至少有一个为true,否则知识库会报错
|
||||
"usedInClassify": true, // 是否用于问题分类(务必保证至少有一个为true)
|
||||
"usedInExtractFields": true, // 是否用于内容提取(务必保证至少有一个为true)
|
||||
"usedInToolCall": true, // 是否用于工具调用(务必保证至少有一个为true)
|
||||
@@ -44,7 +44,7 @@
|
||||
"charsPointsPrice": 0,
|
||||
"censor": false,
|
||||
"vision": true,
|
||||
"datasetProcess": false,
|
||||
"datasetProcess": true,
|
||||
"usedInClassify": true,
|
||||
"usedInExtractFields": true,
|
||||
"usedInToolCall": true,
|
||||
@@ -68,7 +68,7 @@
|
||||
"charsPointsPrice": 0,
|
||||
"censor": false,
|
||||
"vision": false,
|
||||
"datasetProcess": false,
|
||||
"datasetProcess": true,
|
||||
"usedInClassify": true,
|
||||
"usedInExtractFields": true,
|
||||
"usedInToolCall": true,
|
||||
@@ -97,7 +97,7 @@
|
||||
"charsPointsPrice": 0,
|
||||
"censor": false,
|
||||
"vision": false,
|
||||
"datasetProcess": false,
|
||||
"datasetProcess": true,
|
||||
"usedInClassify": true,
|
||||
"usedInExtractFields": true,
|
||||
"usedInToolCall": true,
|
||||
|
@@ -56,6 +56,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
||||
[router.pathname, router.query]
|
||||
);
|
||||
|
||||
// System hook
|
||||
const { data, refetch: refetchUnRead } = useQuery(['getUnreadCount'], getUnreadCount, {
|
||||
enabled: !!userInfo && !!feConfigs.isPlus,
|
||||
refetchInterval: 10000
|
||||
|
@@ -11,11 +11,25 @@ import { useInitApp } from '@/web/context/useInitApp';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import '@/web/styles/reset.scss';
|
||||
import NextHead from '@/components/common/NextHead';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
function App({ Component, pageProps }: AppProps) {
|
||||
const { feConfigs, scripts, title } = useInitApp();
|
||||
const { t } = useTranslation();
|
||||
|
||||
// Forbid touch scale
|
||||
useEffect(() => {
|
||||
document.addEventListener(
|
||||
'wheel',
|
||||
function (e) {
|
||||
if (e.ctrlKey && Math.abs(e.deltaY) !== 0) {
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
{ passive: false }
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<NextHead
|
||||
|
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
import type { NextApiResponse } from 'next';
|
||||
import {
|
||||
getPluginPreviewNode,
|
||||
getChildAppPreviewNode,
|
||||
splitCombinePluginId
|
||||
} from '@fastgpt/service/core/app/plugin/controller';
|
||||
import { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node.d';
|
||||
@@ -27,7 +27,7 @@ async function handler(
|
||||
await authApp({ req, authToken: true, appId, per: ReadPermissionVal });
|
||||
}
|
||||
|
||||
return getPluginPreviewNode({ id: appId });
|
||||
return getChildAppPreviewNode({ id: appId });
|
||||
}
|
||||
|
||||
export default NextAPI(handler);
|
||||
|
@@ -116,8 +116,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const workflowResponseWrite = getWorkflowResponseWrite({
|
||||
res,
|
||||
detail: true,
|
||||
streamResponse: true,
|
||||
id: getNanoid(24)
|
||||
streamResponse: true
|
||||
});
|
||||
|
||||
/* start process */
|
||||
|
@@ -240,7 +240,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
res,
|
||||
detail,
|
||||
streamResponse: stream,
|
||||
id: chatId || getNanoid(24)
|
||||
id: chatId
|
||||
});
|
||||
|
||||
/* start flow controller */
|
||||
|
@@ -262,7 +262,8 @@ const Header = () => {
|
||||
await onClickSave({});
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:saved_success')
|
||||
title: t('app:saved_success'),
|
||||
position: 'top-right'
|
||||
});
|
||||
onClose();
|
||||
setIsSave(false);
|
||||
@@ -332,7 +333,8 @@ const Header = () => {
|
||||
onBack();
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:saved_success')
|
||||
title: t('app:saved_success'),
|
||||
position: 'top-right'
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
@@ -85,7 +85,8 @@ const Header = ({
|
||||
});
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:publish_success')
|
||||
title: t('app:publish_success'),
|
||||
position: 'top-right'
|
||||
});
|
||||
},
|
||||
[onSaveApp, t, toast]
|
||||
|
@@ -264,7 +264,8 @@ const Header = () => {
|
||||
await onClickSave({});
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:saved_success')
|
||||
title: t('app:saved_success'),
|
||||
position: 'top-right'
|
||||
});
|
||||
onClose();
|
||||
setIsSave(false);
|
||||
@@ -334,7 +335,8 @@ const Header = () => {
|
||||
onBack();
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:saved_success')
|
||||
title: t('app:saved_success'),
|
||||
position: 'top-right'
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
@@ -67,7 +67,8 @@ const SaveAndPublishModal = ({
|
||||
await onClickSave({ ...data, isPublish: true });
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('app:publish_success')
|
||||
title: t('app:publish_success'),
|
||||
position: 'top-right'
|
||||
});
|
||||
onClose();
|
||||
})}
|
||||
|
@@ -89,6 +89,7 @@ const InputLabel = ({ nodeId, input }: Props) => {
|
||||
required,
|
||||
selectedTypeIndex,
|
||||
t,
|
||||
valueDesc,
|
||||
valueType
|
||||
]);
|
||||
|
||||
|
@@ -344,7 +344,7 @@ const WorkflowContextProvider = ({
|
||||
const [workflowControlMode, setWorkflowControlMode] = useLocalStorageState<'drag' | 'select'>(
|
||||
'workflow-control-mode',
|
||||
{
|
||||
defaultValue: 'select',
|
||||
defaultValue: 'drag',
|
||||
listenStorageChange: true
|
||||
}
|
||||
);
|
||||
@@ -782,10 +782,12 @@ const WorkflowContextProvider = ({
|
||||
|
||||
/* snapshots */
|
||||
const [past, setPast] = useLocalStorageState<SnapshotsType[]>(`${appId}-past`, {
|
||||
defaultValue: []
|
||||
defaultValue: [],
|
||||
listenStorageChange: true
|
||||
}) as [SnapshotsType[], (value: SetStateAction<SnapshotsType[]>) => void];
|
||||
const [future, setFuture] = useLocalStorageState<SnapshotsType[]>(`${appId}-future`, {
|
||||
defaultValue: []
|
||||
defaultValue: [],
|
||||
listenStorageChange: true
|
||||
}) as [SnapshotsType[], (value: SetStateAction<SnapshotsType[]>) => void];
|
||||
|
||||
const resetSnapshot = useMemoizedFn((state: SnapshotsType) => {
|
||||
|
@@ -25,10 +25,17 @@ export const uiWorkflow2StoreWorkflow = ({
|
||||
version: item.data.version,
|
||||
inputs: item.data.inputs,
|
||||
outputs: item.data.outputs,
|
||||
pluginId: item.data.pluginId,
|
||||
parentNodeId: item.data.parentNodeId
|
||||
pluginId: item.data.pluginId
|
||||
}));
|
||||
|
||||
// get all handle
|
||||
const reactFlowViewport = document.querySelector('.react-flow__viewport');
|
||||
// Gets the value of data-handleid on all elements below it whose data-handleid is not empty
|
||||
const handleList =
|
||||
reactFlowViewport?.querySelectorAll('[data-handleid]:not([data-handleid=""])') || [];
|
||||
const handleIdList = Array.from(handleList).map(
|
||||
(item) => item.getAttribute('data-handleid') || ''
|
||||
);
|
||||
const formatEdges: StoreEdgeItemType[] = edges
|
||||
.map((item) => ({
|
||||
source: item.source,
|
||||
@@ -36,7 +43,15 @@ export const uiWorkflow2StoreWorkflow = ({
|
||||
sourceHandle: item.sourceHandle || '',
|
||||
targetHandle: item.targetHandle || ''
|
||||
}))
|
||||
.filter((item) => item.sourceHandle && item.targetHandle);
|
||||
.filter((item) => item.sourceHandle && item.targetHandle)
|
||||
.filter(
|
||||
// Filter out edges that do not have both sourceHandle and targetHandle
|
||||
(item) => {
|
||||
// Not in react flow page
|
||||
if (!reactFlowViewport) return true;
|
||||
return handleIdList.includes(item.sourceHandle) && handleIdList.includes(item.targetHandle);
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
nodes: formatNodes,
|
||||
|
@@ -113,7 +113,7 @@ const Chat = ({
|
||||
if (e?.code === 501) {
|
||||
router.replace('/app/list');
|
||||
} else if (chatId) {
|
||||
onChangeChatId('');
|
||||
onChangeChatId();
|
||||
}
|
||||
},
|
||||
onFinally() {
|
||||
|
@@ -2,12 +2,13 @@ import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Box, Flex, Drawer, DrawerOverlay, DrawerContent } from '@chakra-ui/react';
|
||||
import { streamFetch } from '@/web/common/api/fetch';
|
||||
import { useShareChatStore } from '@/web/core/chat/storeShareChat';
|
||||
import SideBar from '@/components/SideBar';
|
||||
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
|
||||
|
||||
const nanoid = customAlphabet(
|
||||
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ1234567890_',
|
||||
24
|
||||
);
|
||||
import ChatBox from '@/components/core/chat/ChatContainer/ChatBox';
|
||||
import type { StartChatFnProps } from '@/components/core/chat/ChatContainer/type';
|
||||
|
||||
@@ -16,7 +17,7 @@ import ChatHeader from './components/ChatHeader';
|
||||
import ChatHistorySlider from './components/ChatHistorySlider';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { delChatRecordById, getChatHistories, getInitOutLinkChatInfo } from '@/web/core/chat/api';
|
||||
import { delChatRecordById, getInitOutLinkChatInfo } from '@/web/core/chat/api';
|
||||
import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils';
|
||||
import { ChatStatusEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
|
||||
@@ -36,6 +37,7 @@ import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||
import { useShareChatStore } from '@/web/core/chat/storeShareChat';
|
||||
const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox'));
|
||||
|
||||
type Props = {
|
||||
@@ -46,7 +48,14 @@ type Props = {
|
||||
authToken: string;
|
||||
};
|
||||
|
||||
const OutLink = ({ appName, appIntro, appAvatar }: Props) => {
|
||||
const OutLink = ({
|
||||
outLinkUid,
|
||||
appName,
|
||||
appIntro,
|
||||
appAvatar
|
||||
}: Props & {
|
||||
outLinkUid: string;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const {
|
||||
@@ -69,14 +78,9 @@ const OutLink = ({ appName, appIntro, appAvatar }: Props) => {
|
||||
const [isEmbed, setIdEmbed] = useState(true);
|
||||
|
||||
const [chatData, setChatData] = useState<InitChatResponse>(defaultChatData);
|
||||
const appId = chatData.appId;
|
||||
|
||||
const { localUId } = useShareChatStore();
|
||||
const outLinkUid: string = authToken || localUId;
|
||||
|
||||
const {
|
||||
onUpdateHistoryTitle,
|
||||
loadHistories,
|
||||
onUpdateHistory,
|
||||
onClearHistories,
|
||||
onDelHistory,
|
||||
@@ -212,7 +216,7 @@ const OutLink = ({ appName, appIntro, appAvatar }: Props) => {
|
||||
onError(e: any) {
|
||||
console.log(e);
|
||||
if (chatId) {
|
||||
onChangeChatId('');
|
||||
onChangeChatId();
|
||||
}
|
||||
},
|
||||
onFinally() {
|
||||
@@ -352,16 +356,21 @@ const OutLink = ({ appName, appIntro, appAvatar }: Props) => {
|
||||
|
||||
const Render = (props: Props) => {
|
||||
const { shareId, authToken } = props;
|
||||
const { localUId } = useShareChatStore();
|
||||
const outLinkUid: string = authToken || localUId;
|
||||
const { localUId, setLocalUId } = useShareChatStore();
|
||||
|
||||
const contextParams = useMemo(() => {
|
||||
return { shareId, outLinkUid };
|
||||
}, [shareId, outLinkUid]);
|
||||
if (!localUId) {
|
||||
const localId = `shareChat-${Date.now()}-${nanoid()}`;
|
||||
setLocalUId(localId);
|
||||
return { shareId, outLinkUid: authToken || localId };
|
||||
}
|
||||
|
||||
return { shareId, outLinkUid: authToken || localUId };
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ChatContextProvider params={contextParams}>
|
||||
<OutLink {...props} />;
|
||||
<OutLink {...props} outLinkUid={contextParams.outLinkUid} />;
|
||||
</ChatContextProvider>
|
||||
);
|
||||
};
|
||||
|
@@ -166,7 +166,7 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
||||
status: 'error'
|
||||
});
|
||||
if (chatId) {
|
||||
onChangeChatId('');
|
||||
onChangeChatId();
|
||||
}
|
||||
},
|
||||
onFinally() {
|
||||
|
@@ -287,9 +287,9 @@ function List() {
|
||||
<HStack>
|
||||
{isPc && (
|
||||
<HStack spacing={1} className="time">
|
||||
<MyIcon name={'history'} w={'0.85rem'} color={'myGray.400'} />
|
||||
<Avatar src={dataset.vectorModel.avatar} w={'0.85rem'} />
|
||||
<Box color={'myGray.500'} fontSize={'mini'}>
|
||||
{formatTimeToChatTime(dataset.updateTime)}
|
||||
{dataset.vectorModel.name}
|
||||
</Box>
|
||||
</HStack>
|
||||
)}
|
||||
|
@@ -195,7 +195,7 @@ const ChatContextProvider = ({
|
||||
setHistories([]);
|
||||
},
|
||||
onFinally() {
|
||||
onChangeChatId('');
|
||||
onChangeChatId();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@@ -1,22 +1,22 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import type { ChatHistoryItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet(
|
||||
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ1234567890_',
|
||||
24
|
||||
);
|
||||
|
||||
type State = {
|
||||
localUId: string;
|
||||
setLocalUId: (id: string) => void;
|
||||
};
|
||||
|
||||
export const useShareChatStore = create<State>()(
|
||||
devtools(
|
||||
persist(
|
||||
immer((set, get) => ({
|
||||
localUId: `shareChat-${Date.now()}-${nanoid()}`
|
||||
localUId: '',
|
||||
setLocalUId(id) {
|
||||
set((state) => {
|
||||
state.localUId = id;
|
||||
});
|
||||
}
|
||||
})),
|
||||
{
|
||||
name: 'shareChatStore'
|
||||
|
@@ -90,7 +90,7 @@ export const useUserStore = create<State>()(
|
||||
if (!useSystemStore.getState()?.feConfigs?.isPlus) return [];
|
||||
|
||||
const randomRefresh = Math.random() > 0.7;
|
||||
if (!randomRefresh && !init && get().teamMembers.length)
|
||||
if (!randomRefresh && !init && get().teamMembers?.length)
|
||||
return Promise.resolve(get().teamMembers);
|
||||
|
||||
const res = await getTeamMembers();
|
||||
|
Reference in New Issue
Block a user