diff --git a/packages/components/nodes/vectorstores/Chroma_Existing/Chroma_Existing.ts b/packages/components/nodes/vectorstores/Chroma/Chroma_Existing.ts similarity index 69% rename from packages/components/nodes/vectorstores/Chroma_Existing/Chroma_Existing.ts rename to packages/components/nodes/vectorstores/Chroma/Chroma_Existing.ts index 47266fda7..f55faa404 100644 --- a/packages/components/nodes/vectorstores/Chroma_Existing/Chroma_Existing.ts +++ b/packages/components/nodes/vectorstores/Chroma/Chroma_Existing.ts @@ -1,8 +1,8 @@ import { ICommonObject, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface' -import { Chroma, ChromaLibArgs } from 'langchain/vectorstores/chroma' +import { Chroma } from 'langchain/vectorstores/chroma' import { Embeddings } from 'langchain/embeddings/base' import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils' -import type { Collection } from 'chromadb' +import { ChromaExtended } from './core' class Chroma_Existing_VectorStores implements INode { label: string @@ -94,7 +94,7 @@ class Chroma_Existing_VectorStores implements INode { if (chromaURL) obj.url = chromaURL if (chromaApiKey) obj.chromaApiKey = chromaApiKey - const vectorStore = await ChromaExisting.fromExistingCollection(embeddings, obj) + const vectorStore = await ChromaExtended.fromExistingCollection(embeddings, obj) if (output === 'retriever') { const retriever = vectorStore.asRetriever(k) @@ -107,50 +107,4 @@ class Chroma_Existing_VectorStores implements INode { } } -interface ChromaAuth { - chromaApiKey?: string -} - -class ChromaExisting extends Chroma { - chromaApiKey?: string - - constructor(embeddings: Embeddings, args: ChromaLibArgs & Partial) { - super(embeddings, args) - this.chromaApiKey = args.chromaApiKey - } - - static async fromExistingCollection(embeddings: Embeddings, dbConfig: ChromaLibArgs & Partial): Promise { - const instance = new this(embeddings, dbConfig) - await instance.ensureCollection() - return instance - } - - async ensureCollection(): Promise { - if (!this.collection) { - if (!this.index) { - const { ChromaClient } = await Chroma.imports() - const obj: any = { - path: this.url - } - if (this.chromaApiKey) { - obj.fetchOptions = { - headers: { - 'X-Api-Key': this.chromaApiKey - } - } - } - this.index = new ChromaClient(obj) - } - try { - this.collection = await this.index.getOrCreateCollection({ - name: this.collectionName - }) - } catch (err) { - throw new Error(`Chroma getOrCreateCollection error: ${err}`) - } - } - return this.collection - } -} - module.exports = { nodeClass: Chroma_Existing_VectorStores } diff --git a/packages/components/nodes/vectorstores/Chroma_Upsert/Chroma_Upsert.ts b/packages/components/nodes/vectorstores/Chroma/Chroma_Upsert.ts similarity index 76% rename from packages/components/nodes/vectorstores/Chroma_Upsert/Chroma_Upsert.ts rename to packages/components/nodes/vectorstores/Chroma/Chroma_Upsert.ts index 2be1bb3ab..0527b7297 100644 --- a/packages/components/nodes/vectorstores/Chroma_Upsert/Chroma_Upsert.ts +++ b/packages/components/nodes/vectorstores/Chroma/Chroma_Upsert.ts @@ -1,9 +1,10 @@ -import { INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface' +import { ICommonObject, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface' import { Chroma } from 'langchain/vectorstores/chroma' import { Embeddings } from 'langchain/embeddings/base' import { Document } from 'langchain/document' -import { getBaseClasses } from '../../../src/utils' +import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils' import { flatten } from 'lodash' +import { ChromaExtended } from './core' class ChromaUpsert_VectorStores implements INode { label: string @@ -15,6 +16,7 @@ class ChromaUpsert_VectorStores implements INode { category: string baseClasses: string[] inputs: INodeParams[] + credential: INodeParams outputs: INodeOutputsValue[] constructor() { @@ -26,6 +28,14 @@ class ChromaUpsert_VectorStores implements INode { this.category = 'Vector Stores' this.description = 'Upsert documents to Chroma' this.baseClasses = [this.type, 'VectorStoreRetriever', 'BaseRetriever'] + this.credential = { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + description: 'Only needed if you have chroma on cloud services with X-Api-key', + optional: true, + credentialNames: ['chromaApi'] + } this.inputs = [ { label: 'Document', @@ -73,7 +83,7 @@ class ChromaUpsert_VectorStores implements INode { ] } - async init(nodeData: INodeData): Promise { + async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { const collectionName = nodeData.inputs?.collectionName as string const docs = nodeData.inputs?.document as Document[] const embeddings = nodeData.inputs?.embeddings as Embeddings @@ -82,6 +92,9 @@ class ChromaUpsert_VectorStores implements INode { const topK = nodeData.inputs?.topK as string const k = topK ? parseFloat(topK) : 4 + const credentialData = await getCredentialData(nodeData.credential ?? '', options) + const chromaApiKey = getCredentialParam('chromaApiKey', credentialData, nodeData) + const flattenDocs = docs && docs.length ? flatten(docs) : [] const finalDocs = [] for (let i = 0; i < flattenDocs.length; i += 1) { @@ -91,10 +104,12 @@ class ChromaUpsert_VectorStores implements INode { const obj: { collectionName: string url?: string + chromaApiKey?: string } = { collectionName } if (chromaURL) obj.url = chromaURL + if (chromaApiKey) obj.chromaApiKey = chromaApiKey - const vectorStore = await Chroma.fromDocuments(finalDocs, embeddings, obj) + const vectorStore = await ChromaExtended.fromDocuments(finalDocs, embeddings, obj) if (output === 'retriever') { const retriever = vectorStore.asRetriever(k) diff --git a/packages/components/nodes/vectorstores/Chroma_Existing/chroma.svg b/packages/components/nodes/vectorstores/Chroma/chroma.svg similarity index 100% rename from packages/components/nodes/vectorstores/Chroma_Existing/chroma.svg rename to packages/components/nodes/vectorstores/Chroma/chroma.svg diff --git a/packages/components/nodes/vectorstores/Chroma/core.ts b/packages/components/nodes/vectorstores/Chroma/core.ts new file mode 100644 index 000000000..ccdbe03c9 --- /dev/null +++ b/packages/components/nodes/vectorstores/Chroma/core.ts @@ -0,0 +1,49 @@ +import { Chroma, ChromaLibArgs } from 'langchain/vectorstores/chroma' +import { Embeddings } from 'langchain/embeddings/base' +import type { Collection } from 'chromadb' + +interface ChromaAuth { + chromaApiKey?: string +} + +export class ChromaExtended extends Chroma { + chromaApiKey?: string + + constructor(embeddings: Embeddings, args: ChromaLibArgs & Partial) { + super(embeddings, args) + this.chromaApiKey = args.chromaApiKey + } + + static async fromExistingCollection(embeddings: Embeddings, dbConfig: ChromaLibArgs & Partial): Promise { + const instance = new this(embeddings, dbConfig) + await instance.ensureCollection() + return instance + } + + async ensureCollection(): Promise { + if (!this.collection) { + if (!this.index) { + const { ChromaClient } = await Chroma.imports() + const obj: any = { + path: this.url + } + if (this.chromaApiKey) { + obj.fetchOptions = { + headers: { + 'X-Api-Key': this.chromaApiKey + } + } + } + this.index = new ChromaClient(obj) + } + try { + this.collection = await this.index.getOrCreateCollection({ + name: this.collectionName + }) + } catch (err) { + throw new Error(`Chroma getOrCreateCollection error: ${err}`) + } + } + return this.collection + } +} diff --git a/packages/components/nodes/vectorstores/Chroma_Upsert/chroma.svg b/packages/components/nodes/vectorstores/Chroma_Upsert/chroma.svg deleted file mode 100644 index 64090685b..000000000 --- a/packages/components/nodes/vectorstores/Chroma_Upsert/chroma.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - -