update all memory nodes
This commit is contained in:
parent
48b17fc785
commit
aac0546a7f
|
|
@ -1,6 +1,7 @@
|
||||||
import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
import { FlowiseMemory, IMessage, INode, INodeData, INodeParams, MemoryMethods, MessageType } from '../../../src/Interface'
|
||||||
import { getBaseClasses } from '../../../src/utils'
|
import { convertBaseMessagetoIMessage, getBaseClasses } from '../../../src/utils'
|
||||||
import { BufferMemory } from 'langchain/memory'
|
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
||||||
|
import { BaseMessage } from 'langchain/schema'
|
||||||
|
|
||||||
class BufferMemory_Memory implements INode {
|
class BufferMemory_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -41,7 +42,7 @@ class BufferMemory_Memory implements INode {
|
||||||
async init(nodeData: INodeData): Promise<any> {
|
async init(nodeData: INodeData): Promise<any> {
|
||||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||||
const inputKey = nodeData.inputs?.inputKey as string
|
const inputKey = nodeData.inputs?.inputKey as string
|
||||||
return new BufferMemory({
|
return new BufferMemoryExtended({
|
||||||
returnMessages: true,
|
returnMessages: true,
|
||||||
memoryKey,
|
memoryKey,
|
||||||
inputKey
|
inputKey
|
||||||
|
|
@ -49,4 +50,41 @@ class BufferMemory_Memory implements INode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BufferMemoryExtended extends FlowiseMemory implements MemoryMethods {
|
||||||
|
constructor(fields: BufferMemoryInput) {
|
||||||
|
super(fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChatMessages(_?: string, returnBaseMessages = false): Promise<IMessage[] | BaseMessage[]> {
|
||||||
|
const memoryResult = await this.loadMemoryVariables({})
|
||||||
|
const baseMessages = memoryResult[this.memoryKey ?? 'chat_history']
|
||||||
|
return returnBaseMessages ? baseMessages : convertBaseMessagetoIMessage(baseMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addChatMessages(msgArray: { text: string; type: MessageType }[]): Promise<void> {
|
||||||
|
const input = msgArray.find((msg) => msg.type === 'userMessage')
|
||||||
|
const output = msgArray.find((msg) => msg.type === 'apiMessage')
|
||||||
|
|
||||||
|
const inputValues = { [this.inputKey ?? 'input']: input?.text }
|
||||||
|
const outputValues = { output: output?.text }
|
||||||
|
|
||||||
|
await this.saveContext(inputValues, outputValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearChatMessages(): Promise<void> {
|
||||||
|
await this.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
async resumeMessages(messages: IMessage[]): Promise<void> {
|
||||||
|
// Clear existing chatHistory to avoid duplication
|
||||||
|
if (messages.length) await this.clear()
|
||||||
|
|
||||||
|
// Insert into chatHistory
|
||||||
|
for (const msg of messages) {
|
||||||
|
if (msg.type === 'userMessage') await this.chatHistory.addUserMessage(msg.message)
|
||||||
|
else if (msg.type === 'apiMessage') await this.chatHistory.addAIChatMessage(msg.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = { nodeClass: BufferMemory_Memory }
|
module.exports = { nodeClass: BufferMemory_Memory }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
import { FlowiseWindowMemory, IMessage, INode, INodeData, INodeParams, MemoryMethods, MessageType } from '../../../src/Interface'
|
||||||
import { getBaseClasses } from '../../../src/utils'
|
import { convertBaseMessagetoIMessage, getBaseClasses } from '../../../src/utils'
|
||||||
import { BufferWindowMemory, BufferWindowMemoryInput } from 'langchain/memory'
|
import { BufferWindowMemory, BufferWindowMemoryInput } from 'langchain/memory'
|
||||||
|
import { BaseMessage } from 'langchain/schema'
|
||||||
|
|
||||||
class BufferWindowMemory_Memory implements INode {
|
class BufferWindowMemory_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -57,7 +58,44 @@ class BufferWindowMemory_Memory implements INode {
|
||||||
k: parseInt(k, 10)
|
k: parseInt(k, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BufferWindowMemory(obj)
|
return new BufferWindowMemoryExtended(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BufferWindowMemoryExtended extends FlowiseWindowMemory implements MemoryMethods {
|
||||||
|
constructor(fields: BufferWindowMemoryInput) {
|
||||||
|
super(fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChatMessages(_?: string, returnBaseMessages = false): Promise<IMessage[] | BaseMessage[]> {
|
||||||
|
const memoryResult = await this.loadMemoryVariables({})
|
||||||
|
const baseMessages = memoryResult[this.memoryKey ?? 'chat_history']
|
||||||
|
return returnBaseMessages ? baseMessages : convertBaseMessagetoIMessage(baseMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addChatMessages(msgArray: { text: string; type: MessageType }[]): Promise<void> {
|
||||||
|
const input = msgArray.find((msg) => msg.type === 'userMessage')
|
||||||
|
const output = msgArray.find((msg) => msg.type === 'apiMessage')
|
||||||
|
|
||||||
|
const inputValues = { [this.inputKey ?? 'input']: input?.text }
|
||||||
|
const outputValues = { output: output?.text }
|
||||||
|
|
||||||
|
await this.saveContext(inputValues, outputValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearChatMessages(): Promise<void> {
|
||||||
|
await this.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
async resumeMessages(messages: IMessage[]): Promise<void> {
|
||||||
|
// Clear existing chatHistory to avoid duplication
|
||||||
|
if (messages.length) await this.clear()
|
||||||
|
|
||||||
|
// Insert into chatHistory
|
||||||
|
for (const msg of messages) {
|
||||||
|
if (msg.type === 'userMessage') await this.chatHistory.addUserMessage(msg.message)
|
||||||
|
else if (msg.type === 'apiMessage') await this.chatHistory.addAIChatMessage(msg.message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
import { FlowiseSummaryMemory, IMessage, INode, INodeData, INodeParams, MemoryMethods, MessageType } from '../../../src/Interface'
|
||||||
import { getBaseClasses } from '../../../src/utils'
|
import { convertBaseMessagetoIMessage, getBaseClasses } from '../../../src/utils'
|
||||||
import { ConversationSummaryMemory, ConversationSummaryMemoryInput } from 'langchain/memory'
|
import { ConversationSummaryMemory, ConversationSummaryMemoryInput } from 'langchain/memory'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
|
import { BaseMessage } from 'langchain/schema'
|
||||||
|
|
||||||
class ConversationSummaryMemory_Memory implements INode {
|
class ConversationSummaryMemory_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -56,7 +57,48 @@ class ConversationSummaryMemory_Memory implements INode {
|
||||||
inputKey
|
inputKey
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ConversationSummaryMemory(obj)
|
return new ConversationSummaryMemoryExtended(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConversationSummaryMemoryExtended extends FlowiseSummaryMemory implements MemoryMethods {
|
||||||
|
constructor(fields: ConversationSummaryMemoryInput) {
|
||||||
|
super(fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChatMessages(_?: string, returnBaseMessages = false): Promise<IMessage[] | BaseMessage[]> {
|
||||||
|
const memoryResult = await this.loadMemoryVariables({})
|
||||||
|
const baseMessages = memoryResult[this.memoryKey ?? 'chat_history']
|
||||||
|
return returnBaseMessages ? baseMessages : convertBaseMessagetoIMessage(baseMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addChatMessages(msgArray: { text: string; type: MessageType }[]): Promise<void> {
|
||||||
|
const input = msgArray.find((msg) => msg.type === 'userMessage')
|
||||||
|
const output = msgArray.find((msg) => msg.type === 'apiMessage')
|
||||||
|
|
||||||
|
const inputValues = { [this.inputKey ?? 'input']: input?.text }
|
||||||
|
const outputValues = { output: output?.text }
|
||||||
|
|
||||||
|
await this.saveContext(inputValues, outputValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearChatMessages(): Promise<void> {
|
||||||
|
await this.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
async resumeMessages(messages: IMessage[]): Promise<void> {
|
||||||
|
// Clear existing chatHistory to avoid duplication
|
||||||
|
if (messages.length) await this.clear()
|
||||||
|
|
||||||
|
// Insert into chatHistory
|
||||||
|
for (const msg of messages) {
|
||||||
|
if (msg.type === 'userMessage') await this.chatHistory.addUserMessage(msg.message)
|
||||||
|
else if (msg.type === 'apiMessage') await this.chatHistory.addAIChatMessage(msg.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace buffer
|
||||||
|
const chatMessages = await this.chatHistory.getMessages()
|
||||||
|
this.buffer = await this.predictNewSummary(chatMessages.slice(-2), this.buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,25 @@
|
||||||
import {
|
import {
|
||||||
ICommonObject,
|
DynamoDBClient,
|
||||||
INode,
|
DynamoDBClientConfig,
|
||||||
INodeData,
|
GetItemCommand,
|
||||||
INodeParams,
|
GetItemCommandInput,
|
||||||
|
UpdateItemCommand,
|
||||||
|
UpdateItemCommandInput,
|
||||||
|
DeleteItemCommand,
|
||||||
|
DeleteItemCommandInput,
|
||||||
|
AttributeValue
|
||||||
|
} from '@aws-sdk/client-dynamodb'
|
||||||
|
import { DynamoDBChatMessageHistory } from 'langchain/stores/message/dynamodb'
|
||||||
|
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
||||||
|
import { mapStoredMessageToChatMessage, AIMessage, HumanMessage, StoredMessage, BaseMessage } from 'langchain/schema'
|
||||||
|
import {
|
||||||
|
convertBaseMessagetoIMessage,
|
||||||
getBaseClasses,
|
getBaseClasses,
|
||||||
getCredentialData,
|
getCredentialData,
|
||||||
getCredentialParam,
|
getCredentialParam,
|
||||||
serializeChatHistory
|
serializeChatHistory
|
||||||
} from '../../../src'
|
} from '../../../src/utils'
|
||||||
import { DynamoDBChatMessageHistory } from 'langchain/stores/message/dynamodb'
|
import { FlowiseMemory, ICommonObject, IMessage, INode, INodeData, INodeParams, MemoryMethods, MessageType } from '../../../src/Interface'
|
||||||
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
|
||||||
|
|
||||||
class DynamoDb_Memory implements INode {
|
class DynamoDb_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -102,49 +112,199 @@ class DynamoDb_Memory implements INode {
|
||||||
const initalizeDynamoDB = async (nodeData: INodeData, options: ICommonObject): Promise<BufferMemory> => {
|
const initalizeDynamoDB = async (nodeData: INodeData, options: ICommonObject): Promise<BufferMemory> => {
|
||||||
const tableName = nodeData.inputs?.tableName as string
|
const tableName = nodeData.inputs?.tableName as string
|
||||||
const partitionKey = nodeData.inputs?.partitionKey as string
|
const partitionKey = nodeData.inputs?.partitionKey as string
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
|
||||||
const region = nodeData.inputs?.region as string
|
const region = nodeData.inputs?.region as string
|
||||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||||
const chatId = options.chatId
|
const chatId = options.chatId
|
||||||
|
|
||||||
let isSessionIdUsingChatMessageId = false
|
let isSessionIdUsingChatMessageId = false
|
||||||
if (!sessionId && chatId) isSessionIdUsingChatMessageId = true
|
let sessionId = ''
|
||||||
|
|
||||||
|
if (!nodeData.inputs?.sessionId && chatId) {
|
||||||
|
isSessionIdUsingChatMessageId = true
|
||||||
|
sessionId = chatId
|
||||||
|
} else {
|
||||||
|
sessionId = nodeData.inputs?.sessionId
|
||||||
|
}
|
||||||
|
|
||||||
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
||||||
const accessKeyId = getCredentialParam('accessKey', credentialData, nodeData)
|
const accessKeyId = getCredentialParam('accessKey', credentialData, nodeData)
|
||||||
const secretAccessKey = getCredentialParam('secretAccessKey', credentialData, nodeData)
|
const secretAccessKey = getCredentialParam('secretAccessKey', credentialData, nodeData)
|
||||||
|
|
||||||
const dynamoDb = new DynamoDBChatMessageHistory({
|
const config: DynamoDBClientConfig = {
|
||||||
tableName,
|
|
||||||
partitionKey,
|
|
||||||
sessionId: sessionId ? sessionId : chatId,
|
|
||||||
config: {
|
|
||||||
region,
|
region,
|
||||||
credentials: {
|
credentials: {
|
||||||
accessKeyId,
|
accessKeyId,
|
||||||
secretAccessKey
|
secretAccessKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const client = new DynamoDBClient(config ?? {})
|
||||||
|
|
||||||
|
const dynamoDb = new DynamoDBChatMessageHistory({
|
||||||
|
tableName,
|
||||||
|
partitionKey,
|
||||||
|
sessionId,
|
||||||
|
config
|
||||||
})
|
})
|
||||||
|
|
||||||
const memory = new BufferMemoryExtended({
|
const memory = new BufferMemoryExtended({
|
||||||
memoryKey: memoryKey ?? 'chat_history',
|
memoryKey: memoryKey ?? 'chat_history',
|
||||||
chatHistory: dynamoDb,
|
chatHistory: dynamoDb,
|
||||||
isSessionIdUsingChatMessageId
|
isSessionIdUsingChatMessageId,
|
||||||
|
sessionId,
|
||||||
|
dynamodbClient: client
|
||||||
})
|
})
|
||||||
return memory
|
return memory
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BufferMemoryExtendedInput {
|
interface BufferMemoryExtendedInput {
|
||||||
isSessionIdUsingChatMessageId: boolean
|
isSessionIdUsingChatMessageId: boolean
|
||||||
|
dynamodbClient: DynamoDBClient
|
||||||
|
sessionId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
class BufferMemoryExtended extends BufferMemory {
|
interface DynamoDBSerializedChatMessage {
|
||||||
isSessionIdUsingChatMessageId? = false
|
M: {
|
||||||
|
type: {
|
||||||
|
S: string
|
||||||
|
}
|
||||||
|
text: {
|
||||||
|
S: string
|
||||||
|
}
|
||||||
|
role?: {
|
||||||
|
S: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor(fields: BufferMemoryInput & Partial<BufferMemoryExtendedInput>) {
|
class BufferMemoryExtended extends FlowiseMemory implements MemoryMethods {
|
||||||
|
isSessionIdUsingChatMessageId = false
|
||||||
|
sessionId = ''
|
||||||
|
dynamodbClient: DynamoDBClient
|
||||||
|
|
||||||
|
constructor(fields: BufferMemoryInput & BufferMemoryExtendedInput) {
|
||||||
super(fields)
|
super(fields)
|
||||||
this.isSessionIdUsingChatMessageId = fields.isSessionIdUsingChatMessageId
|
this.sessionId = fields.sessionId
|
||||||
|
this.dynamodbClient = fields.dynamodbClient
|
||||||
|
}
|
||||||
|
|
||||||
|
overrideDynamoKey(overrideSessionId = '') {
|
||||||
|
const existingDynamoKey = (this as any).dynamoKey
|
||||||
|
const partitionKey = (this as any).partitionKey
|
||||||
|
|
||||||
|
let newDynamoKey: Record<string, AttributeValue> = {}
|
||||||
|
|
||||||
|
if (Object.keys(existingDynamoKey).includes(partitionKey)) {
|
||||||
|
newDynamoKey[partitionKey] = { S: overrideSessionId }
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(newDynamoKey).length ? newDynamoKey : existingDynamoKey
|
||||||
|
}
|
||||||
|
|
||||||
|
async addNewMessage(
|
||||||
|
messages: StoredMessage[],
|
||||||
|
client: DynamoDBClient,
|
||||||
|
tableName = '',
|
||||||
|
dynamoKey: Record<string, AttributeValue> = {},
|
||||||
|
messageAttributeName = 'messages'
|
||||||
|
) {
|
||||||
|
const params: UpdateItemCommandInput = {
|
||||||
|
TableName: tableName,
|
||||||
|
Key: dynamoKey,
|
||||||
|
ExpressionAttributeNames: {
|
||||||
|
'#m': messageAttributeName
|
||||||
|
},
|
||||||
|
ExpressionAttributeValues: {
|
||||||
|
':empty_list': {
|
||||||
|
L: []
|
||||||
|
},
|
||||||
|
':m': {
|
||||||
|
L: messages.map((message) => {
|
||||||
|
const dynamoSerializedMessage: DynamoDBSerializedChatMessage = {
|
||||||
|
M: {
|
||||||
|
type: {
|
||||||
|
S: message.type
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
S: message.data.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (message.data.role) {
|
||||||
|
dynamoSerializedMessage.M.role = { S: message.data.role }
|
||||||
|
}
|
||||||
|
return dynamoSerializedMessage
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpdateExpression: 'SET #m = list_append(if_not_exists(#m, :empty_list), :m)'
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.send(new UpdateItemCommand(params))
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChatMessages(overrideSessionId = '', returnBaseMessages = false): Promise<IMessage[] | BaseMessage[]> {
|
||||||
|
if (!this.dynamodbClient) return []
|
||||||
|
|
||||||
|
const dynamoKey = overrideSessionId ? this.overrideDynamoKey(overrideSessionId) : (this as any).dynamoKey
|
||||||
|
const tableName = (this as any).tableName
|
||||||
|
const messageAttributeName = (this as any).messageAttributeName
|
||||||
|
|
||||||
|
const params: GetItemCommandInput = {
|
||||||
|
TableName: tableName,
|
||||||
|
Key: dynamoKey
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await this.dynamodbClient.send(new GetItemCommand(params))
|
||||||
|
const items = response.Item ? response.Item[messageAttributeName]?.L ?? [] : []
|
||||||
|
const messages = items
|
||||||
|
.map((item) => ({
|
||||||
|
type: item.M?.type.S,
|
||||||
|
data: {
|
||||||
|
role: item.M?.role?.S,
|
||||||
|
content: item.M?.text.S
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.filter((x): x is StoredMessage => x.type !== undefined && x.data.content !== undefined)
|
||||||
|
const baseMessages = messages.map(mapStoredMessageToChatMessage)
|
||||||
|
return returnBaseMessages ? baseMessages : convertBaseMessagetoIMessage(baseMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addChatMessages(msgArray: { text: string; type: MessageType }[], overrideSessionId = ''): Promise<void> {
|
||||||
|
if (!this.dynamodbClient) return
|
||||||
|
|
||||||
|
const dynamoKey = overrideSessionId ? this.overrideDynamoKey(overrideSessionId) : (this as any).dynamoKey
|
||||||
|
const tableName = (this as any).tableName
|
||||||
|
const messageAttributeName = (this as any).messageAttributeName
|
||||||
|
|
||||||
|
const input = msgArray.find((msg) => msg.type === 'userMessage')
|
||||||
|
const output = msgArray.find((msg) => msg.type === 'apiMessage')
|
||||||
|
|
||||||
|
if (input) {
|
||||||
|
const newInputMessage = new HumanMessage(input.text)
|
||||||
|
const messageToAdd = [newInputMessage].map((msg) => msg.toDict())
|
||||||
|
await this.addNewMessage(messageToAdd, this.dynamodbClient, tableName, dynamoKey, messageAttributeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output) {
|
||||||
|
const newOutputMessage = new AIMessage(output.text)
|
||||||
|
const messageToAdd = [newOutputMessage].map((msg) => msg.toDict())
|
||||||
|
await this.addNewMessage(messageToAdd, this.dynamodbClient, tableName, dynamoKey, messageAttributeName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearChatMessages(overrideSessionId = ''): Promise<void> {
|
||||||
|
if (!this.dynamodbClient) return
|
||||||
|
|
||||||
|
const dynamoKey = overrideSessionId ? this.overrideDynamoKey(overrideSessionId) : (this as any).dynamoKey
|
||||||
|
const tableName = (this as any).tableName
|
||||||
|
|
||||||
|
const params: DeleteItemCommandInput = {
|
||||||
|
TableName: tableName,
|
||||||
|
Key: dynamoKey
|
||||||
|
}
|
||||||
|
await this.dynamodbClient.send(new DeleteItemCommand(params))
|
||||||
|
await this.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
|
import { MongoClient, Collection, Document } from 'mongodb'
|
||||||
|
import { MongoDBChatMessageHistory } from 'langchain/stores/message/mongodb'
|
||||||
|
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
||||||
|
import { mapStoredMessageToChatMessage, AIMessage, HumanMessage, BaseMessage } from 'langchain/schema'
|
||||||
import {
|
import {
|
||||||
|
convertBaseMessagetoIMessage,
|
||||||
getBaseClasses,
|
getBaseClasses,
|
||||||
getCredentialData,
|
getCredentialData,
|
||||||
getCredentialParam,
|
getCredentialParam,
|
||||||
ICommonObject,
|
|
||||||
INode,
|
|
||||||
INodeData,
|
|
||||||
INodeParams,
|
|
||||||
serializeChatHistory
|
serializeChatHistory
|
||||||
} from '../../../src'
|
} from '../../../src/utils'
|
||||||
import { MongoDBChatMessageHistory } from 'langchain/stores/message/mongodb'
|
import { FlowiseMemory, ICommonObject, IMessage, INode, INodeData, INodeParams, MemoryMethods, MessageType } from '../../../src/Interface'
|
||||||
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
|
||||||
import { BaseMessage, mapStoredMessageToChatMessage } from 'langchain/schema'
|
|
||||||
import { MongoClient } from 'mongodb'
|
|
||||||
|
|
||||||
class MongoDB_Memory implements INode {
|
class MongoDB_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -99,23 +97,30 @@ class MongoDB_Memory implements INode {
|
||||||
const initializeMongoDB = async (nodeData: INodeData, options: ICommonObject): Promise<BufferMemory> => {
|
const initializeMongoDB = async (nodeData: INodeData, options: ICommonObject): Promise<BufferMemory> => {
|
||||||
const databaseName = nodeData.inputs?.databaseName as string
|
const databaseName = nodeData.inputs?.databaseName as string
|
||||||
const collectionName = nodeData.inputs?.collectionName as string
|
const collectionName = nodeData.inputs?.collectionName as string
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
|
||||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||||
const chatId = options?.chatId as string
|
const chatId = options?.chatId as string
|
||||||
|
|
||||||
let isSessionIdUsingChatMessageId = false
|
let isSessionIdUsingChatMessageId = false
|
||||||
if (!sessionId && chatId) isSessionIdUsingChatMessageId = true
|
let sessionId = ''
|
||||||
|
|
||||||
|
if (!nodeData.inputs?.sessionId && chatId) {
|
||||||
|
isSessionIdUsingChatMessageId = true
|
||||||
|
sessionId = chatId
|
||||||
|
} else {
|
||||||
|
sessionId = nodeData.inputs?.sessionId
|
||||||
|
}
|
||||||
|
|
||||||
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
||||||
let mongoDBConnectUrl = getCredentialParam('mongoDBConnectUrl', credentialData, nodeData)
|
const mongoDBConnectUrl = getCredentialParam('mongoDBConnectUrl', credentialData, nodeData)
|
||||||
|
|
||||||
const client = new MongoClient(mongoDBConnectUrl)
|
const client = new MongoClient(mongoDBConnectUrl)
|
||||||
await client.connect()
|
await client.connect()
|
||||||
|
|
||||||
const collection = client.db(databaseName).collection(collectionName)
|
const collection = client.db(databaseName).collection(collectionName)
|
||||||
|
|
||||||
const mongoDBChatMessageHistory = new MongoDBChatMessageHistory({
|
const mongoDBChatMessageHistory = new MongoDBChatMessageHistory({
|
||||||
collection,
|
collection,
|
||||||
sessionId: sessionId ? sessionId : chatId
|
sessionId
|
||||||
})
|
})
|
||||||
|
|
||||||
mongoDBChatMessageHistory.getMessages = async (): Promise<BaseMessage[]> => {
|
mongoDBChatMessageHistory.getMessages = async (): Promise<BaseMessage[]> => {
|
||||||
|
|
@ -144,20 +149,77 @@ const initializeMongoDB = async (nodeData: INodeData, options: ICommonObject): P
|
||||||
return new BufferMemoryExtended({
|
return new BufferMemoryExtended({
|
||||||
memoryKey: memoryKey ?? 'chat_history',
|
memoryKey: memoryKey ?? 'chat_history',
|
||||||
chatHistory: mongoDBChatMessageHistory,
|
chatHistory: mongoDBChatMessageHistory,
|
||||||
isSessionIdUsingChatMessageId
|
isSessionIdUsingChatMessageId,
|
||||||
|
sessionId,
|
||||||
|
collection
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BufferMemoryExtendedInput {
|
interface BufferMemoryExtendedInput {
|
||||||
isSessionIdUsingChatMessageId: boolean
|
isSessionIdUsingChatMessageId: boolean
|
||||||
|
collection: Collection<Document>
|
||||||
|
sessionId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
class BufferMemoryExtended extends BufferMemory {
|
class BufferMemoryExtended extends FlowiseMemory implements MemoryMethods {
|
||||||
|
sessionId = ''
|
||||||
|
collection: Collection<Document>
|
||||||
isSessionIdUsingChatMessageId? = false
|
isSessionIdUsingChatMessageId? = false
|
||||||
|
|
||||||
constructor(fields: BufferMemoryInput & Partial<BufferMemoryExtendedInput>) {
|
constructor(fields: BufferMemoryInput & BufferMemoryExtendedInput) {
|
||||||
super(fields)
|
super(fields)
|
||||||
this.isSessionIdUsingChatMessageId = fields.isSessionIdUsingChatMessageId
|
this.sessionId = fields.sessionId
|
||||||
|
this.collection = fields.collection
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChatMessages(overrideSessionId = '', returnBaseMessages = false): Promise<IMessage[] | BaseMessage[]> {
|
||||||
|
if (!this.collection) return []
|
||||||
|
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
const document = await this.collection.findOne({ sessionId: id })
|
||||||
|
const messages = document?.messages || []
|
||||||
|
const baseMessages = messages.map(mapStoredMessageToChatMessage)
|
||||||
|
return returnBaseMessages ? baseMessages : convertBaseMessagetoIMessage(baseMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addChatMessages(msgArray: { text: string; type: MessageType }[], overrideSessionId = ''): Promise<void> {
|
||||||
|
if (!this.collection) return
|
||||||
|
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
const input = msgArray.find((msg) => msg.type === 'userMessage')
|
||||||
|
const output = msgArray.find((msg) => msg.type === 'apiMessage')
|
||||||
|
|
||||||
|
if (input) {
|
||||||
|
const newInputMessage = new HumanMessage(input.text)
|
||||||
|
const messageToAdd = [newInputMessage].map((msg) => msg.toDict())
|
||||||
|
await this.collection.updateOne(
|
||||||
|
{ sessionId: id },
|
||||||
|
{
|
||||||
|
$push: { messages: { $each: messageToAdd } }
|
||||||
|
},
|
||||||
|
{ upsert: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output) {
|
||||||
|
const newOutputMessage = new AIMessage(output.text)
|
||||||
|
const messageToAdd = [newOutputMessage].map((msg) => msg.toDict())
|
||||||
|
await this.collection.updateOne(
|
||||||
|
{ sessionId: id },
|
||||||
|
{
|
||||||
|
$push: { messages: { $each: messageToAdd } }
|
||||||
|
},
|
||||||
|
{ upsert: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearChatMessages(overrideSessionId = ''): Promise<void> {
|
||||||
|
if (!this.collection) return
|
||||||
|
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
await this.collection.deleteOne({ sessionId: id })
|
||||||
|
await this.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
import { IMessage, INode, INodeData, INodeParams, MessageType } from '../../../src/Interface'
|
||||||
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
import { convertBaseMessagetoIMessage, getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
||||||
import { ICommonObject } from '../../../src'
|
import { ICommonObject } from '../../../src'
|
||||||
import { MotorheadMemory, MotorheadMemoryInput } from 'langchain/memory'
|
import { MotorheadMemory, MotorheadMemoryInput, InputValues, MemoryVariables, OutputValues, getBufferString } from 'langchain/memory'
|
||||||
import fetch from 'node-fetch'
|
import fetch from 'node-fetch'
|
||||||
import { getBufferString } from 'langchain/memory'
|
import { BaseMessage } from 'langchain/schema'
|
||||||
|
|
||||||
class MotorMemory_Memory implements INode {
|
class MotorMemory_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -88,19 +88,26 @@ class MotorMemory_Memory implements INode {
|
||||||
const initalizeMotorhead = async (nodeData: INodeData, options: ICommonObject): Promise<MotorheadMemory> => {
|
const initalizeMotorhead = async (nodeData: INodeData, options: ICommonObject): Promise<MotorheadMemory> => {
|
||||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||||
const baseURL = nodeData.inputs?.baseURL as string
|
const baseURL = nodeData.inputs?.baseURL as string
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
|
||||||
const chatId = options?.chatId as string
|
const chatId = options?.chatId as string
|
||||||
|
|
||||||
let isSessionIdUsingChatMessageId = false
|
let isSessionIdUsingChatMessageId = false
|
||||||
if (!sessionId && chatId) isSessionIdUsingChatMessageId = true
|
let sessionId = ''
|
||||||
|
|
||||||
|
if (!nodeData.inputs?.sessionId && chatId) {
|
||||||
|
isSessionIdUsingChatMessageId = true
|
||||||
|
sessionId = chatId
|
||||||
|
} else {
|
||||||
|
sessionId = nodeData.inputs?.sessionId
|
||||||
|
}
|
||||||
|
|
||||||
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
||||||
const apiKey = getCredentialParam('apiKey', credentialData, nodeData)
|
const apiKey = getCredentialParam('apiKey', credentialData, nodeData)
|
||||||
const clientId = getCredentialParam('clientId', credentialData, nodeData)
|
const clientId = getCredentialParam('clientId', credentialData, nodeData)
|
||||||
|
|
||||||
let obj: MotorheadMemoryInput & Partial<MotorheadMemoryExtendedInput> = {
|
let obj: MotorheadMemoryInput & MotorheadMemoryExtendedInput = {
|
||||||
returnMessages: true,
|
returnMessages: true,
|
||||||
sessionId: sessionId ? sessionId : chatId,
|
isSessionIdUsingChatMessageId,
|
||||||
|
sessionId,
|
||||||
memoryKey
|
memoryKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,8 +124,6 @@ const initalizeMotorhead = async (nodeData: INodeData, options: ICommonObject):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSessionIdUsingChatMessageId) obj.isSessionIdUsingChatMessageId = true
|
|
||||||
|
|
||||||
const motorheadMemory = new MotorheadMemoryExtended(obj)
|
const motorheadMemory = new MotorheadMemoryExtended(obj)
|
||||||
|
|
||||||
// Get messages from sessionId
|
// Get messages from sessionId
|
||||||
|
|
@ -134,12 +139,29 @@ interface MotorheadMemoryExtendedInput {
|
||||||
class MotorheadMemoryExtended extends MotorheadMemory {
|
class MotorheadMemoryExtended extends MotorheadMemory {
|
||||||
isSessionIdUsingChatMessageId? = false
|
isSessionIdUsingChatMessageId? = false
|
||||||
|
|
||||||
constructor(fields: MotorheadMemoryInput & Partial<MotorheadMemoryExtendedInput>) {
|
constructor(fields: MotorheadMemoryInput & MotorheadMemoryExtendedInput) {
|
||||||
super(fields)
|
super(fields)
|
||||||
this.isSessionIdUsingChatMessageId = fields.isSessionIdUsingChatMessageId
|
this.isSessionIdUsingChatMessageId = fields.isSessionIdUsingChatMessageId
|
||||||
}
|
}
|
||||||
|
|
||||||
async clear(): Promise<void> {
|
async loadMemoryVariables(values: InputValues, overrideSessionId = ''): Promise<MemoryVariables> {
|
||||||
|
if (overrideSessionId) {
|
||||||
|
this.sessionId = overrideSessionId
|
||||||
|
}
|
||||||
|
return super.loadMemoryVariables({ values })
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveContext(inputValues: InputValues, outputValues: OutputValues, overrideSessionId = ''): Promise<void> {
|
||||||
|
if (overrideSessionId) {
|
||||||
|
this.sessionId = overrideSessionId
|
||||||
|
}
|
||||||
|
return super.saveContext(inputValues, outputValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
async clear(overrideSessionId = ''): Promise<void> {
|
||||||
|
if (overrideSessionId) {
|
||||||
|
this.sessionId = overrideSessionId
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await this.caller.call(fetch, `${this.url}/sessions/${this.sessionId}/memory`, {
|
await this.caller.call(fetch, `${this.url}/sessions/${this.sessionId}/memory`, {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
|
|
@ -155,6 +177,28 @@ class MotorheadMemoryExtended extends MotorheadMemory {
|
||||||
await this.chatHistory.clear()
|
await this.chatHistory.clear()
|
||||||
await super.clear()
|
await super.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getChatMessages(overrideSessionId = '', returnBaseMessages = false): Promise<IMessage[] | BaseMessage[]> {
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
const memoryVariables = await this.loadMemoryVariables({}, id)
|
||||||
|
const baseMessages = memoryVariables[this.memoryKey]
|
||||||
|
return returnBaseMessages ? baseMessages : convertBaseMessagetoIMessage(baseMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addChatMessages(msgArray: { text: string; type: MessageType }[], overrideSessionId = ''): Promise<void> {
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
const input = msgArray.find((msg) => msg.type === 'userMessage')
|
||||||
|
const output = msgArray.find((msg) => msg.type === 'apiMessage')
|
||||||
|
const inputValues = { [this.inputKey ?? 'input']: input?.text }
|
||||||
|
const outputValues = { output: output?.text }
|
||||||
|
|
||||||
|
await this.saveContext(inputValues, outputValues, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearChatMessages(overrideSessionId = ''): Promise<void> {
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
await this.clear(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { nodeClass: MotorMemory_Memory }
|
module.exports = { nodeClass: MotorMemory_Memory }
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,16 @@
|
||||||
import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
import { Redis } from '@upstash/redis'
|
||||||
import { getBaseClasses, getCredentialData, getCredentialParam, serializeChatHistory } from '../../../src/utils'
|
|
||||||
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'
|
||||||
|
import { mapStoredMessageToChatMessage, AIMessage, HumanMessage, StoredMessage, BaseMessage } from 'langchain/schema'
|
||||||
|
import { FlowiseMemory, IMessage, INode, INodeData, INodeParams, MemoryMethods, MessageType } from '../../../src/Interface'
|
||||||
|
import {
|
||||||
|
convertBaseMessagetoIMessage,
|
||||||
|
getBaseClasses,
|
||||||
|
getCredentialData,
|
||||||
|
getCredentialParam,
|
||||||
|
serializeChatHistory
|
||||||
|
} from '../../../src/utils'
|
||||||
|
import { ICommonObject } from '../../../src/Interface'
|
||||||
|
|
||||||
class UpstashRedisBackedChatMemory_Memory implements INode {
|
class UpstashRedisBackedChatMemory_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -84,29 +92,39 @@ class UpstashRedisBackedChatMemory_Memory implements INode {
|
||||||
|
|
||||||
const initalizeUpstashRedis = async (nodeData: INodeData, options: ICommonObject): Promise<BufferMemory> => {
|
const initalizeUpstashRedis = async (nodeData: INodeData, options: ICommonObject): Promise<BufferMemory> => {
|
||||||
const baseURL = nodeData.inputs?.baseURL as string
|
const baseURL = nodeData.inputs?.baseURL as string
|
||||||
const sessionId = nodeData.inputs?.sessionId as string
|
|
||||||
const sessionTTL = nodeData.inputs?.sessionTTL as string
|
const sessionTTL = nodeData.inputs?.sessionTTL as string
|
||||||
const chatId = options?.chatId as string
|
const chatId = options?.chatId as string
|
||||||
|
|
||||||
let isSessionIdUsingChatMessageId = false
|
let isSessionIdUsingChatMessageId = false
|
||||||
if (!sessionId && chatId) isSessionIdUsingChatMessageId = true
|
let sessionId = ''
|
||||||
|
|
||||||
|
if (!nodeData.inputs?.sessionId && chatId) {
|
||||||
|
isSessionIdUsingChatMessageId = true
|
||||||
|
sessionId = chatId
|
||||||
|
} else {
|
||||||
|
sessionId = nodeData.inputs?.sessionId
|
||||||
|
}
|
||||||
|
|
||||||
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
||||||
const upstashRestToken = getCredentialParam('upstashRestToken', credentialData, nodeData)
|
const upstashRestToken = getCredentialParam('upstashRestToken', credentialData, nodeData)
|
||||||
|
|
||||||
const redisChatMessageHistory = new UpstashRedisChatMessageHistory({
|
const client = new Redis({
|
||||||
sessionId: sessionId ? sessionId : chatId,
|
|
||||||
sessionTTL: sessionTTL ? parseInt(sessionTTL, 10) : undefined,
|
|
||||||
config: {
|
|
||||||
url: baseURL,
|
url: baseURL,
|
||||||
token: upstashRestToken
|
token: upstashRestToken
|
||||||
}
|
})
|
||||||
|
|
||||||
|
const redisChatMessageHistory = new UpstashRedisChatMessageHistory({
|
||||||
|
sessionId,
|
||||||
|
sessionTTL: sessionTTL ? parseInt(sessionTTL, 10) : undefined,
|
||||||
|
client
|
||||||
})
|
})
|
||||||
|
|
||||||
const memory = new BufferMemoryExtended({
|
const memory = new BufferMemoryExtended({
|
||||||
memoryKey: 'chat_history',
|
memoryKey: 'chat_history',
|
||||||
chatHistory: redisChatMessageHistory,
|
chatHistory: redisChatMessageHistory,
|
||||||
isSessionIdUsingChatMessageId
|
isSessionIdUsingChatMessageId,
|
||||||
|
sessionId,
|
||||||
|
redisClient: client
|
||||||
})
|
})
|
||||||
|
|
||||||
return memory
|
return memory
|
||||||
|
|
@ -114,14 +132,59 @@ const initalizeUpstashRedis = async (nodeData: INodeData, options: ICommonObject
|
||||||
|
|
||||||
interface BufferMemoryExtendedInput {
|
interface BufferMemoryExtendedInput {
|
||||||
isSessionIdUsingChatMessageId: boolean
|
isSessionIdUsingChatMessageId: boolean
|
||||||
|
redisClient: Redis
|
||||||
|
sessionId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
class BufferMemoryExtended extends BufferMemory {
|
class BufferMemoryExtended extends FlowiseMemory implements MemoryMethods {
|
||||||
isSessionIdUsingChatMessageId? = false
|
isSessionIdUsingChatMessageId? = false
|
||||||
|
sessionId = ''
|
||||||
|
redisClient: Redis
|
||||||
|
|
||||||
constructor(fields: BufferMemoryInput & Partial<BufferMemoryExtendedInput>) {
|
constructor(fields: BufferMemoryInput & BufferMemoryExtendedInput) {
|
||||||
super(fields)
|
super(fields)
|
||||||
this.isSessionIdUsingChatMessageId = fields.isSessionIdUsingChatMessageId
|
this.isSessionIdUsingChatMessageId = fields.isSessionIdUsingChatMessageId
|
||||||
|
this.sessionId = fields.sessionId
|
||||||
|
this.redisClient = fields.redisClient
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChatMessages(overrideSessionId = '', returnBaseMessages = false): Promise<IMessage[] | BaseMessage[]> {
|
||||||
|
if (!this.redisClient) return []
|
||||||
|
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
const rawStoredMessages: StoredMessage[] = await this.redisClient.lrange<StoredMessage>(id, 0, -1)
|
||||||
|
const orderedMessages = rawStoredMessages.reverse()
|
||||||
|
const previousMessages = orderedMessages.filter((x): x is StoredMessage => x.type !== undefined && x.data.content !== undefined)
|
||||||
|
const baseMessages = previousMessages.map(mapStoredMessageToChatMessage)
|
||||||
|
return returnBaseMessages ? baseMessages : convertBaseMessagetoIMessage(baseMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addChatMessages(msgArray: { text: string; type: MessageType }[], overrideSessionId = ''): Promise<void> {
|
||||||
|
if (!this.redisClient) return
|
||||||
|
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
const input = msgArray.find((msg) => msg.type === 'userMessage')
|
||||||
|
const output = msgArray.find((msg) => msg.type === 'apiMessage')
|
||||||
|
|
||||||
|
if (input) {
|
||||||
|
const newInputMessage = new HumanMessage(input.text)
|
||||||
|
const messageToAdd = [newInputMessage].map((msg) => msg.toDict())
|
||||||
|
await this.redisClient.lpush(id, JSON.stringify(messageToAdd[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output) {
|
||||||
|
const newOutputMessage = new AIMessage(output.text)
|
||||||
|
const messageToAdd = [newOutputMessage].map((msg) => msg.toDict())
|
||||||
|
await this.redisClient.lpush(id, JSON.stringify(messageToAdd[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearChatMessages(overrideSessionId = ''): Promise<void> {
|
||||||
|
if (!this.redisClient) return
|
||||||
|
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
await this.redisClient.del(id)
|
||||||
|
await this.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
|
import { IMessage, INode, INodeData, INodeParams, MessageType } from '../../../src/Interface'
|
||||||
|
import { convertBaseMessagetoIMessage, getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
||||||
import { ZepMemory, ZepMemoryInput } from 'langchain/memory/zep'
|
import { ZepMemory, ZepMemoryInput } from 'langchain/memory/zep'
|
||||||
import { getBufferString, InputValues, MemoryVariables, OutputValues } from 'langchain/memory'
|
|
||||||
import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
|
||||||
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
|
||||||
import { ICommonObject } from '../../../src'
|
import { ICommonObject } from '../../../src'
|
||||||
|
import { InputValues, MemoryVariables, OutputValues, getBufferString } from 'langchain/memory'
|
||||||
|
import { BaseMessage } from 'langchain/schema'
|
||||||
|
|
||||||
class ZepMemory_Memory implements INode {
|
class ZepMemory_Memory implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -147,7 +148,7 @@ const initalizeZep = async (nodeData: INodeData, options: ICommonObject): Promis
|
||||||
|
|
||||||
const obj: ZepMemoryInput & ZepMemoryExtendedInput = {
|
const obj: ZepMemoryInput & ZepMemoryExtendedInput = {
|
||||||
baseURL,
|
baseURL,
|
||||||
sessionId: sessionId ? sessionId : chatId,
|
sessionId,
|
||||||
aiPrefix,
|
aiPrefix,
|
||||||
humanPrefix,
|
humanPrefix,
|
||||||
returnMessages: true,
|
returnMessages: true,
|
||||||
|
|
@ -196,6 +197,28 @@ class ZepMemoryExtended extends ZepMemory {
|
||||||
}
|
}
|
||||||
return super.clear()
|
return super.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getChatMessages(overrideSessionId = '', returnBaseMessages = false): Promise<IMessage[] | BaseMessage[]> {
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
const memoryVariables = await this.loadMemoryVariables({}, id)
|
||||||
|
const baseMessages = memoryVariables[this.memoryKey]
|
||||||
|
return returnBaseMessages ? baseMessages : convertBaseMessagetoIMessage(baseMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addChatMessages(msgArray: { text: string; type: MessageType }[], overrideSessionId = ''): Promise<void> {
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
const input = msgArray.find((msg) => msg.type === 'userMessage')
|
||||||
|
const output = msgArray.find((msg) => msg.type === 'apiMessage')
|
||||||
|
const inputValues = { [this.inputKey ?? 'input']: input?.text }
|
||||||
|
const outputValues = { output: output?.text }
|
||||||
|
|
||||||
|
await this.saveContext(inputValues, outputValues, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearChatMessages(overrideSessionId = ''): Promise<void> {
|
||||||
|
const id = overrideSessionId ?? this.sessionId
|
||||||
|
await this.clear(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { nodeClass: ZepMemory_Memory }
|
module.exports = { nodeClass: ZepMemory_Memory }
|
||||||
|
|
|
||||||
|
|
@ -196,3 +196,34 @@ export class VectorStoreRetriever {
|
||||||
this.vectorStore = fields.vectorStore
|
this.vectorStore = fields.vectorStore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement abstract classes and interface for memory
|
||||||
|
*/
|
||||||
|
import { BaseMessage } from 'langchain/schema'
|
||||||
|
import { BufferMemory, BufferWindowMemory, ConversationSummaryMemory } from 'langchain/memory'
|
||||||
|
|
||||||
|
export interface MemoryMethods {
|
||||||
|
getChatMessages(overrideSessionId?: string, returnBaseMessages?: boolean): Promise<IMessage[] | BaseMessage[]>
|
||||||
|
addChatMessages(msgArray: { text: string; type: MessageType }[], overrideSessionId?: string): Promise<void>
|
||||||
|
clearChatMessages(overrideSessionId?: string): Promise<void>
|
||||||
|
resumeMessages?(messages: IMessage[]): Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class FlowiseMemory extends BufferMemory implements MemoryMethods {
|
||||||
|
abstract getChatMessages(overrideSessionId?: string, returnBaseMessages?: boolean): Promise<IMessage[] | BaseMessage[]>
|
||||||
|
abstract addChatMessages(msgArray: { text: string; type: MessageType }[], overrideSessionId?: string): Promise<void>
|
||||||
|
abstract clearChatMessages(overrideSessionId?: string): Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class FlowiseWindowMemory extends BufferWindowMemory implements MemoryMethods {
|
||||||
|
abstract getChatMessages(overrideSessionId?: string, returnBaseMessages?: boolean): Promise<IMessage[] | BaseMessage[]>
|
||||||
|
abstract addChatMessages(msgArray: { text: string; type: MessageType }[], overrideSessionId?: string): Promise<void>
|
||||||
|
abstract clearChatMessages(overrideSessionId?: string): Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class FlowiseSummaryMemory extends ConversationSummaryMemory implements MemoryMethods {
|
||||||
|
abstract getChatMessages(overrideSessionId?: string, returnBaseMessages?: boolean): Promise<IMessage[] | BaseMessage[]>
|
||||||
|
abstract addChatMessages(msgArray: { text: string; type: MessageType }[], overrideSessionId?: string): Promise<void>
|
||||||
|
abstract clearChatMessages(overrideSessionId?: string): Promise<void>
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue