Unverified Commit b16a7b0b authored by Joel's avatar Joel Committed by GitHub

feat: stop response call api (#340)

parent e083a706
...@@ -53,6 +53,7 @@ export type IChatProps = { ...@@ -53,6 +53,7 @@ export type IChatProps = {
displayScene?: DisplayScene displayScene?: DisplayScene
useCurrentUserAvatar?: boolean useCurrentUserAvatar?: boolean
isResponsing?: boolean isResponsing?: boolean
canStopResponsing?: boolean
abortResponsing?: () => void abortResponsing?: () => void
controlClearQuery?: number controlClearQuery?: number
controlFocus?: number controlFocus?: number
...@@ -412,6 +413,7 @@ const Chat: FC<IChatProps> = ({ ...@@ -412,6 +413,7 @@ const Chat: FC<IChatProps> = ({
displayScene, displayScene,
useCurrentUserAvatar, useCurrentUserAvatar,
isResponsing, isResponsing,
canStopResponsing,
abortResponsing, abortResponsing,
controlClearQuery, controlClearQuery,
controlFocus, controlFocus,
...@@ -508,7 +510,7 @@ const Chat: FC<IChatProps> = ({ ...@@ -508,7 +510,7 @@ const Chat: FC<IChatProps> = ({
{ {
!isHideSendInput && ( !isHideSendInput && (
<div className={cn(!feedbackDisabled && '!left-3.5 !right-3.5', 'absolute z-10 bottom-0 left-0 right-0')}> <div className={cn(!feedbackDisabled && '!left-3.5 !right-3.5', 'absolute z-10 bottom-0 left-0 right-0')}>
{isResponsing && ( {(isResponsing && canStopResponsing) && (
<div className='flex justify-center mb-4'> <div className='flex justify-center mb-4'>
<Button className='flex items-center space-x-1 bg-white' onClick={() => abortResponsing?.()}> <Button className='flex items-center space-x-1 bg-white' onClick={() => abortResponsing?.()}>
{stopIcon} {stopIcon}
......
...@@ -16,7 +16,7 @@ import type { IChatItem } from '@/app/components/app/chat' ...@@ -16,7 +16,7 @@ import type { IChatItem } from '@/app/components/app/chat'
import Chat from '@/app/components/app/chat' import Chat from '@/app/components/app/chat'
import ConfigContext from '@/context/debug-configuration' import ConfigContext from '@/context/debug-configuration'
import { ToastContext } from '@/app/components/base/toast' import { ToastContext } from '@/app/components/base/toast'
import { fetchConvesationMessages, fetchSuggestedQuestions, sendChatMessage, sendCompletionMessage } from '@/service/debug' import { fetchConvesationMessages, fetchSuggestedQuestions, sendChatMessage, sendCompletionMessage, stopChatMessageResponding } from '@/service/debug'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import type { ModelConfig as BackendModelConfig } from '@/types/app' import type { ModelConfig as BackendModelConfig } from '@/types/app'
import { promptVariablesToUserInputsForm } from '@/utils/model-config' import { promptVariablesToUserInputsForm } from '@/utils/model-config'
...@@ -136,6 +136,7 @@ const Debug: FC<IDebug> = ({ ...@@ -136,6 +136,7 @@ const Debug: FC<IDebug> = ({
const doShowSuggestion = isShowSuggestion && !isResponsing const doShowSuggestion = isShowSuggestion && !isResponsing
const [suggestQuestions, setSuggestQuestions] = useState<string[]>([]) const [suggestQuestions, setSuggestQuestions] = useState<string[]>([])
const [messageTaskId, setMessageTaskId] = useState('')
const onSend = async (message: string) => { const onSend = async (message: string) => {
if (isResponsing) { if (isResponsing) {
notify({ type: 'info', message: t('appDebug.errorMessage.waitForResponse') }) notify({ type: 'info', message: t('appDebug.errorMessage.waitForResponse') })
...@@ -208,12 +209,13 @@ const Debug: FC<IDebug> = ({ ...@@ -208,12 +209,13 @@ const Debug: FC<IDebug> = ({
getAbortController: (abortController) => { getAbortController: (abortController) => {
setAbortController(abortController) setAbortController(abortController)
}, },
onData: (message: string, isFirstMessage: boolean, { conversationId: newConversationId, messageId }: any) => { onData: (message: string, isFirstMessage: boolean, { conversationId: newConversationId, messageId, taskId }: any) => {
responseItem.content = responseItem.content + message responseItem.content = responseItem.content + message
if (isFirstMessage && newConversationId) { if (isFirstMessage && newConversationId) {
setConversationId(newConversationId) setConversationId(newConversationId)
_newConversationId = newConversationId _newConversationId = newConversationId
} }
setMessageTaskId(taskId)
if (messageId) if (messageId)
responseItem.id = messageId responseItem.id = messageId
...@@ -375,8 +377,10 @@ const Debug: FC<IDebug> = ({ ...@@ -375,8 +377,10 @@ const Debug: FC<IDebug> = ({
feedbackDisabled feedbackDisabled
useCurrentUserAvatar useCurrentUserAvatar
isResponsing={isResponsing} isResponsing={isResponsing}
abortResponsing={() => { canStopResponsing={!!messageTaskId}
abortResponsing={async () => {
abortController?.abort() abortController?.abort()
await stopChatMessageResponding(appId, messageTaskId)
setResponsingFalse() setResponsingFalse()
}} }}
isShowSuggestion={doShowSuggestion} isShowSuggestion={doShowSuggestion}
......
...@@ -14,7 +14,7 @@ import { ToastContext } from '@/app/components/base/toast' ...@@ -14,7 +14,7 @@ import { ToastContext } from '@/app/components/base/toast'
import Sidebar from '@/app/components/share/chat/sidebar' import Sidebar from '@/app/components/share/chat/sidebar'
import ConfigSence from '@/app/components/share/chat/config-scence' import ConfigSence from '@/app/components/share/chat/config-scence'
import Header from '@/app/components/share/header' import Header from '@/app/components/share/header'
import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, sendChatMessage, updateFeedback } from '@/service/share' import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, sendChatMessage, stopChatMessageResponding, updateFeedback } from '@/service/share'
import type { ConversationItem, SiteInfo } from '@/models/share' import type { ConversationItem, SiteInfo } from '@/models/share'
import type { PromptConfig, SuggestedQuestionsAfterAnswerConfig } from '@/models/debug' import type { PromptConfig, SuggestedQuestionsAfterAnswerConfig } from '@/models/debug'
import type { Feedbacktype, IChatItem } from '@/app/components/app/chat' import type { Feedbacktype, IChatItem } from '@/app/components/app/chat'
...@@ -332,6 +332,7 @@ const Main: FC<IMainProps> = ({ ...@@ -332,6 +332,7 @@ const Main: FC<IMainProps> = ({
const [isShowSuggestion, setIsShowSuggestion] = useState(false) const [isShowSuggestion, setIsShowSuggestion] = useState(false)
const doShowSuggestion = isShowSuggestion && !isResponsing const doShowSuggestion = isShowSuggestion && !isResponsing
const [suggestQuestions, setSuggestQuestions] = useState<string[]>([]) const [suggestQuestions, setSuggestQuestions] = useState<string[]>([])
const [messageTaskId, setMessageTaskId] = useState('')
const handleSend = async (message: string) => { const handleSend = async (message: string) => {
if (isResponsing) { if (isResponsing) {
notify({ type: 'info', message: t('appDebug.errorMessage.waitForResponse') }) notify({ type: 'info', message: t('appDebug.errorMessage.waitForResponse') })
...@@ -376,12 +377,13 @@ const Main: FC<IMainProps> = ({ ...@@ -376,12 +377,13 @@ const Main: FC<IMainProps> = ({
getAbortController: (abortController) => { getAbortController: (abortController) => {
setAbortController(abortController) setAbortController(abortController)
}, },
onData: (message: string, isFirstMessage: boolean, { conversationId: newConversationId, messageId }: any) => { onData: (message: string, isFirstMessage: boolean, { conversationId: newConversationId, messageId, taskId }: any) => {
responseItem.content = responseItem.content + message responseItem.content = responseItem.content + message
responseItem.id = messageId responseItem.id = messageId
if (isFirstMessage && newConversationId) if (isFirstMessage && newConversationId)
tempNewConversationId = newConversationId tempNewConversationId = newConversationId
setMessageTaskId(taskId)
// closesure new list is outdated. // closesure new list is outdated.
const newListWithAnswer = produce( const newListWithAnswer = produce(
getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId), getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
...@@ -532,8 +534,10 @@ const Main: FC<IMainProps> = ({ ...@@ -532,8 +534,10 @@ const Main: FC<IMainProps> = ({
isHideFeedbackEdit isHideFeedbackEdit
onFeedback={handleFeedback} onFeedback={handleFeedback}
isResponsing={isResponsing} isResponsing={isResponsing}
abortResponsing={() => { canStopResponsing={!!messageTaskId}
abortResponsing={async () => {
abortController?.abort() abortController?.abort()
await stopChatMessageResponding(appId, messageTaskId, isInstalledApp, installedAppInfo?.id)
setResponsingFalse() setResponsingFalse()
}} }}
checkCanSend={checkCanSend} checkCanSend={checkCanSend}
......
...@@ -23,7 +23,8 @@ const baseOptions = { ...@@ -23,7 +23,8 @@ const baseOptions = {
} }
export type IOnDataMoreInfo = { export type IOnDataMoreInfo = {
conversationId: string | undefined conversationId?: string
taskId?: string
messageId: string messageId: string
errorMessage?: string errorMessage?: string
} }
...@@ -101,6 +102,7 @@ const handleStream = (response: any, onData: IOnData, onCompleted?: IOnCompleted ...@@ -101,6 +102,7 @@ const handleStream = (response: any, onData: IOnData, onCompleted?: IOnCompleted
// can not use format here. Because message is splited. // can not use format here. Because message is splited.
onData(unicodeToChar(bufferObj.answer), isFirstMessage, { onData(unicodeToChar(bufferObj.answer), isFirstMessage, {
conversationId: bufferObj.conversation_id, conversationId: bufferObj.conversation_id,
taskId: bufferObj.task_id,
messageId: bufferObj.id, messageId: bufferObj.id,
}) })
isFirstMessage = false isFirstMessage = false
......
...@@ -15,6 +15,10 @@ export const sendChatMessage = async (appId: string, body: Record<string, any>, ...@@ -15,6 +15,10 @@ export const sendChatMessage = async (appId: string, body: Record<string, any>,
}, { onData, onCompleted, onError, getAbortController }) }, { onData, onCompleted, onError, getAbortController })
} }
export const stopChatMessageResponding = async (appId: string, taskId: string) => {
return post(`apps/${appId}/chat-messages/${taskId}/stop`)
}
export const sendCompletionMessage = async (appId: string, body: Record<string, any>, { onData, onCompleted, onError }: { export const sendCompletionMessage = async (appId: string, body: Record<string, any>, { onData, onCompleted, onError }: {
onData: IOnData onData: IOnData
onCompleted: IOnCompleted onCompleted: IOnCompleted
......
...@@ -34,6 +34,10 @@ export const sendChatMessage = async (body: Record<string, any>, { onData, onCom ...@@ -34,6 +34,10 @@ export const sendChatMessage = async (body: Record<string, any>, { onData, onCom
}, { onData, onCompleted, isPublicAPI: !isInstalledApp, onError, getAbortController }) }, { onData, onCompleted, isPublicAPI: !isInstalledApp, onError, getAbortController })
} }
export const stopChatMessageResponding = async (appId: string, taskId: string, isInstalledApp: boolean, installedAppId = '') => {
return getAction('post', isInstalledApp)(getUrl(`chat-messages/${taskId}/stop`, isInstalledApp, installedAppId))
}
export const sendCompletionMessage = async (body: Record<string, any>, { onData, onCompleted, onError }: { export const sendCompletionMessage = async (body: Record<string, any>, { onData, onCompleted, onError }: {
onData: IOnData onData: IOnData
onCompleted: IOnCompleted onCompleted: IOnCompleted
......
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 to comment