mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 15:00:57 +03:00
Feature/Buffer Memory SessionId (#2111)
* add sessionId to buffer memory, add conversation summary buffer memory * add fix for conv retrieval qa chain
This commit is contained in:
@@ -195,7 +195,6 @@ export interface IMessage {
|
||||
|
||||
export interface IncomingInput {
|
||||
question: string
|
||||
history: IMessage[]
|
||||
overrideConfig?: ICommonObject
|
||||
socketIOClientId?: string
|
||||
chatId?: string
|
||||
|
||||
@@ -132,7 +132,6 @@ export const utilBuildChatflow = async (req: Request, socketIO?: Server, isInter
|
||||
incomingInput = {
|
||||
question: req.body.question ?? 'hello',
|
||||
overrideConfig,
|
||||
history: [],
|
||||
socketIOClientId: req.body.socketIOClientId
|
||||
}
|
||||
}
|
||||
@@ -146,8 +145,7 @@ export const utilBuildChatflow = async (req: Request, socketIO?: Server, isInter
|
||||
// Get session ID
|
||||
const memoryNode = findMemoryNode(nodes, edges)
|
||||
const memoryType = memoryNode?.data.label
|
||||
let sessionId = undefined
|
||||
if (memoryNode) sessionId = getMemorySessionId(memoryNode, incomingInput, chatId, isInternal)
|
||||
let sessionId = getMemorySessionId(memoryNode, incomingInput, chatId, isInternal)
|
||||
|
||||
/* Reuse the flow without having to rebuild (to avoid duplicated upsert, recomputation, reinitialization of memory) when all these conditions met:
|
||||
* - Node Data already exists in pool
|
||||
@@ -225,9 +223,9 @@ export const utilBuildChatflow = async (req: Request, socketIO?: Server, isInter
|
||||
// Once custom function ending node exists, flow is always unavailable to stream
|
||||
isStreamValid = isEndingNodeExists ? false : isStreamValid
|
||||
|
||||
let chatHistory: IMessage[] = incomingInput.history ?? []
|
||||
let chatHistory: IMessage[] = []
|
||||
|
||||
// When {{chat_history}} is used in Prompt Template, fetch the chat conversations from memory node
|
||||
// When {{chat_history}} is used in Format Prompt Value, fetch the chat conversations from memory node
|
||||
for (const endingNode of endingNodes) {
|
||||
const endingNodeData = endingNode.data
|
||||
|
||||
@@ -238,16 +236,15 @@ export const utilBuildChatflow = async (req: Request, socketIO?: Server, isInter
|
||||
|
||||
if (!memoryNode) continue
|
||||
|
||||
if (!chatHistory.length && (incomingInput.chatId || incomingInput.overrideConfig?.sessionId)) {
|
||||
chatHistory = await getSessionChatHistory(
|
||||
memoryNode,
|
||||
appServer.nodesPool.componentNodes,
|
||||
incomingInput,
|
||||
appServer.AppDataSource,
|
||||
databaseEntities,
|
||||
logger
|
||||
)
|
||||
}
|
||||
chatHistory = await getSessionChatHistory(
|
||||
chatflowid,
|
||||
getMemorySessionId(memoryNode, incomingInput, chatId, isInternal),
|
||||
memoryNode,
|
||||
appServer.nodesPool.componentNodes,
|
||||
appServer.AppDataSource,
|
||||
databaseEntities,
|
||||
logger
|
||||
)
|
||||
}
|
||||
|
||||
/*** Get Starting Nodes with Reversed Graph ***/
|
||||
@@ -314,7 +311,6 @@ export const utilBuildChatflow = async (req: Request, socketIO?: Server, isInter
|
||||
? await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
|
||||
chatId,
|
||||
chatflowid,
|
||||
chatHistory: incomingInput.history,
|
||||
logger,
|
||||
appDataSource: appServer.AppDataSource,
|
||||
databaseEntities,
|
||||
@@ -326,7 +322,6 @@ export const utilBuildChatflow = async (req: Request, socketIO?: Server, isInter
|
||||
: await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
|
||||
chatId,
|
||||
chatflowid,
|
||||
chatHistory: incomingInput.history,
|
||||
logger,
|
||||
appDataSource: appServer.AppDataSource,
|
||||
databaseEntities,
|
||||
|
||||
@@ -1144,16 +1144,18 @@ export const redactCredentialWithPasswordType = (
|
||||
* API/Embed + UI:
|
||||
* (3) Hard-coded sessionId in UI
|
||||
* (4) Not specified on UI nor API, default to chatId
|
||||
* @param {any} instance
|
||||
* @param {IReactFlowNode | undefined} memoryNode
|
||||
* @param {IncomingInput} incomingInput
|
||||
* @param {string} chatId
|
||||
* @param {boolean} isInternal
|
||||
* @returns {string}
|
||||
*/
|
||||
export const getMemorySessionId = (
|
||||
memoryNode: IReactFlowNode,
|
||||
memoryNode: IReactFlowNode | undefined,
|
||||
incomingInput: IncomingInput,
|
||||
chatId: string,
|
||||
isInternal: boolean
|
||||
): string | undefined => {
|
||||
): string => {
|
||||
if (!isInternal) {
|
||||
// Provided in API body - incomingInput.overrideConfig: { sessionId: 'abc' }
|
||||
if (incomingInput.overrideConfig?.sessionId) {
|
||||
@@ -1166,7 +1168,7 @@ export const getMemorySessionId = (
|
||||
}
|
||||
|
||||
// Hard-coded sessionId in UI
|
||||
if (memoryNode.data.inputs?.sessionId) {
|
||||
if (memoryNode && memoryNode.data.inputs?.sessionId) {
|
||||
return memoryNode.data.inputs.sessionId
|
||||
}
|
||||
|
||||
@@ -1175,18 +1177,21 @@ export const getMemorySessionId = (
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace chatHistory if incomingInput.history is empty and sessionId/chatId is provided
|
||||
* Get chat messages from sessionId
|
||||
* @param {IReactFlowNode} memoryNode
|
||||
* @param {IncomingInput} incomingInput
|
||||
* @param {string} sessionId
|
||||
* @param {IReactFlowNode} memoryNode
|
||||
* @param {IComponentNodes} componentNodes
|
||||
* @param {DataSource} appDataSource
|
||||
* @param {IDatabaseEntity} databaseEntities
|
||||
* @param {any} logger
|
||||
* @returns {string}
|
||||
* @returns {IMessage[]}
|
||||
*/
|
||||
export const getSessionChatHistory = async (
|
||||
chatflowid: string,
|
||||
sessionId: string,
|
||||
memoryNode: IReactFlowNode,
|
||||
componentNodes: IComponentNodes,
|
||||
incomingInput: IncomingInput,
|
||||
appDataSource: DataSource,
|
||||
databaseEntities: IDatabaseEntity,
|
||||
logger: any
|
||||
@@ -1196,19 +1201,18 @@ export const getSessionChatHistory = async (
|
||||
const newNodeInstance = new nodeModule.nodeClass()
|
||||
|
||||
// Replace memory's sessionId/chatId
|
||||
if (incomingInput.overrideConfig?.sessionId && memoryNode.data.inputs) {
|
||||
memoryNode.data.inputs.sessionId = incomingInput.overrideConfig.sessionId
|
||||
} else if (incomingInput.chatId && memoryNode.data.inputs) {
|
||||
memoryNode.data.inputs.sessionId = incomingInput.chatId
|
||||
if (memoryNode.data.inputs) {
|
||||
memoryNode.data.inputs.sessionId = sessionId
|
||||
}
|
||||
|
||||
const initializedInstance: FlowiseMemory = await newNodeInstance.init(memoryNode.data, '', {
|
||||
chatflowid,
|
||||
appDataSource,
|
||||
databaseEntities,
|
||||
logger
|
||||
})
|
||||
|
||||
return (await initializedInstance.getChatMessages()) as IMessage[]
|
||||
return (await initializedInstance.getChatMessages(sessionId)) as IMessage[]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1216,7 +1220,7 @@ export const getSessionChatHistory = async (
|
||||
* In a chatflow, there should only be 1 memory node
|
||||
* @param {IReactFlowNode[]} nodes
|
||||
* @param {IReactFlowEdge[]} edges
|
||||
* @returns {string | undefined}
|
||||
* @returns {IReactFlowNode | undefined}
|
||||
*/
|
||||
export const findMemoryNode = (nodes: IReactFlowNode[], edges: IReactFlowEdge[]): IReactFlowNode | undefined => {
|
||||
const memoryNodes = nodes.filter((node) => node.data.category === 'Memory')
|
||||
@@ -1228,6 +1232,7 @@ export const findMemoryNode = (nodes: IReactFlowNode[], edges: IReactFlowEdge[])
|
||||
return memoryNode
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Request } from 'express'
|
||||
import * as fs from 'fs'
|
||||
import { cloneDeep, omit } from 'lodash'
|
||||
import { ICommonObject } from 'flowise-components'
|
||||
import { ICommonObject, IMessage } from 'flowise-components'
|
||||
import telemetryService from '../services/telemetry'
|
||||
import logger from '../utils/logger'
|
||||
import {
|
||||
@@ -66,7 +66,6 @@ export const upsertVector = async (req: Request, isInternal: boolean = false) =>
|
||||
incomingInput = {
|
||||
question: req.body.question ?? 'hello',
|
||||
overrideConfig,
|
||||
history: [],
|
||||
stopNodeId: req.body.stopNodeId
|
||||
}
|
||||
}
|
||||
@@ -78,14 +77,13 @@ export const upsertVector = async (req: Request, isInternal: boolean = false) =>
|
||||
const edges = parsedFlowData.edges
|
||||
|
||||
let stopNodeId = incomingInput?.stopNodeId ?? ''
|
||||
let chatHistory = incomingInput?.history
|
||||
let chatHistory: IMessage[] = []
|
||||
let chatId = incomingInput.chatId ?? ''
|
||||
let isUpsert = true
|
||||
|
||||
// Get session ID
|
||||
const memoryNode = findMemoryNode(nodes, edges)
|
||||
let sessionId = undefined
|
||||
if (memoryNode) sessionId = getMemorySessionId(memoryNode, incomingInput, chatId, isInternal)
|
||||
let sessionId = getMemorySessionId(memoryNode, incomingInput, chatId, isInternal)
|
||||
|
||||
const vsNodes = nodes.filter(
|
||||
(node) =>
|
||||
|
||||
Reference in New Issue
Block a user