From 377c0fb4fa98f9274dc793a8ea18ea01ed1262b6 Mon Sep 17 00:00:00 2001 From: balibabu Date: Tue, 11 Nov 2025 15:21:08 +0800 Subject: [PATCH] Feat: Call the interface to stop the output of the large model #10997 (#11164) ### What problem does this PR solve? Feat: Call the interface to stop the output of the large model #10997 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/hooks/use-agent-request.ts | 18 ++++++++++ web/src/locales/zh.ts | 1 - web/src/pages/agent/canvas/index.tsx | 8 ++++- .../agent/chat/use-send-agent-message.ts | 15 ++++++-- .../pages/agent/hooks/use-cache-chat-log.ts | 5 +++ web/src/pages/agent/hooks/use-stop-message.ts | 36 +++++++++++++++++++ web/src/services/agent-service.ts | 5 +++ web/src/utils/api.ts | 1 + 8 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 web/src/pages/agent/hooks/use-stop-message.ts diff --git a/web/src/hooks/use-agent-request.ts b/web/src/hooks/use-agent-request.ts index 6b9673b44..4f8d8c538 100644 --- a/web/src/hooks/use-agent-request.ts +++ b/web/src/hooks/use-agent-request.ts @@ -54,6 +54,7 @@ export const enum AgentApiAction { SetAgentSetting = 'setAgentSetting', FetchPrompt = 'fetchPrompt', CancelDataflow = 'cancelDataflow', + CancelCanvas = 'cancelCanvas', } export const EmptyDsl = { @@ -734,3 +735,20 @@ export const useCancelDataflow = () => { // return { list: data, loading }; // }; + +export function useCancelConversation() { + const { + data, + isPending: loading, + mutateAsync, + } = useMutation({ + mutationKey: [AgentApiAction.CancelCanvas], + mutationFn: async (taskId: string) => { + const ret = await agentService.cancelCanvas(taskId); + + return ret?.data?.code; + }, + }); + + return { data, loading, cancelConversation: mutateAsync }; +} diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index c7d21477d..4ba1f9623 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -674,7 +674,6 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于 chatSetting: '聊天设置', avatarHidden: '隐藏头像', locale: '地区', - tocEnhance: '目录增强', tocEnhanceTip: `解析文档时生成了目录信息(见General方法的‘启用目录抽取’),让大模型返回和用户问题相关的目录项,从而利用目录项拿到相关chunk,对这些chunk在排序中进行加权。这种方法来源于模仿人类查询书本中知识的行为逻辑`, }, setting: { diff --git a/web/src/pages/agent/canvas/index.tsx b/web/src/pages/agent/canvas/index.tsx index 7a25771e9..5f78e8185 100644 --- a/web/src/pages/agent/canvas/index.tsx +++ b/web/src/pages/agent/canvas/index.tsx @@ -45,6 +45,7 @@ import { useShowDrawer, useShowLogSheet, } from '../hooks/use-show-drawer'; +import { useStopMessageUnmount } from '../hooks/use-stop-message'; import { LogSheet } from '../log-sheet'; import RunSheet from '../run-sheet'; import { ButtonEdge } from './edge'; @@ -154,8 +155,11 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { currentEventListWithoutMessageById, clearEventList, currentMessageId, + currentTaskId, } = useCacheChatLog(); + const { stopMessage } = useStopMessageUnmount(chatVisible, currentTaskId); + const { showLogSheet, logSheetVisible, hideLogSheet } = useShowLogSheet({ setCurrentMessageId, }); @@ -171,9 +175,11 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { useEffect(() => { if (!chatVisible) { + stopMessage(currentTaskId); clearEventList(); } - }, [chatVisible, clearEventList]); + }, [chatVisible, clearEventList, currentTaskId, stopMessage]); + const setLastSendLoadingFunc = (loading: boolean, messageId: string) => { if (messageId === currentMessageId) { setLastSendLoading(loading); diff --git a/web/src/pages/agent/chat/use-send-agent-message.ts b/web/src/pages/agent/chat/use-send-agent-message.ts index c822819f6..a0460fd71 100644 --- a/web/src/pages/agent/chat/use-send-agent-message.ts +++ b/web/src/pages/agent/chat/use-send-agent-message.ts @@ -35,6 +35,7 @@ import { useIsTaskMode, useSelectBeginNodeDataInputs, } from '../hooks/use-get-begin-query'; +import { useStopMessage } from '../hooks/use-stop-message'; import { BeginQuery } from '../interface'; import useGraphStore from '../store'; import { receiveMessageError } from '../utils'; @@ -243,6 +244,14 @@ export const useSendAgentMessage = ({ fileList, } = useSetUploadResponseData(); + const { stopMessage } = useStopMessage(); + + const stopConversation = useCallback(() => { + const taskId = answerList.at(0)?.task_id; + stopOutputMessage(); + stopMessage(taskId); + }, [answerList, stopMessage, stopOutputMessage]); + const sendMessage = useCallback( async ({ message, @@ -321,7 +330,7 @@ export const useSendAgentMessage = ({ // reset session const resetSession = useCallback(() => { - stopOutputMessage(); + stopConversation(); resetAnswerList(); setSessionId(null); if (isTaskMode) { @@ -330,7 +339,7 @@ export const useSendAgentMessage = ({ removeAllMessagesExceptFirst(); } }, [ - stopOutputMessage, + stopConversation, resetAnswerList, isTaskMode, removeAllMessages, @@ -432,7 +441,7 @@ export const useSendAgentMessage = ({ handlePressEnter, handleInputChange, removeMessageById, - stopOutputMessage, + stopOutputMessage: stopConversation, send, sendFormMessage, resetSession, diff --git a/web/src/pages/agent/hooks/use-cache-chat-log.ts b/web/src/pages/agent/hooks/use-cache-chat-log.ts index c61079003..7e67cdd0b 100644 --- a/web/src/pages/agent/hooks/use-cache-chat-log.ts +++ b/web/src/pages/agent/hooks/use-cache-chat-log.ts @@ -73,6 +73,10 @@ export function useCacheChatLog() { [messageIdPool], ); + const currentTaskId = useMemo(() => { + return eventList.at(-1)?.task_id; + }, [eventList]); + return { eventList, currentEventListWithoutMessage, @@ -84,5 +88,6 @@ export function useCacheChatLog() { filterEventListByMessageId, setCurrentMessageId, currentMessageId, + currentTaskId, }; } diff --git a/web/src/pages/agent/hooks/use-stop-message.ts b/web/src/pages/agent/hooks/use-stop-message.ts new file mode 100644 index 000000000..1696599cf --- /dev/null +++ b/web/src/pages/agent/hooks/use-stop-message.ts @@ -0,0 +1,36 @@ +import { useCancelConversation } from '@/hooks/use-agent-request'; +import { useCallback, useEffect } from 'react'; + +export function useStopMessage() { + const { cancelConversation } = useCancelConversation(); + + const stopMessage = useCallback( + (taskId?: string) => { + if (taskId) { + cancelConversation(taskId); + } + }, + [cancelConversation], + ); + + return { stopMessage }; +} + +export function useStopMessageUnmount(chatVisible: boolean, taskId?: string) { + const { stopMessage } = useStopMessage(); + + const handleBeforeUnload = useCallback(() => { + if (chatVisible) { + stopMessage(taskId); + } + }, [chatVisible, stopMessage, taskId]); + + useEffect(() => { + window.addEventListener('beforeunload', handleBeforeUnload); + return () => { + window.removeEventListener('beforeunload', handleBeforeUnload); + }; + }, [handleBeforeUnload]); + + return { stopMessage }; +} diff --git a/web/src/services/agent-service.ts b/web/src/services/agent-service.ts index 9fe7de1fc..2e95d4d1a 100644 --- a/web/src/services/agent-service.ts +++ b/web/src/services/agent-service.ts @@ -29,6 +29,7 @@ const { fetchExternalAgentInputs, prompt, cancelDataflow, + cancelCanvas, } = api; const methods = { @@ -120,6 +121,10 @@ const methods = { url: cancelDataflow, method: 'put', }, + cancelCanvas: { + url: cancelCanvas, + method: 'put', + }, } as const; const agentService = registerNextServer(methods); diff --git a/web/src/utils/api.ts b/web/src/utils/api.ts index 816777f50..2e93d1010 100644 --- a/web/src/utils/api.ts +++ b/web/src/utils/api.ts @@ -174,6 +174,7 @@ export default { debug: `${api_host}/canvas/debug`, uploadCanvasFile: `${api_host}/canvas/upload`, trace: `${api_host}/canvas/trace`, + cancelCanvas: (taskId: string) => `${api_host}/canvas/cancel/${taskId}`, // cancel conversation // agent inputForm: `${api_host}/canvas/input_form`, fetchVersionList: (id: string) => `${api_host}/canvas/getlistversion/${id}`,