Commit 86c27e85 by Archer Committed by GitHub

4.8.10 perf (#2378)

* perf: helpline code

* fix: prompt call stream=false response prefix

* fix: app chat log auth

* perf: new chat i18n

* fix: milvus dataset cannot export data

* perf: doc intro
parent fdeb1590
...@@ -20,4 +20,10 @@ weight: 816 ...@@ -20,4 +20,10 @@ weight: 816
## V4.8.10 更新说明 ## V4.8.10 更新说明
1. 新增 - 模板市场 1. 新增 - 模板市场
2. 2. 新增 - 工作流节点拖动自动对齐吸附
3. 新增 - 用户选择节点(Debug 模式暂未支持)
4. 商业版新增 - 飞书机器人接入
5. 商业版新增 - 公众号接入接入
6. 修复 - Prompt 模式调用工具,stream=false 模式下,会携带 0: 开头标记。
7. 修复 - 对话日志鉴权问题:仅为 APP 管理员的用户,无法查看对话日志详情。
8. 修复 - 选择 Milvus 部署时,无法导出知识库。
...@@ -411,6 +411,7 @@ const parseAnswer = ( ...@@ -411,6 +411,7 @@ const parseAnswer = (
str = str.trim(); str = str.trim();
// 首先,使用正则表达式提取TOOL_ID和TOOL_ARGUMENTS // 首先,使用正则表达式提取TOOL_ID和TOOL_ARGUMENTS
const prefixReg = /^1(:|:)/; const prefixReg = /^1(:|:)/;
const answerPrefixReg = /^0(:|:)/;
if (prefixReg.test(str)) { if (prefixReg.test(str)) {
const toolString = sliceJsonStr(str); const toolString = sliceJsonStr(str);
...@@ -432,7 +433,7 @@ const parseAnswer = ( ...@@ -432,7 +433,7 @@ const parseAnswer = (
} }
} else { } else {
return { return {
answer: str answer: str.replace(answerPrefixReg, '')
}; };
} }
}; };
...@@ -30,7 +30,7 @@ export type InitChatResponse = { ...@@ -30,7 +30,7 @@ export type InitChatResponse = {
chatId?: string; chatId?: string;
appId: string; appId: string;
userAvatar?: string; userAvatar?: string;
title: string; title?: string;
variables: Record<string, any>; variables: Record<string, any>;
history: ChatItemType[]; history: ChatItemType[];
app: { app: {
......
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { InitChatResponse } from './api'; import { InitChatResponse } from './api';
import { i18nT } from '@fastgpt/web/i18n/utils';
export const defaultChatData: InitChatResponse = { export const defaultChatData: InitChatResponse = {
chatId: '', chatId: '',
appId: '', appId: '',
...@@ -12,7 +12,7 @@ export const defaultChatData: InitChatResponse = { ...@@ -12,7 +12,7 @@ export const defaultChatData: InitChatResponse = {
type: AppTypeEnum.simple, type: AppTypeEnum.simple,
pluginInputs: [] pluginInputs: []
}, },
title: i18nT('chat:new_chat'), title: '',
variables: {}, variables: {},
history: [] history: []
}; };
import { authChatCrud } from '@/service/support/permission/auth/chat'; import { authChatCrud } from '@/service/support/permission/auth/chat';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import {
ManagePermissionVal,
ReadPermissionVal
} from '@fastgpt/global/support/permission/constant';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema'; import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type'; import { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type';
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
export type getResDataQuery = OutLinkChatAuthProps & { export type getResDataQuery = OutLinkChatAuthProps & {
chatId?: string; chatId?: string;
...@@ -25,12 +29,24 @@ async function handler( ...@@ -25,12 +29,24 @@ async function handler(
if (!appId || !chatId || !dataId) { if (!appId || !chatId || !dataId) {
return {}; return {};
} }
// 1. Un login api: share chat, team chat
// 2. Login api: account chat, chat log
try {
await authChatCrud({ await authChatCrud({
req, req,
authToken: true, authToken: true,
...req.query, ...req.query,
per: ReadPermissionVal per: ReadPermissionVal
}); });
} catch (error) {
await authApp({
req,
authToken: true,
appId,
per: ManagePermissionVal
});
}
const chatData = await MongoChatItem.findOne({ const chatData = await MongoChatItem.findOne({
appId, appId,
......
...@@ -14,7 +14,7 @@ import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; ...@@ -14,7 +14,7 @@ import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { transformPreviewHistories } from '@/global/core/chat/utils'; import { transformPreviewHistories } from '@/global/core/chat/utils';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { i18nT } from '@fastgpt/web/i18n/utils';
async function handler( async function handler(
req: NextApiRequest, req: NextApiRequest,
res: NextApiResponse res: NextApiResponse
...@@ -62,7 +62,7 @@ async function handler( ...@@ -62,7 +62,7 @@ async function handler(
return { return {
chatId, chatId,
appId, appId,
title: chat?.title || i18nT('chat:new_chat'), title: chat?.title,
userAvatar: undefined, userAvatar: undefined,
variables: chat?.variables || {}, variables: chat?.variables || {},
history: app.type === AppTypeEnum.plugin ? histories : transformPreviewHistories(histories), history: app.type === AppTypeEnum.plugin ? histories : transformPreviewHistories(histories),
......
...@@ -18,11 +18,9 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/controller'; ...@@ -18,11 +18,9 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { transformPreviewHistories } from '@/global/core/chat/utils'; import { transformPreviewHistories } from '@/global/core/chat/utils';
import { i18nT } from '@fastgpt/web/i18n/utils'; import { NextAPI } from '@/service/middleware/entry';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
async function handler(req: NextApiRequest, res: NextApiResponse) {
let { chatId, shareId, outLinkUid } = req.query as InitOutLinkChatProps; let { chatId, shareId, outLinkUid } = req.query as InitOutLinkChatProps;
// auth link permission // auth link permission
...@@ -70,7 +68,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) ...@@ -70,7 +68,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
data: { data: {
chatId, chatId,
appId: app._id, appId: app._id,
title: chat?.title || i18nT('chat:new_chat'), title: chat?.title,
//@ts-ignore //@ts-ignore
userAvatar: tmb?.userId?.avatar, userAvatar: tmb?.userId?.avatar,
variables: chat?.variables || {}, variables: chat?.variables || {},
...@@ -94,14 +92,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) ...@@ -94,14 +92,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
} }
} }
}); });
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
} }
export default NextAPI(handler);
export const config = { export const config = {
api: { api: {
responseLimit: '10mb' responseLimit: '10mb'
......
...@@ -18,12 +18,9 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/controller'; ...@@ -18,12 +18,9 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { transformPreviewHistories } from '@/global/core/chat/utils'; import { transformPreviewHistories } from '@/global/core/chat/utils';
import { i18nT } from '@fastgpt/web/i18n/utils'; import { NextAPI } from '@/service/middleware/entry';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
async function handler(req: NextApiRequest, res: NextApiResponse) {
let { teamId, appId, chatId, teamToken } = req.query as InitTeamChatProps; let { teamId, appId, chatId, teamToken } = req.query as InitTeamChatProps;
if (!teamId || !appId || !teamToken) { if (!teamId || !appId || !teamToken) {
...@@ -73,7 +70,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) ...@@ -73,7 +70,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
data: { data: {
chatId, chatId,
appId, appId,
title: chat?.title || i18nT('chat:new_chat'), title: chat?.title,
userAvatar: team?.avatar, userAvatar: team?.avatar,
variables: chat?.variables || {}, variables: chat?.variables || {},
history: app.type === AppTypeEnum.plugin ? histories : transformPreviewHistories(histories), history: app.type === AppTypeEnum.plugin ? histories : transformPreviewHistories(histories),
...@@ -96,14 +93,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) ...@@ -96,14 +93,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
} }
} }
}); });
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
} }
export default NextAPI(handler);
export const config = { export const config = {
api: { api: {
responseLimit: '10mb' responseLimit: '10mb'
......
...@@ -18,7 +18,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) { ...@@ -18,7 +18,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
datasetId: string; datasetId: string;
}; };
if (!datasetId || !global.pgClient) { if (!datasetId) {
return Promise.reject(CommonErrEnum.missingParams); return Promise.reject(CommonErrEnum.missingParams);
} }
......
...@@ -89,7 +89,7 @@ function HelperLinesRenderer({ horizontal, vertical }: HelperLinesProps) { ...@@ -89,7 +89,7 @@ function HelperLinesRenderer({ horizontal, vertical }: HelperLinesProps) {
drawCross(node.right * transform[2] + transform[0], y, 5 * zoom); drawCross(node.right * transform[2] + transform[0], y, 5 * zoom);
}); });
} }
}, [width, height, transform, horizontal, vertical]); }, [width, height, transform, horizontal, vertical, zoom]);
return <canvas ref={canvasRef} style={canvasStyle} />; return <canvas ref={canvasRef} style={canvasStyle} />;
} }
......
...@@ -64,8 +64,7 @@ const edgeTypes = { ...@@ -64,8 +64,7 @@ const edgeTypes = {
}; };
const Workflow = () => { const Workflow = () => {
const { nodes, edges, reactFlowWrapper, helperLineHorizontal, helperLineVertical } = const { nodes, edges, reactFlowWrapper } = useContextSelector(WorkflowContext, (v) => v);
useContextSelector(WorkflowContext, (v) => v);
const { const {
ConfirmDeleteModal, ConfirmDeleteModal,
...@@ -75,7 +74,9 @@ const Workflow = () => { ...@@ -75,7 +74,9 @@ const Workflow = () => {
onConnectEnd, onConnectEnd,
customOnConnect, customOnConnect,
onEdgeMouseEnter, onEdgeMouseEnter,
onEdgeMouseLeave onEdgeMouseLeave,
helperLineHorizontal,
helperLineVertical
} = useWorkflow(); } = useWorkflow();
const { const {
...@@ -85,7 +86,7 @@ const Workflow = () => { ...@@ -85,7 +86,7 @@ const Workflow = () => {
} = useDisclosure(); } = useDisclosure();
return ( return (
<ReactFlowProvider> <>
<Box <Box
flex={'1 0 0'} flex={'1 0 0'}
h={0} h={0}
...@@ -143,11 +144,19 @@ const Workflow = () => { ...@@ -143,11 +144,19 @@ const Workflow = () => {
</Box> </Box>
<ConfirmDeleteModal /> <ConfirmDeleteModal />
</>
);
};
const Render = () => {
return (
<ReactFlowProvider>
<Workflow />
</ReactFlowProvider> </ReactFlowProvider>
); );
}; };
export default React.memo(Workflow); export default React.memo(Render);
const FlowController = React.memo(function FlowController() { const FlowController = React.memo(function FlowController() {
const { fitView } = useReactFlow(); const { fitView } = useReactFlow();
......
...@@ -48,7 +48,6 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; ...@@ -48,7 +48,6 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { formatTime2HM, formatTime2YMDHMW } from '@fastgpt/global/common/string/time'; import { formatTime2HM, formatTime2YMDHMW } from '@fastgpt/global/common/string/time';
import type { InitProps } from '@/pages/app/detail/components/PublishHistoriesSlider'; import type { InitProps } from '@/pages/app/detail/components/PublishHistoriesSlider';
import { cloneDeep } from 'lodash'; import { cloneDeep } from 'lodash';
import { THelperLine } from '@fastgpt/global/core/workflow/type';
type OnChange<ChangesType> = (changes: ChangesType[]) => void; type OnChange<ChangesType> = (changes: ChangesType[]) => void;
...@@ -136,12 +135,6 @@ type WorkflowContextType = { ...@@ -136,12 +135,6 @@ type WorkflowContextType = {
historiesDefaultData?: InitProps; historiesDefaultData?: InitProps;
setHistoriesDefaultData: React.Dispatch<React.SetStateAction<undefined | InitProps>>; setHistoriesDefaultData: React.Dispatch<React.SetStateAction<undefined | InitProps>>;
// helper line
helperLineHorizontal?: THelperLine;
setHelperLineHorizontal: React.Dispatch<React.SetStateAction<THelperLine | undefined>>;
helperLineVertical?: THelperLine;
setHelperLineVertical: React.Dispatch<React.SetStateAction<THelperLine | undefined>>;
// chat test // chat test
setWorkflowTestData: React.Dispatch< setWorkflowTestData: React.Dispatch<
React.SetStateAction< React.SetStateAction<
...@@ -267,14 +260,6 @@ export const WorkflowContext = createContext<WorkflowContextType>({ ...@@ -267,14 +260,6 @@ export const WorkflowContext = createContext<WorkflowContextType>({
setHistoriesDefaultData: function (value: React.SetStateAction<InitProps | undefined>): void { setHistoriesDefaultData: function (value: React.SetStateAction<InitProps | undefined>): void {
throw new Error('Function not implemented.'); throw new Error('Function not implemented.');
}, },
helperLineHorizontal: undefined,
setHelperLineHorizontal: function (value: React.SetStateAction<THelperLine | undefined>): void {
throw new Error('Function not implemented.');
},
helperLineVertical: undefined,
setHelperLineVertical: function (value: React.SetStateAction<THelperLine | undefined>): void {
throw new Error('Function not implemented.');
},
getNodeDynamicInputs: function (nodeId: string): FlowNodeInputItemType[] { getNodeDynamicInputs: function (nodeId: string): FlowNodeInputItemType[] {
throw new Error('Function not implemented.'); throw new Error('Function not implemented.');
} }
...@@ -742,11 +727,6 @@ const WorkflowContextProvider = ({ ...@@ -742,11 +727,6 @@ const WorkflowContextProvider = ({
/* Version histories */ /* Version histories */
const [historiesDefaultData, setHistoriesDefaultData] = useState<InitProps>(); const [historiesDefaultData, setHistoriesDefaultData] = useState<InitProps>();
/* helper line */
const [helperLineHorizontal, setHelperLineHorizontal] = useState<THelperLine | undefined>(
undefined
);
const [helperLineVertical, setHelperLineVertical] = useState<THelperLine | undefined>(undefined);
/* event bus */ /* event bus */
useEffect(() => { useEffect(() => {
eventBus.on(EventNameEnum.requestWorkflowStore, () => { eventBus.on(EventNameEnum.requestWorkflowStore, () => {
...@@ -816,12 +796,6 @@ const WorkflowContextProvider = ({ ...@@ -816,12 +796,6 @@ const WorkflowContextProvider = ({
historiesDefaultData, historiesDefaultData,
setHistoriesDefaultData, setHistoriesDefaultData,
// helper line
helperLineHorizontal,
setHelperLineHorizontal,
helperLineVertical,
setHelperLineVertical,
// chat test // chat test
setWorkflowTestData setWorkflowTestData
}; };
......
...@@ -36,6 +36,7 @@ const ChatHeader = ({ ...@@ -36,6 +36,7 @@ const ChatHeader = ({
apps?: AppListItemType[]; apps?: AppListItemType[];
onRouteToAppDetail?: () => void; onRouteToAppDetail?: () => void;
}) => { }) => {
const { t } = useTranslation();
const isPlugin = chatData.app.type === AppTypeEnum.plugin; const isPlugin = chatData.app.type === AppTypeEnum.plugin;
const { isPc } = useSystem(); const { isPc } = useSystem();
...@@ -50,7 +51,11 @@ const ChatHeader = ({ ...@@ -50,7 +51,11 @@ const ChatHeader = ({
> >
{isPc ? ( {isPc ? (
<> <>
<PcHeader title={chatData.title} chatModels={chatData.app.chatModels} history={history} /> <PcHeader
title={chatData.title || t('chat:new_chat')}
chatModels={chatData.app.chatModels}
history={history}
/>
<Box flex={1} /> <Box flex={1} />
</> </>
) : ( ) : (
......
...@@ -81,7 +81,7 @@ export async function authChatCrud({ ...@@ -81,7 +81,7 @@ export async function authChatCrud({
if (permission.isOwner) return { uid: outLinkUid }; if (permission.isOwner) return { uid: outLinkUid };
if (String(tmbId) === String(chat.tmbId)) return { uid: outLinkUid }; if (String(tmbId) === String(chat.tmbId)) return { uid: outLinkUid };
// admin // Admin can manage all chat
if (per === WritePermissionVal && permission.hasManagePer) return { uid: outLinkUid }; if (per === WritePermissionVal && permission.hasManagePer) return { uid: outLinkUid };
return Promise.reject(ChatErrEnum.unAuthChat); return Promise.reject(ChatErrEnum.unAuthChat);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment