diff --git a/packages/components/nodes/memory/ZepMemory/ZepMemory.ts b/packages/components/nodes/memory/ZepMemory/ZepMemory.ts new file mode 100644 index 00000000..f833b4e3 --- /dev/null +++ b/packages/components/nodes/memory/ZepMemory/ZepMemory.ts @@ -0,0 +1,136 @@ +import { SystemChatMessage } from 'langchain/schema' +import { INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses } from '../../../src/utils' +import { ZepMemory, ZepMemoryInput } from 'langchain/memory/zep' + +class ZepMemory_Memory implements INode { + label: string + name: string + description: string + type: string + icon: string + category: string + baseClasses: string[] + inputs: INodeParams[] + + constructor() { + this.label = 'Zep Memory' + this.name = 'ZepMemory' + this.type = 'ZepMemory' + this.icon = 'memory.svg' + this.category = 'Memory' + this.description = 'Summarizes the conversation and stores the memory in zep server' + this.baseClasses = [this.type, ...getBaseClasses(ZepMemory)] + this.inputs = [ + { + label: 'Base URL', + name: 'baseURL', + type: 'string', + default: 'http://127.0.0.1:8000' + }, + { + label: 'Session Id', + name: 'sessionId', + type: 'string', + placeholder: 'unique and manually change in every conversion!', + default: '' + }, + { + label: 'Auto Summary', + name: 'autoSummary', + type: 'boolean', + default: true + }, + { + label: 'Auto Summary Template', + name: 'autoSummaryTemplate', + type: 'string', + default: 'This is the summary of the following conversation:\n{summary}', + additionalParams: true + }, + { + label: 'AI Prefix', + name: 'aiPrefix', + type: 'string', + default: 'ai', + additionalParams: true + }, + { + label: 'Human Prefix', + name: 'humanPrefix', + type: 'string', + default: 'human', + additionalParams: true + }, + { + label: 'Memory Key', + name: 'memoryKey', + type: 'string', + default: 'chat_history', + additionalParams: true + }, + { + label: 'Input Key', + name: 'inputKey', + type: 'string', + default: 'input', + additionalParams: true + }, + { + label: 'Output Key', + name: 'outputKey', + type: 'string', + default: 'text', + additionalParams: true + } + ] + } + + async init(nodeData: INodeData): Promise { + const baseURL = nodeData.inputs?.baseURL as string + const sessionId = nodeData.inputs?.sessionId as string + const aiPrefix = nodeData.inputs?.aiPrefix as string + const humanPrefix = nodeData.inputs?.humanPrefix as string + const memoryKey = nodeData.inputs?.memoryKey as string + const inputKey = nodeData.inputs?.inputKey as string + const autoSummaryTemplate = nodeData.inputs?.autoSummaryTemplate as string + const autoSummary = nodeData.inputs?.autoSummary as boolean + + const obj: ZepMemoryInput = { + baseURL, + sessionId, + aiPrefix, + humanPrefix, + returnMessages: true, + memoryKey, + inputKey + } + + let zep = new ZepMemory(obj) + + // hack to support summary + let tmpFunc = zep.loadMemoryVariables + zep.loadMemoryVariables = async (values) => { + let data = await tmpFunc.bind(zep, values)() + if (autoSummary && zep.returnMessages && data[zep.memoryKey] && data[zep.memoryKey].length) { + const memory = await zep.zepClient.getMemory(zep.sessionId, 10) + if (memory?.summary) { + let summary = autoSummaryTemplate.replace(/{summary}/g, memory.summary.content) + // eslint-disable-next-line no-console + console.log('[ZepMemory] auto summary:', summary) + data[zep.memoryKey].unshift(new SystemChatMessage(summary)) + } + } + // for langchain zep memory compatibility, or we will get "Missing value for input variable chat_history" + if (data instanceof Array) { + data = { + [zep.memoryKey]: data + } + } + return data + } + return zep + } +} + +module.exports = { nodeClass: ZepMemory_Memory } diff --git a/packages/components/nodes/memory/ZepMemory/memory.svg b/packages/components/nodes/memory/ZepMemory/memory.svg new file mode 100644 index 00000000..ca8e17da --- /dev/null +++ b/packages/components/nodes/memory/ZepMemory/memory.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/components/package.json b/packages/components/package.json index 3e3d58b6..a778ea8f 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -17,6 +17,7 @@ "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@dqbd/tiktoken": "^1.0.7", + "@getzep/zep-js": "^0.3.1", "@huggingface/inference": "1", "@pinecone-database/pinecone": "^0.0.12", "@supabase/supabase-js": "^2.21.0",