Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,8 @@
},
"engines": {
"node": ">=18.15.0"
},
"resolutions": {
"@qdrant/openapi-typescript-fetch": "1.2.1"
}
}
6 changes: 3 additions & 3 deletions packages/components/nodes/memory/ZepMemory/ZepMemory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ZepMemory_Memory implements INode {
inputs: INodeParams[]

constructor() {
this.label = 'Zep Memory'
this.label = 'Zep Memory - Open Source'
this.name = 'ZepMemory'
this.version = 2.0
this.type = 'ZepMemory'
Expand Down Expand Up @@ -97,11 +97,11 @@ class ZepMemory_Memory implements INode {
}

async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
return await initalizeZep(nodeData, options)
return await initializeZep(nodeData, options)
}
}

const initalizeZep = async (nodeData: INodeData, options: ICommonObject): Promise<ZepMemory> => {
const initializeZep = async (nodeData: INodeData, options: ICommonObject): Promise<ZepMemory> => {
const baseURL = nodeData.inputs?.baseURL as string
const aiPrefix = nodeData.inputs?.aiPrefix as string
const humanPrefix = nodeData.inputs?.humanPrefix as string
Expand Down
181 changes: 181 additions & 0 deletions packages/components/nodes/memory/ZepMemoryCloud/ZepMemoryCloud.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { IMessage, INode, INodeData, INodeParams, MemoryMethods, MessageType } from '../../../src/Interface'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of creating a new node, what do u think if we just add a new options field to the ZepMemory that allow users to select OpenSource or Cloud, then according to selection, use the respective library for init

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be doable, but I have some reservations.

Our interfaces are not the same for open source and cloud sdk. For memory, for example, we don't offer the ability to specify memoryType on Open Source version, whereas this is one of the new things we have introduced with Zep Cloud. The same applies to vector stores, in cloud fro example we don't accept embeddings and embedding dimensions any more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we would have to have a lot of additional if blocks in the nodes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh okay i thought the difference is only the initialization. In that case, make sense to have separate nodes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Marked it as ready for review then!

import { convertBaseMessagetoIMessage, getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
import { ZepMemory, ZepMemoryInput } from '@getzep/zep-cloud/langchain'

import { ICommonObject } from '../../../src'
import { InputValues, MemoryVariables, OutputValues } from 'langchain/memory'
import { BaseMessage } from 'langchain/schema'

class ZepMemoryCloud_Memory implements INode {
label: string
name: string
version: number
description: string
type: string
icon: string
category: string
baseClasses: string[]
credential: INodeParams
inputs: INodeParams[]

constructor() {
this.label = 'Zep Memory - Cloud'
this.name = 'ZepMemoryCloud'
this.version = 2.0
this.type = 'ZepMemory'
this.icon = 'zep.svg'
this.category = 'Memory'
this.description = 'Summarizes the conversation and stores the memory in zep server'
this.baseClasses = [this.type, ...getBaseClasses(ZepMemory)]
this.credential = {
label: 'Connect Credential',
name: 'credential',
type: 'credential',
optional: true,
description: 'Configure JWT authentication on your Zep instance (Optional)',
credentialNames: ['zepMemoryApi']
}
this.inputs = [
{
label: 'Session Id',
name: 'sessionId',
type: 'string',
description:
'If not specified, a random id will be used. Learn <a target="_blank" href="https://docs.flowiseai.com/memory/long-term-memory#ui-and-embedded-chat">more</a>',
default: '',
additionalParams: true,
optional: true
},
{
label: 'Memory Type',
name: 'memoryType',
type: 'string',
default: 'perpetual',
description: 'Zep Memory Type, can be perpetual or message_window',
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, _: string, options: ICommonObject): Promise<any> {
return await initializeZep(nodeData, options)
}
}

const initializeZep = async (nodeData: INodeData, options: ICommonObject): Promise<ZepMemory> => {
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 memoryType = nodeData.inputs?.memoryType as 'perpetual' | 'message_window'
const sessionId = nodeData.inputs?.sessionId as string

const credentialData = await getCredentialData(nodeData.credential ?? '', options)
const apiKey = getCredentialParam('apiKey', credentialData, nodeData)
const obj: ZepMemoryInput & ZepMemoryExtendedInput = {
apiKey,
aiPrefix,
humanPrefix,
memoryKey,
sessionId,
inputKey,
memoryType: memoryType,
returnMessages: true
}

return new ZepMemoryExtended(obj)
}

interface ZepMemoryExtendedInput {
memoryType?: 'perpetual' | 'message_window'
}

class ZepMemoryExtended extends ZepMemory implements MemoryMethods {
memoryType: 'perpetual' | 'message_window'

constructor(fields: ZepMemoryInput & ZepMemoryExtendedInput) {
super(fields)
this.memoryType = fields.memoryType ?? 'perpetual'
}

async loadMemoryVariables(values: InputValues, overrideSessionId = ''): Promise<MemoryVariables> {
if (overrideSessionId) {
this.sessionId = overrideSessionId
}
return super.loadMemoryVariables({ ...values, memoryType: this.memoryType })
}

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
}
return super.clear()
}

async getChatMessages(overrideSessionId = '', returnBaseMessages = false): Promise<IMessage[] | BaseMessage[]> {
const id = overrideSessionId ? 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 ? 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 ? overrideSessionId : this.sessionId
await this.clear(id)
}
}

module.exports = { nodeClass: ZepMemoryCloud_Memory }
19 changes: 19 additions & 0 deletions packages/components/nodes/memory/ZepMemoryCloud/zep.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/components/nodes/vectorstores/Zep/Zep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Zep_VectorStores implements INode {
outputs: INodeOutputsValue[]

constructor() {
this.label = 'Zep'
this.label = 'Zep Collection - Open Source'
this.name = 'zep'
this.version = 2.0
this.type = 'Zep'
Expand Down
2 changes: 1 addition & 1 deletion packages/components/nodes/vectorstores/Zep/Zep_Existing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Zep_Existing_VectorStores implements INode {
outputs: INodeOutputsValue[]

constructor() {
this.label = 'Zep Load Existing Index'
this.label = 'Zep Load Existing Index - Open Source'
this.name = 'zepExistingIndex'
this.version = 1.0
this.type = 'Zep'
Expand Down
2 changes: 1 addition & 1 deletion packages/components/nodes/vectorstores/Zep/Zep_Upsert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Zep_Upsert_VectorStores implements INode {
outputs: INodeOutputsValue[]

constructor() {
this.label = 'Zep Upsert Document'
this.label = 'Zep Upsert Document - Open Source'
this.name = 'zepUpsert'
this.version = 1.0
this.type = 'Zep'
Expand Down
Loading