diff --git a/packages/components/nodes/vectorstores/Vectara_Existing/Vectara_Existing.ts b/packages/components/nodes/vectorstores/Vectara_Existing/Vectara_Existing.ts new file mode 100644 index 000000000..fcf0b1aad --- /dev/null +++ b/packages/components/nodes/vectorstores/Vectara_Existing/Vectara_Existing.ts @@ -0,0 +1,115 @@ +import { INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface' +import { getBaseClasses } from '../../../src/utils' +import { VectaraStore, VectaraLibArgs, VectaraFilter } from 'langchain/vectorstores/vectara' + +class VectaraExisting_VectorStores implements INode { + label: string + name: string + description: string + type: string + icon: string + category: string + baseClasses: string[] + inputs: INodeParams[] + outputs: INodeOutputsValue[] + + constructor() { + this.label = 'Vectara Load Existing Index' + this.name = 'vectaraExistingIndex' + this.type = 'Vectara' + this.icon = 'vectara.png' + this.category = 'Vector Stores' + this.description = 'Load existing index from Vectara (i.e: Document has been upserted)' + this.baseClasses = [this.type, 'VectorStoreRetriever', 'BaseRetriever'] + this.inputs = [ + { + label: 'Vectara Customer ID', + name: 'customerID', + type: 'string' + }, + { + label: 'Vectara Corpus ID', + name: 'corpusID', + type: 'string' + }, + { + label: 'Vectara API Key', + name: 'apiKey', + type: 'password' + }, + { + label: 'Vectara Metadata Filter', + name: 'filter', + type: 'json', + additionalParams: true, + optional: true + }, + { + label: 'Lambda', + name: 'lambda', + type: 'number', + additionalParams: true, + optional: true + }, + { + label: 'Top K', + name: 'topK', + description: 'Number of top results to fetch. Defaults to 4', + placeholder: '4', + type: 'number', + additionalParams: true, + optional: true + } + ] + this.outputs = [ + { + label: 'Vectara Retriever', + name: 'retriever', + baseClasses: this.baseClasses + }, + { + label: 'Vectara Vector Store', + name: 'vectorStore', + baseClasses: [this.type, ...getBaseClasses(VectaraStore)] + } + ] + } + async init(nodeData: INodeData): Promise { + const customerId = nodeData.inputs?.customerID as number + const corpusId = nodeData.inputs?.corpusID as number + const apiKey = nodeData.inputs?.apiKey as string + const vectaraMetadatafilter = nodeData.inputs?.filter as VectaraFilter + const lambda = nodeData.inputs?.lambda as number + const output = nodeData.outputs?.output as string + const topK = nodeData.inputs?.topK as string + const k = topK ? parseInt(topK, 10) : 4 + + const vectaraArgs: VectaraLibArgs = { + apiKey: apiKey, + customerId: customerId, + corpusId: corpusId + } + + const vectaraFilter: VectaraFilter = {} + + if (vectaraMetadatafilter) { + const metadatafilter = typeof vectaraMetadatafilter === 'object' ? vectaraMetadatafilter : JSON.parse(vectaraMetadatafilter) + vectaraFilter.filter = metadatafilter + } + + if (lambda) vectaraFilter.lambda = lambda + + const vectorStore = new VectaraStore(vectaraArgs) + + if (output === 'retriever') { + const retriever = vectorStore.asRetriever(k, vectaraFilter) + return retriever + } else if (output === 'vectorStore') { + ;(vectorStore as any).k = k + return vectorStore + } + return vectorStore + } +} + +module.exports = { nodeClass: VectaraExisting_VectorStores } diff --git a/packages/components/nodes/vectorstores/Vectara_Upsert/Vectara_Upsert.ts b/packages/components/nodes/vectorstores/Vectara_Upsert/Vectara_Upsert.ts new file mode 100644 index 000000000..ea44f3c9b --- /dev/null +++ b/packages/components/nodes/vectorstores/Vectara_Upsert/Vectara_Upsert.ts @@ -0,0 +1,132 @@ +import { INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface' +import { Embeddings } from 'langchain/embeddings/base' +import { getBaseClasses } from '../../../src/utils' +import { VectaraStore, VectaraLibArgs, VectaraFilter } from 'langchain/vectorstores/vectara' +import { Document } from 'langchain/document' +import { flatten } from 'lodash' + +class VectaraExisting_VectorStores implements INode { + label: string + name: string + description: string + type: string + icon: string + category: string + baseClasses: string[] + inputs: INodeParams[] + outputs: INodeOutputsValue[] + + constructor() { + this.label = 'Vectara Upsert Document' + this.name = 'vectaraExisting' + this.type = 'Vectara' + this.icon = 'vectara.png' + this.category = 'Vector Stores' + this.description = 'Upsert documents to Vectara' + this.baseClasses = [this.type, 'VectorStoreRetriever', 'BaseRetriever'] + this.inputs = [ + { + label: 'Vectara Customer ID', + name: 'customerID', + type: 'string' + }, + { + label: 'Vectara Corpus ID', + name: 'corpusID', + type: 'string' + }, + { + label: 'Vectara API Key', + name: 'apiKey', + type: 'password' + }, + { + label: 'Document', + name: 'document', + type: 'Document', + list: true + }, + { + label: 'Filter', + name: 'filter', + type: 'json', + additionalParams: true, + optional: true + }, + { + label: 'Lambda', + name: 'lambda', + type: 'number', + additionalParams: true, + optional: true + }, + { + label: 'Top K', + name: 'topK', + description: 'Number of top results to fetch. Defaults to 4', + placeholder: '4', + type: 'number', + additionalParams: true, + optional: true + } + ] + this.outputs = [ + { + label: 'Vectara Retriever', + name: 'retriever', + baseClasses: this.baseClasses + }, + { + label: 'Vectara Vector Store', + name: 'vectorStore', + baseClasses: [this.type, ...getBaseClasses(VectaraStore)] + } + ] + } + async init(nodeData: INodeData): Promise { + const customerId = nodeData.inputs?.customerID as number + const corpusId = nodeData.inputs?.corpusID as number + const apiKey = nodeData.inputs?.apiKey as string + const docs = nodeData.inputs?.document as Document[] + const embeddings = {} as Embeddings + const vectaraMetadatafilter = nodeData.inputs?.filter as VectaraFilter + const lambda = nodeData.inputs?.lambda as number + const output = nodeData.outputs?.output as string + const topK = nodeData.inputs?.topK as string + const k = topK ? parseInt(topK, 10) : 4 + + const vectaraArgs: VectaraLibArgs = { + apiKey: apiKey, + customerId: customerId, + corpusId: corpusId + } + + const vectaraFilter: VectaraFilter = {} + + if (vectaraMetadatafilter) { + const metadatafilter = typeof vectaraMetadatafilter === 'object' ? vectaraMetadatafilter : JSON.parse(vectaraMetadatafilter) + vectaraFilter.filter = metadatafilter + } + + if (lambda) vectaraFilter.lambda = lambda + + const flattenDocs = docs && docs.length ? flatten(docs) : [] + const finalDocs = [] + for (let i = 0; i < flattenDocs.length; i += 1) { + finalDocs.push(new Document(flattenDocs[i])) + } + + const vectorStore = await VectaraStore.fromDocuments(finalDocs, embeddings, vectaraArgs) + + if (output === 'retriever') { + const retriever = vectorStore.asRetriever(k, vectaraFilter) + return retriever + } else if (output === 'vectorStore') { + ;(vectorStore as any).k = k + return vectorStore + } + return vectorStore + } +} + +module.exports = { nodeClass: VectaraExisting_VectorStores }