mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 19:00:59 +03:00
Feature/sse (#3125)
* Base changes for ServerSide Events (instead of socket.io) * lint fixes * adding of interface and separate methods for streaming events * lint * first draft, handles both internal and external prediction end points. * lint fixes * additional internal end point for streaming and associated changes * return streamresponse as true to build agent flow * 1) JSON formatting for internal events 2) other fixes * 1) convert internal event to metadata to maintain consistency with external response * fix action and metadata streaming * fix for error when agent flow is aborted * prevent subflows from streaming and other code cleanup * prevent streaming from enclosed tools * add fix for preventing chaintool streaming * update lock file * add open when hidden to sse * Streaming errors * Streaming errors * add fix for showing error message --------- Co-authored-by: Henry <hzj94@hotmail.com>
This commit is contained in:
@@ -9,9 +9,9 @@ import {
|
||||
ISeqAgentsState,
|
||||
ISeqAgentNode,
|
||||
IUsedTool,
|
||||
IDocument
|
||||
IDocument,
|
||||
IServerSideEventStreamer
|
||||
} from 'flowise-components'
|
||||
import { Server } from 'socket.io'
|
||||
import { omit, cloneDeep, flatten, uniq } from 'lodash'
|
||||
import { StateGraph, END, START } from '@langchain/langgraph'
|
||||
import { Document } from '@langchain/core/documents'
|
||||
@@ -53,7 +53,6 @@ import logger from './logger'
|
||||
* @param {ICommonObject} incomingInput
|
||||
* @param {boolean} isInternal
|
||||
* @param {string} baseURL
|
||||
* @param {Server} socketIO
|
||||
*/
|
||||
export const buildAgentGraph = async (
|
||||
chatflow: IChatFlow,
|
||||
@@ -62,7 +61,8 @@ export const buildAgentGraph = async (
|
||||
incomingInput: IncomingInput,
|
||||
isInternal: boolean,
|
||||
baseURL?: string,
|
||||
socketIO?: Server
|
||||
sseStreamer?: IServerSideEventStreamer,
|
||||
shouldStreamResponse?: boolean
|
||||
): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
@@ -287,28 +287,31 @@ export const buildAgentGraph = async (
|
||||
? output[agentName].messages[output[agentName].messages.length - 1].content
|
||||
: lastWorkerResult
|
||||
|
||||
if (socketIO && incomingInput.socketIOClientId) {
|
||||
if (shouldStreamResponse) {
|
||||
if (!isStreamingStarted) {
|
||||
isStreamingStarted = true
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('start', agentReasoning)
|
||||
if (sseStreamer) {
|
||||
sseStreamer.streamStartEvent(chatId, agentReasoning)
|
||||
}
|
||||
}
|
||||
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('agentReasoning', agentReasoning)
|
||||
if (sseStreamer) {
|
||||
sseStreamer.streamAgentReasoningEvent(chatId, agentReasoning)
|
||||
}
|
||||
|
||||
// Send loading next agent indicator
|
||||
if (reasoning.next && reasoning.next !== 'FINISH' && reasoning.next !== 'END') {
|
||||
socketIO
|
||||
.to(incomingInput.socketIOClientId)
|
||||
.emit('nextAgent', mapNameToLabel[reasoning.next].label || reasoning.next)
|
||||
if (sseStreamer) {
|
||||
sseStreamer.streamNextAgentEvent(chatId, mapNameToLabel[reasoning.next].label || reasoning.next)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
finalResult = output.__end__.messages.length ? output.__end__.messages.pop()?.content : ''
|
||||
if (Array.isArray(finalResult)) finalResult = output.__end__.instructions
|
||||
|
||||
if (socketIO && incomingInput.socketIOClientId) {
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('token', finalResult)
|
||||
if (shouldStreamResponse && sseStreamer) {
|
||||
sseStreamer.streamTokenEvent(chatId, finalResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -321,9 +324,8 @@ export const buildAgentGraph = async (
|
||||
if (!isSequential && !finalResult) {
|
||||
if (lastWorkerResult) finalResult = lastWorkerResult
|
||||
else if (finalSummarization) finalResult = finalSummarization
|
||||
|
||||
if (socketIO && incomingInput.socketIOClientId) {
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('token', finalResult)
|
||||
if (shouldStreamResponse && sseStreamer) {
|
||||
sseStreamer.streamTokenEvent(chatId, finalResult)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,16 +379,16 @@ export const buildAgentGraph = async (
|
||||
{ type: 'reject-button', label: rejectButtonText }
|
||||
]
|
||||
}
|
||||
if (socketIO && incomingInput.socketIOClientId) {
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('token', finalResult)
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('action', finalAction)
|
||||
if (shouldStreamResponse && sseStreamer) {
|
||||
sseStreamer.streamTokenEvent(chatId, finalResult)
|
||||
sseStreamer.streamActionEvent(chatId, finalAction)
|
||||
}
|
||||
}
|
||||
totalUsedTools.push(...mappedToolCalls)
|
||||
} else if (lastAgentReasoningMessage) {
|
||||
finalResult = lastAgentReasoningMessage
|
||||
if (socketIO && incomingInput.socketIOClientId) {
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('token', finalResult)
|
||||
if (shouldStreamResponse && sseStreamer) {
|
||||
sseStreamer.streamTokenEvent(chatId, finalResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,10 +396,10 @@ export const buildAgentGraph = async (
|
||||
totalSourceDocuments = uniq(flatten(totalSourceDocuments))
|
||||
totalUsedTools = uniq(flatten(totalUsedTools))
|
||||
|
||||
if (socketIO && incomingInput.socketIOClientId) {
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('usedTools', totalUsedTools)
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('sourceDocuments', totalSourceDocuments)
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('end')
|
||||
if (shouldStreamResponse && sseStreamer) {
|
||||
sseStreamer.streamUsedToolsEvent(chatId, totalUsedTools)
|
||||
sseStreamer.streamSourceDocumentsEvent(chatId, totalSourceDocuments)
|
||||
sseStreamer.streamEndEvent(chatId)
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -412,8 +414,8 @@ export const buildAgentGraph = async (
|
||||
// clear agent memory because checkpoints were saved during runtime
|
||||
await clearSessionMemory(nodes, appServer.nodesPool.componentNodes, chatId, appServer.AppDataSource, sessionId)
|
||||
if (getErrorMessage(e).includes('Aborted')) {
|
||||
if (socketIO && incomingInput.socketIOClientId) {
|
||||
socketIO.to(incomingInput.socketIOClientId).emit('abort')
|
||||
if (shouldStreamResponse && sseStreamer) {
|
||||
sseStreamer.streamAbortEvent(chatId)
|
||||
}
|
||||
return { finalResult, agentReasoning }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user