fix chat history
This commit is contained in:
parent
5a5097e997
commit
4b5f7028e3
|
|
@ -85,43 +85,46 @@ class OpenAIAssistant_Agents implements INode {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
//@ts-ignore
|
||||||
const selectedAssistantId = nodeData.inputs?.selectedAssistant as string
|
memoryMethods = {
|
||||||
const appDataSource = options.appDataSource as DataSource
|
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||||
const databaseEntities = options.databaseEntities as IDatabaseEntity
|
const selectedAssistantId = nodeData.inputs?.selectedAssistant as string
|
||||||
let sessionId = nodeData.inputs?.sessionId as string
|
const appDataSource = options.appDataSource as DataSource
|
||||||
|
const databaseEntities = options.databaseEntities as IDatabaseEntity
|
||||||
|
let sessionId = nodeData.inputs?.sessionId as string
|
||||||
|
|
||||||
const assistant = await appDataSource.getRepository(databaseEntities['Assistant']).findOneBy({
|
const assistant = await appDataSource.getRepository(databaseEntities['Assistant']).findOneBy({
|
||||||
id: selectedAssistantId
|
id: selectedAssistantId
|
||||||
})
|
|
||||||
|
|
||||||
if (!assistant) {
|
|
||||||
options.logger.error(`Assistant ${selectedAssistantId} not found`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sessionId && options.chatId) {
|
|
||||||
const chatmsg = await appDataSource.getRepository(databaseEntities['ChatMessage']).findOneBy({
|
|
||||||
chatId: options.chatId
|
|
||||||
})
|
})
|
||||||
if (!chatmsg) {
|
|
||||||
options.logger.error(`Chat Message with Chat Id: ${options.chatId} not found`)
|
if (!assistant) {
|
||||||
|
options.logger.error(`Assistant ${selectedAssistantId} not found`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sessionId = chatmsg.sessionId
|
|
||||||
}
|
|
||||||
|
|
||||||
const credentialData = await getCredentialData(assistant.credential ?? '', options)
|
if (!sessionId && options.chatId) {
|
||||||
const openAIApiKey = getCredentialParam('openAIApiKey', credentialData, nodeData)
|
const chatmsg = await appDataSource.getRepository(databaseEntities['ChatMessage']).findOneBy({
|
||||||
if (!openAIApiKey) {
|
chatId: options.chatId
|
||||||
options.logger.error(`OpenAI ApiKey not found`)
|
})
|
||||||
return
|
if (!chatmsg) {
|
||||||
}
|
options.logger.error(`Chat Message with Chat Id: ${options.chatId} not found`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sessionId = chatmsg.sessionId
|
||||||
|
}
|
||||||
|
|
||||||
const openai = new OpenAI({ apiKey: openAIApiKey })
|
const credentialData = await getCredentialData(assistant.credential ?? '', options)
|
||||||
options.logger.info(`Clearing OpenAI Thread ${sessionId}`)
|
const openAIApiKey = getCredentialParam('openAIApiKey', credentialData, nodeData)
|
||||||
if (sessionId) await openai.beta.threads.del(sessionId)
|
if (!openAIApiKey) {
|
||||||
options.logger.info(`Successfully cleared OpenAI Thread ${sessionId}`)
|
options.logger.error(`OpenAI ApiKey not found`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const openai = new OpenAI({ apiKey: openAIApiKey })
|
||||||
|
options.logger.info(`Clearing OpenAI Thread ${sessionId}`)
|
||||||
|
if (sessionId) await openai.beta.threads.del(sessionId)
|
||||||
|
options.logger.info(`Successfully cleared OpenAI Thread ${sessionId}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async run(nodeData: INodeData, input: string, options: ICommonObject): Promise<string | object> {
|
async run(nodeData: INodeData, input: string, options: ICommonObject): Promise<string | object> {
|
||||||
|
|
@ -359,7 +362,10 @@ class OpenAIAssistant_Agents implements INode {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the text with a footnote
|
// Replace the text with a footnote
|
||||||
message_content.value = message_content.value.replace(`${annotation.text}`, `${filePath}`)
|
message_content.value = message_content.value.replace(
|
||||||
|
`${annotation.text}`,
|
||||||
|
`${disableFileDownload ? '' : filePath}`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
returnVal += message_content.value
|
returnVal += message_content.value
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,13 @@
|
||||||
import { ICommonObject, INode, INodeData, INodeParams, getBaseClasses, getCredentialData, getCredentialParam } from '../../../src'
|
import {
|
||||||
|
ICommonObject,
|
||||||
|
INode,
|
||||||
|
INodeData,
|
||||||
|
INodeParams,
|
||||||
|
getBaseClasses,
|
||||||
|
getCredentialData,
|
||||||
|
getCredentialParam,
|
||||||
|
serializeChatHistory
|
||||||
|
} from '../../../src'
|
||||||
import { DynamoDBChatMessageHistory } from 'langchain/stores/message/dynamodb'
|
import { DynamoDBChatMessageHistory } from 'langchain/stores/message/dynamodb'
|
||||||
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
||||||
|
|
||||||
|
|
@ -70,13 +79,23 @@ class DynamoDb_Memory implements INode {
|
||||||
return initalizeDynamoDB(nodeData, options)
|
return initalizeDynamoDB(nodeData, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
//@ts-ignore
|
||||||
const dynamodbMemory = await initalizeDynamoDB(nodeData, options)
|
memoryMethods = {
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||||
const chatId = options?.chatId as string
|
const dynamodbMemory = await initalizeDynamoDB(nodeData, options)
|
||||||
options.logger.info(`Clearing DynamoDb memory session ${sessionId ? sessionId : chatId}`)
|
const sessionId = nodeData.inputs?.sessionId as string
|
||||||
await dynamodbMemory.clear()
|
const chatId = options?.chatId as string
|
||||||
options.logger.info(`Successfully cleared DynamoDb memory session ${sessionId ? sessionId : chatId}`)
|
options.logger.info(`Clearing DynamoDb memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
await dynamodbMemory.clear()
|
||||||
|
options.logger.info(`Successfully cleared DynamoDb memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
},
|
||||||
|
async getChatMessages(nodeData: INodeData, options: ICommonObject): Promise<string> {
|
||||||
|
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||||
|
const dynamodbMemory = await initalizeDynamoDB(nodeData, options)
|
||||||
|
const key = memoryKey ?? 'chat_history'
|
||||||
|
const memoryResult = await dynamodbMemory.loadMemoryVariables({})
|
||||||
|
return serializeChatHistory(memoryResult[key])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,13 @@
|
||||||
import { getBaseClasses, getCredentialData, getCredentialParam, ICommonObject, INode, INodeData, INodeParams } from '../../../src'
|
import {
|
||||||
|
getBaseClasses,
|
||||||
|
getCredentialData,
|
||||||
|
getCredentialParam,
|
||||||
|
ICommonObject,
|
||||||
|
INode,
|
||||||
|
INodeData,
|
||||||
|
INodeParams,
|
||||||
|
serializeChatHistory
|
||||||
|
} from '../../../src'
|
||||||
import { MongoDBChatMessageHistory } from 'langchain/stores/message/mongodb'
|
import { MongoDBChatMessageHistory } from 'langchain/stores/message/mongodb'
|
||||||
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
||||||
import { BaseMessage, mapStoredMessageToChatMessage } from 'langchain/schema'
|
import { BaseMessage, mapStoredMessageToChatMessage } from 'langchain/schema'
|
||||||
|
|
@ -67,13 +76,23 @@ class MongoDB_Memory implements INode {
|
||||||
return initializeMongoDB(nodeData, options)
|
return initializeMongoDB(nodeData, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
//@ts-ignore
|
||||||
const mongodbMemory = await initializeMongoDB(nodeData, options)
|
memoryMethods = {
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||||
const chatId = options?.chatId as string
|
const mongodbMemory = await initializeMongoDB(nodeData, options)
|
||||||
options.logger.info(`Clearing MongoDB memory session ${sessionId ? sessionId : chatId}`)
|
const sessionId = nodeData.inputs?.sessionId as string
|
||||||
await mongodbMemory.clear()
|
const chatId = options?.chatId as string
|
||||||
options.logger.info(`Successfully cleared MongoDB memory session ${sessionId ? sessionId : chatId}`)
|
options.logger.info(`Clearing MongoDB memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
await mongodbMemory.clear()
|
||||||
|
options.logger.info(`Successfully cleared MongoDB memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
},
|
||||||
|
async getChatMessages(nodeData: INodeData, options: ICommonObject): Promise<string> {
|
||||||
|
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||||
|
const mongodbMemory = await initializeMongoDB(nodeData, options)
|
||||||
|
const key = memoryKey ?? 'chat_history'
|
||||||
|
const memoryResult = await mongodbMemory.loadMemoryVariables({})
|
||||||
|
return serializeChatHistory(memoryResult[key])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../
|
||||||
import { ICommonObject } from '../../../src'
|
import { ICommonObject } from '../../../src'
|
||||||
import { MotorheadMemory, MotorheadMemoryInput } from 'langchain/memory'
|
import { MotorheadMemory, MotorheadMemoryInput } from 'langchain/memory'
|
||||||
import fetch from 'node-fetch'
|
import fetch from 'node-fetch'
|
||||||
|
import { getBufferString } from 'langchain/memory'
|
||||||
|
|
||||||
class MotorMemory_Memory implements INode {
|
class MotorMemory_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -64,13 +65,23 @@ class MotorMemory_Memory implements INode {
|
||||||
return initalizeMotorhead(nodeData, options)
|
return initalizeMotorhead(nodeData, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
//@ts-ignore
|
||||||
const motorhead = await initalizeMotorhead(nodeData, options)
|
memoryMethods = {
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||||
const chatId = options?.chatId as string
|
const motorhead = await initalizeMotorhead(nodeData, options)
|
||||||
options.logger.info(`Clearing Motorhead memory session ${sessionId ? sessionId : chatId}`)
|
const sessionId = nodeData.inputs?.sessionId as string
|
||||||
await motorhead.clear()
|
const chatId = options?.chatId as string
|
||||||
options.logger.info(`Successfully cleared Motorhead memory session ${sessionId ? sessionId : chatId}`)
|
options.logger.info(`Clearing Motorhead memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
await motorhead.clear()
|
||||||
|
options.logger.info(`Successfully cleared Motorhead memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
},
|
||||||
|
async getChatMessages(nodeData: INodeData, options: ICommonObject): Promise<string> {
|
||||||
|
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||||
|
const motorhead = await initalizeMotorhead(nodeData, options)
|
||||||
|
const key = memoryKey ?? 'chat_history'
|
||||||
|
const memoryResult = await motorhead.loadMemoryVariables({})
|
||||||
|
return getBufferString(memoryResult[key])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { INode, INodeData, INodeParams, ICommonObject } from '../../../src/Interface'
|
import { INode, INodeData, INodeParams, ICommonObject } from '../../../src/Interface'
|
||||||
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
import { getBaseClasses, getCredentialData, getCredentialParam, serializeChatHistory } from '../../../src/utils'
|
||||||
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
||||||
import { RedisChatMessageHistory, RedisChatMessageHistoryInput } from 'langchain/stores/message/ioredis'
|
import { RedisChatMessageHistory, RedisChatMessageHistoryInput } from 'langchain/stores/message/ioredis'
|
||||||
import { mapStoredMessageToChatMessage, BaseMessage } from 'langchain/schema'
|
import { mapStoredMessageToChatMessage, BaseMessage } from 'langchain/schema'
|
||||||
|
|
@ -65,13 +65,23 @@ class RedisBackedChatMemory_Memory implements INode {
|
||||||
return await initalizeRedis(nodeData, options)
|
return await initalizeRedis(nodeData, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
//@ts-ignore
|
||||||
const redis = await initalizeRedis(nodeData, options)
|
memoryMethods = {
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||||
const chatId = options?.chatId as string
|
const redis = await initalizeRedis(nodeData, options)
|
||||||
options.logger.info(`Clearing Redis memory session ${sessionId ? sessionId : chatId}`)
|
const sessionId = nodeData.inputs?.sessionId as string
|
||||||
await redis.clear()
|
const chatId = options?.chatId as string
|
||||||
options.logger.info(`Successfully cleared Redis memory session ${sessionId ? sessionId : chatId}`)
|
options.logger.info(`Clearing Redis memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
await redis.clear()
|
||||||
|
options.logger.info(`Successfully cleared Redis memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
},
|
||||||
|
async getChatMessages(nodeData: INodeData, options: ICommonObject): Promise<string> {
|
||||||
|
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||||
|
const redis = await initalizeRedis(nodeData, options)
|
||||||
|
const key = memoryKey ?? 'chat_history'
|
||||||
|
const memoryResult = await redis.loadMemoryVariables({})
|
||||||
|
return serializeChatHistory(memoryResult[key])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
||||||
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
import { getBaseClasses, getCredentialData, getCredentialParam, serializeChatHistory } from '../../../src/utils'
|
||||||
import { ICommonObject } from '../../../src'
|
import { ICommonObject } from '../../../src'
|
||||||
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
||||||
import { UpstashRedisChatMessageHistory } from 'langchain/stores/message/upstash_redis'
|
import { UpstashRedisChatMessageHistory } from 'langchain/stores/message/upstash_redis'
|
||||||
|
|
@ -63,13 +63,22 @@ class UpstashRedisBackedChatMemory_Memory implements INode {
|
||||||
return initalizeUpstashRedis(nodeData, options)
|
return initalizeUpstashRedis(nodeData, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
//@ts-ignore
|
||||||
const redis = await initalizeUpstashRedis(nodeData, options)
|
memoryMethods = {
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||||
const chatId = options?.chatId as string
|
const redis = await initalizeUpstashRedis(nodeData, options)
|
||||||
options.logger.info(`Clearing Upstash Redis memory session ${sessionId ? sessionId : chatId}`)
|
const sessionId = nodeData.inputs?.sessionId as string
|
||||||
await redis.clear()
|
const chatId = options?.chatId as string
|
||||||
options.logger.info(`Successfully cleared Upstash Redis memory session ${sessionId ? sessionId : chatId}`)
|
options.logger.info(`Clearing Upstash Redis memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
await redis.clear()
|
||||||
|
options.logger.info(`Successfully cleared Upstash Redis memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
},
|
||||||
|
async getChatMessages(nodeData: INodeData, options: ICommonObject): Promise<string> {
|
||||||
|
const redis = await initalizeUpstashRedis(nodeData, options)
|
||||||
|
const key = 'chat_history'
|
||||||
|
const memoryResult = await redis.loadMemoryVariables({})
|
||||||
|
return serializeChatHistory(memoryResult[key])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
||||||
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
||||||
import { ZepMemory, ZepMemoryInput } from 'langchain/memory/zep'
|
import { ZepMemory, ZepMemoryInput } from 'langchain/memory/zep'
|
||||||
import { ICommonObject } from '../../../src'
|
import { ICommonObject } from '../../../src'
|
||||||
|
import { getBufferString } from 'langchain/memory'
|
||||||
|
|
||||||
class ZepMemory_Memory implements INode {
|
class ZepMemory_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -140,13 +141,25 @@ class ZepMemory_Memory implements INode {
|
||||||
return zep
|
return zep
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
//@ts-ignore
|
||||||
const zep = await initalizeZep(nodeData, options)
|
memoryMethods = {
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||||
const chatId = options?.chatId as string
|
const zep = await initalizeZep(nodeData, options)
|
||||||
options.logger.info(`Clearing Zep memory session ${sessionId ? sessionId : chatId}`)
|
const sessionId = nodeData.inputs?.sessionId as string
|
||||||
await zep.clear()
|
const chatId = options?.chatId as string
|
||||||
options.logger.info(`Successfully cleared Zep memory session ${sessionId ? sessionId : chatId}`)
|
options.logger.info(`Clearing Zep memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
await zep.clear()
|
||||||
|
options.logger.info(`Successfully cleared Zep memory session ${sessionId ? sessionId : chatId}`)
|
||||||
|
},
|
||||||
|
async getChatMessages(nodeData: INodeData, options: ICommonObject): Promise<string> {
|
||||||
|
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||||
|
const aiPrefix = nodeData.inputs?.aiPrefix as string
|
||||||
|
const humanPrefix = nodeData.inputs?.humanPrefix as string
|
||||||
|
const zep = await initalizeZep(nodeData, options)
|
||||||
|
const key = memoryKey ?? 'chat_history'
|
||||||
|
const memoryResult = await zep.loadMemoryVariables({})
|
||||||
|
return getBufferString(memoryResult[key], humanPrefix, aiPrefix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { DynamicTool, DynamicToolInput } from 'langchain/tools'
|
import { DynamicTool, DynamicToolInput } from 'langchain/tools'
|
||||||
import { BaseChain } from 'langchain/chains'
|
import { BaseChain } from 'langchain/chains'
|
||||||
|
import { handleEscapeCharacters } from '../../../src/utils'
|
||||||
|
|
||||||
export interface ChainToolInput extends Omit<DynamicToolInput, 'func'> {
|
export interface ChainToolInput extends Omit<DynamicToolInput, 'func'> {
|
||||||
chain: BaseChain
|
chain: BaseChain
|
||||||
|
|
@ -14,7 +15,8 @@ export class ChainTool extends DynamicTool {
|
||||||
func: async (input, runManager) => {
|
func: async (input, runManager) => {
|
||||||
// To enable LLM Chain which has promptValues
|
// To enable LLM Chain which has promptValues
|
||||||
if ((chain as any).prompt && (chain as any).prompt.promptValues) {
|
if ((chain as any).prompt && (chain as any).prompt.promptValues) {
|
||||||
const values = await chain.call((chain as any).prompt.promptValues, runManager?.getChild())
|
const promptValues = handleEscapeCharacters((chain as any).prompt.promptValues, true)
|
||||||
|
const values = await chain.call(promptValues, runManager?.getChild())
|
||||||
return values?.text
|
return values?.text
|
||||||
}
|
}
|
||||||
return chain.run(input, runManager?.getChild())
|
return chain.run(input, runManager?.getChild())
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,12 @@ export interface INode extends INodeProperties {
|
||||||
search: (nodeData: INodeData, options?: ICommonObject) => Promise<any>
|
search: (nodeData: INodeData, options?: ICommonObject) => Promise<any>
|
||||||
delete: (nodeData: INodeData, options?: ICommonObject) => Promise<void>
|
delete: (nodeData: INodeData, options?: ICommonObject) => Promise<void>
|
||||||
}
|
}
|
||||||
|
memoryMethods?: {
|
||||||
|
clearSessionMemory: (nodeData: INodeData, options?: ICommonObject) => Promise<void>
|
||||||
|
getChatMessages: (nodeData: INodeData, options?: ICommonObject) => Promise<string>
|
||||||
|
}
|
||||||
init?(nodeData: INodeData, input: string, options?: ICommonObject): Promise<any>
|
init?(nodeData: INodeData, input: string, options?: ICommonObject): Promise<any>
|
||||||
run?(nodeData: INodeData, input: string, options?: ICommonObject): Promise<string | ICommonObject>
|
run?(nodeData: INodeData, input: string, options?: ICommonObject): Promise<string | ICommonObject>
|
||||||
clearSessionMemory?(nodeData: INodeData, options?: ICommonObject): Promise<void>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INodeData extends INodeProperties {
|
export interface INodeData extends INodeProperties {
|
||||||
|
|
|
||||||
|
|
@ -549,6 +549,18 @@ export const convertChatHistoryToText = (chatHistory: IMessage[] = []): string =
|
||||||
.join('\n')
|
.join('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize array chat history to string
|
||||||
|
* @param {IMessage[]} chatHistory
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const serializeChatHistory = (chatHistory: string | Array<string>) => {
|
||||||
|
if (Array.isArray(chatHistory)) {
|
||||||
|
return chatHistory.join('\n')
|
||||||
|
}
|
||||||
|
return chatHistory
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert schema to zod schema
|
* Convert schema to zod schema
|
||||||
* @param {string | object} schema
|
* @param {string | object} schema
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,8 @@ import {
|
||||||
getEncryptionKey,
|
getEncryptionKey,
|
||||||
checkMemorySessionId,
|
checkMemorySessionId,
|
||||||
clearSessionMemoryFromViewMessageDialog,
|
clearSessionMemoryFromViewMessageDialog,
|
||||||
getUserHome
|
getUserHome,
|
||||||
|
replaceChatHistory
|
||||||
} from './utils'
|
} from './utils'
|
||||||
import { cloneDeep, omit, uniqWith, isEqual } from 'lodash'
|
import { cloneDeep, omit, uniqWith, isEqual } from 'lodash'
|
||||||
import { getDataSource } from './DataSource'
|
import { getDataSource } from './DataSource'
|
||||||
|
|
@ -54,7 +55,7 @@ import { Tool } from './database/entities/Tool'
|
||||||
import { Assistant } from './database/entities/Assistant'
|
import { Assistant } from './database/entities/Assistant'
|
||||||
import { ChatflowPool } from './ChatflowPool'
|
import { ChatflowPool } from './ChatflowPool'
|
||||||
import { CachePool } from './CachePool'
|
import { CachePool } from './CachePool'
|
||||||
import { ICommonObject, INodeOptionsValue } from 'flowise-components'
|
import { ICommonObject, IMessage, INodeOptionsValue } from 'flowise-components'
|
||||||
import { createRateLimiter, getRateLimiter, initializeRateLimiter } from './utils/rateLimit'
|
import { createRateLimiter, getRateLimiter, initializeRateLimiter } from './utils/rateLimit'
|
||||||
import { addAPIKey, compareKeys, deleteAPIKey, getApiKey, getAPIKeys, updateAPIKey } from './utils/apiKey'
|
import { addAPIKey, compareKeys, deleteAPIKey, getApiKey, getAPIKeys, updateAPIKey } from './utils/apiKey'
|
||||||
|
|
||||||
|
|
@ -1267,14 +1268,14 @@ export class App {
|
||||||
* @param {IReactFlowEdge[]} edges
|
* @param {IReactFlowEdge[]} edges
|
||||||
* @returns {string | undefined}
|
* @returns {string | undefined}
|
||||||
*/
|
*/
|
||||||
findMemoryLabel(nodes: IReactFlowNode[], edges: IReactFlowEdge[]): string | undefined {
|
findMemoryLabel(nodes: IReactFlowNode[], edges: IReactFlowEdge[]): IReactFlowNode | undefined {
|
||||||
const memoryNodes = nodes.filter((node) => node.data.category === 'Memory')
|
const memoryNodes = nodes.filter((node) => node.data.category === 'Memory')
|
||||||
const memoryNodeIds = memoryNodes.map((mem) => mem.data.id)
|
const memoryNodeIds = memoryNodes.map((mem) => mem.data.id)
|
||||||
|
|
||||||
for (const edge of edges) {
|
for (const edge of edges) {
|
||||||
if (memoryNodeIds.includes(edge.source)) {
|
if (memoryNodeIds.includes(edge.source)) {
|
||||||
const memoryNode = nodes.find((node) => node.data.id === edge.source)
|
const memoryNode = nodes.find((node) => node.data.id === edge.source)
|
||||||
return memoryNode ? memoryNode.data.label : undefined
|
return memoryNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined
|
return undefined
|
||||||
|
|
@ -1395,6 +1396,19 @@ export class App {
|
||||||
|
|
||||||
isStreamValid = isFlowValidForStream(nodes, endingNodeData)
|
isStreamValid = isFlowValidForStream(nodes, endingNodeData)
|
||||||
|
|
||||||
|
let chatHistory: IMessage[] | string = incomingInput.history
|
||||||
|
if (
|
||||||
|
endingNodeData.inputs?.memory &&
|
||||||
|
!incomingInput.history &&
|
||||||
|
(incomingInput.chatId || incomingInput.overrideConfig?.sessionId)
|
||||||
|
) {
|
||||||
|
const memoryNodeId = endingNodeData.inputs?.memory.split('.')[0].replace('{{', '')
|
||||||
|
const memoryNode = nodes.find((node) => node.data.id === memoryNodeId)
|
||||||
|
if (memoryNode) {
|
||||||
|
chatHistory = await replaceChatHistory(memoryNode, incomingInput, this.AppDataSource, databaseEntities, logger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*** Get Starting Nodes with Non-Directed Graph ***/
|
/*** Get Starting Nodes with Non-Directed Graph ***/
|
||||||
const constructedObj = constructGraphs(nodes, edges, true)
|
const constructedObj = constructGraphs(nodes, edges, true)
|
||||||
const nonDirectedGraph = constructedObj.graph
|
const nonDirectedGraph = constructedObj.graph
|
||||||
|
|
@ -1409,7 +1423,7 @@ export class App {
|
||||||
depthQueue,
|
depthQueue,
|
||||||
this.nodesPool.componentNodes,
|
this.nodesPool.componentNodes,
|
||||||
incomingInput.question,
|
incomingInput.question,
|
||||||
incomingInput.history,
|
chatHistory,
|
||||||
chatId,
|
chatId,
|
||||||
chatflowid,
|
chatflowid,
|
||||||
this.AppDataSource,
|
this.AppDataSource,
|
||||||
|
|
@ -1429,7 +1443,7 @@ export class App {
|
||||||
nodeToExecute.data,
|
nodeToExecute.data,
|
||||||
reactFlowNodes,
|
reactFlowNodes,
|
||||||
incomingInput.question,
|
incomingInput.question,
|
||||||
incomingInput.history
|
chatHistory
|
||||||
)
|
)
|
||||||
nodeToExecuteData = reactFlowNodeData
|
nodeToExecuteData = reactFlowNodeData
|
||||||
|
|
||||||
|
|
@ -1446,11 +1460,17 @@ export class App {
|
||||||
let sessionId = undefined
|
let sessionId = undefined
|
||||||
if (nodeToExecuteData.instance) sessionId = checkMemorySessionId(nodeToExecuteData.instance, chatId)
|
if (nodeToExecuteData.instance) sessionId = checkMemorySessionId(nodeToExecuteData.instance, chatId)
|
||||||
|
|
||||||
const memoryType = this.findMemoryLabel(nodes, edges)
|
const memoryNode = this.findMemoryLabel(nodes, edges)
|
||||||
|
const memoryType = memoryNode?.data.label
|
||||||
|
|
||||||
|
let chatHistory: IMessage[] | string = incomingInput.history
|
||||||
|
if (memoryNode && !incomingInput.history && (incomingInput.chatId || incomingInput.overrideConfig?.sessionId)) {
|
||||||
|
chatHistory = await replaceChatHistory(memoryNode, incomingInput, this.AppDataSource, databaseEntities, logger)
|
||||||
|
}
|
||||||
|
|
||||||
let result = isStreamValid
|
let result = isStreamValid
|
||||||
? await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
|
? await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
|
||||||
chatHistory: incomingInput.history,
|
chatHistory,
|
||||||
socketIO,
|
socketIO,
|
||||||
socketIOClientId: incomingInput.socketIOClientId,
|
socketIOClientId: incomingInput.socketIOClientId,
|
||||||
logger,
|
logger,
|
||||||
|
|
@ -1460,7 +1480,7 @@ export class App {
|
||||||
chatId
|
chatId
|
||||||
})
|
})
|
||||||
: await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
|
: await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
|
||||||
chatHistory: incomingInput.history,
|
chatHistory,
|
||||||
logger,
|
logger,
|
||||||
appDataSource: this.AppDataSource,
|
appDataSource: this.AppDataSource,
|
||||||
databaseEntities,
|
databaseEntities,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ import {
|
||||||
IOverrideConfig,
|
IOverrideConfig,
|
||||||
IReactFlowEdge,
|
IReactFlowEdge,
|
||||||
IReactFlowNode,
|
IReactFlowNode,
|
||||||
IVariableDict
|
IVariableDict,
|
||||||
|
IncomingInput
|
||||||
} from '../Interface'
|
} from '../Interface'
|
||||||
import { cloneDeep, get, isEqual } from 'lodash'
|
import { cloneDeep, get, isEqual } from 'lodash'
|
||||||
import {
|
import {
|
||||||
|
|
@ -216,7 +217,7 @@ export const buildLangchain = async (
|
||||||
depthQueue: IDepthQueue,
|
depthQueue: IDepthQueue,
|
||||||
componentNodes: IComponentNodes,
|
componentNodes: IComponentNodes,
|
||||||
question: string,
|
question: string,
|
||||||
chatHistory: IMessage[],
|
chatHistory: IMessage[] | string,
|
||||||
chatId: string,
|
chatId: string,
|
||||||
chatflowid: string,
|
chatflowid: string,
|
||||||
appDataSource: DataSource,
|
appDataSource: DataSource,
|
||||||
|
|
@ -347,8 +348,8 @@ export const clearAllSessionMemory = async (
|
||||||
node.data.inputs.sessionId = sessionId
|
node.data.inputs.sessionId = sessionId
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newNodeInstance.clearSessionMemory) {
|
if (newNodeInstance.memoryMethods && newNodeInstance.memoryMethods.clearSessionMemory) {
|
||||||
await newNodeInstance?.clearSessionMemory(node.data, { chatId, appDataSource, databaseEntities, logger })
|
await newNodeInstance.memoryMethods.clearSessionMemory(node.data, { chatId, appDataSource, databaseEntities, logger })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -380,8 +381,8 @@ export const clearSessionMemoryFromViewMessageDialog = async (
|
||||||
|
|
||||||
if (sessionId && node.data.inputs) node.data.inputs.sessionId = sessionId
|
if (sessionId && node.data.inputs) node.data.inputs.sessionId = sessionId
|
||||||
|
|
||||||
if (newNodeInstance.clearSessionMemory) {
|
if (newNodeInstance.memoryMethods && newNodeInstance.memoryMethods.clearSessionMemory) {
|
||||||
await newNodeInstance?.clearSessionMemory(node.data, { chatId, appDataSource, databaseEntities, logger })
|
await newNodeInstance.memoryMethods.clearSessionMemory(node.data, { chatId, appDataSource, databaseEntities, logger })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -399,7 +400,7 @@ export const getVariableValue = (
|
||||||
paramValue: string,
|
paramValue: string,
|
||||||
reactFlowNodes: IReactFlowNode[],
|
reactFlowNodes: IReactFlowNode[],
|
||||||
question: string,
|
question: string,
|
||||||
chatHistory: IMessage[],
|
chatHistory: IMessage[] | string,
|
||||||
isAcceptVariable = false
|
isAcceptVariable = false
|
||||||
) => {
|
) => {
|
||||||
let returnVal = paramValue
|
let returnVal = paramValue
|
||||||
|
|
@ -432,7 +433,10 @@ export const getVariableValue = (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAcceptVariable && variableFullPath === CHAT_HISTORY_VAR_PREFIX) {
|
if (isAcceptVariable && variableFullPath === CHAT_HISTORY_VAR_PREFIX) {
|
||||||
variableDict[`{{${variableFullPath}}}`] = handleEscapeCharacters(convertChatHistoryToText(chatHistory), false)
|
variableDict[`{{${variableFullPath}}}`] = handleEscapeCharacters(
|
||||||
|
typeof chatHistory === 'string' ? chatHistory : convertChatHistoryToText(chatHistory),
|
||||||
|
false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split by first occurrence of '.' to get just nodeId
|
// Split by first occurrence of '.' to get just nodeId
|
||||||
|
|
@ -475,7 +479,7 @@ export const resolveVariables = (
|
||||||
reactFlowNodeData: INodeData,
|
reactFlowNodeData: INodeData,
|
||||||
reactFlowNodes: IReactFlowNode[],
|
reactFlowNodes: IReactFlowNode[],
|
||||||
question: string,
|
question: string,
|
||||||
chatHistory: IMessage[]
|
chatHistory: IMessage[] | string
|
||||||
): INodeData => {
|
): INodeData => {
|
||||||
let flowNodeData = cloneDeep(reactFlowNodeData)
|
let flowNodeData = cloneDeep(reactFlowNodeData)
|
||||||
const types = 'inputs'
|
const types = 'inputs'
|
||||||
|
|
@ -873,3 +877,39 @@ export const checkMemorySessionId = (instance: any, chatId: string): string | un
|
||||||
return instance.memory.chatHistory.sessionId
|
return instance.memory.chatHistory.sessionId
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace chatHistory if incomingInput.history is empty and sessionId/chatId is provided
|
||||||
|
* @param {IReactFlowNode} memoryNode
|
||||||
|
* @param {IncomingInput} incomingInput
|
||||||
|
* @param {DataSource} appDataSource
|
||||||
|
* @param {IDatabaseEntity} databaseEntities
|
||||||
|
* @param {any} logger
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const replaceChatHistory = async (
|
||||||
|
memoryNode: IReactFlowNode,
|
||||||
|
incomingInput: IncomingInput,
|
||||||
|
appDataSource: DataSource,
|
||||||
|
databaseEntities: IDatabaseEntity,
|
||||||
|
logger: any
|
||||||
|
): Promise<string> => {
|
||||||
|
const nodeInstanceFilePath = memoryNode.data.filePath as string
|
||||||
|
const nodeModule = await import(nodeInstanceFilePath)
|
||||||
|
const newNodeInstance = new nodeModule.nodeClass()
|
||||||
|
|
||||||
|
if (incomingInput.overrideConfig?.sessionId && memoryNode.data.inputs) {
|
||||||
|
memoryNode.data.inputs.sessionId = incomingInput.overrideConfig.sessionId
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newNodeInstance.memoryMethods && newNodeInstance.memoryMethods.getChatMessages) {
|
||||||
|
return await newNodeInstance.memoryMethods.getChatMessages(memoryNode.data, {
|
||||||
|
chatId: incomingInput.chatId,
|
||||||
|
appDataSource,
|
||||||
|
databaseEntities,
|
||||||
|
logger
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue