From e773181b61bea97b4c9e0642b0eb623f13d1f069 Mon Sep 17 00:00:00 2001 From: Eduard-Constantin Ibinceanu Date: Sat, 7 Dec 2024 00:10:46 +0200 Subject: [PATCH] IBM Watsonx embeddings node (#3648) * Add icon image * Add embeddings node * Fix typo --- .../IBMWatsonxEmbedding.ts | 107 ++++++++++++++++++ .../embeddings/IBMWatsonxEmbedding/ibm.png | Bin 0 -> 24591 bytes 2 files changed, 107 insertions(+) create mode 100644 packages/components/nodes/embeddings/IBMWatsonxEmbedding/IBMWatsonxEmbedding.ts create mode 100644 packages/components/nodes/embeddings/IBMWatsonxEmbedding/ibm.png diff --git a/packages/components/nodes/embeddings/IBMWatsonxEmbedding/IBMWatsonxEmbedding.ts b/packages/components/nodes/embeddings/IBMWatsonxEmbedding/IBMWatsonxEmbedding.ts new file mode 100644 index 00000000..45b0d628 --- /dev/null +++ b/packages/components/nodes/embeddings/IBMWatsonxEmbedding/IBMWatsonxEmbedding.ts @@ -0,0 +1,107 @@ +import { WatsonxEmbeddings, WatsonxInputEmbeddings } from '@langchain/community/embeddings/ibm' +import { WatsonxAuth } from '@langchain/community/dist/types/ibm' +import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils' + +class IBMWatsonx_Embeddings implements INode { + label: string + name: string + version: number + type: string + icon: string + category: string + description: string + baseClasses: string[] + credential: INodeParams + inputs: INodeParams[] + + constructor() { + this.label = 'IBM Watsonx Embeddings' + this.name = 'ibmEmbedding' + this.version = 1.0 + this.type = 'WatsonxEmbeddings' + this.icon = 'ibm.png' + this.category = 'Embeddings' + this.description = 'Generate embeddings for a given text using open source model on IBM Watsonx' + this.baseClasses = [this.type, ...getBaseClasses(WatsonxEmbeddings)] + this.credential = { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + credentialNames: ['ibmWatsonx'] + } + this.inputs = [ + { + label: 'Model Name', + name: 'modelName', + type: 'string', + default: 'ibm/slate-30m-english-rtrvr' + }, + { + label: 'Truncate Input Tokens', + name: 'truncateInputTokens', + type: 'number', + description: 'Truncate the input tokens.', + step: 1, + optional: true, + additionalParams: true + }, + { + label: 'Max Retries', + name: 'maxRetries', + type: 'number', + description: 'The maximum number of retries.', + step: 1, + optional: true, + additionalParams: true + }, + { + label: 'Max Concurrency', + name: 'maxConcurrency', + type: 'number', + description: 'The maximum number of concurrencies.', + step: 1, + optional: true, + additionalParams: true + } + ] + } + + async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { + const modelName = nodeData.inputs?.modelName as string + const truncateInputTokens = nodeData.inputs?.truncateInputTokens as string + const maxRetries = nodeData.inputs?.maxRetries as string + const maxConcurrency = nodeData.inputs?.maxConcurrency as string + + const credentialData = await getCredentialData(nodeData.credential ?? '', options) + const version = getCredentialParam('version', credentialData, nodeData) + const serviceUrl = getCredentialParam('serviceUrl', credentialData, nodeData) + const projectId = getCredentialParam('projectId', credentialData, nodeData) + const watsonxAIAuthType = getCredentialParam('watsonxAIAuthType', credentialData, nodeData) + const watsonxAIApikey = getCredentialParam('watsonxAIApikey', credentialData, nodeData) + const watsonxAIBearerToken = getCredentialParam('watsonxAIBearerToken', credentialData, nodeData) + + const auth = { + version, + serviceUrl, + projectId, + watsonxAIAuthType, + watsonxAIApikey, + watsonxAIBearerToken + } + + const obj: WatsonxInputEmbeddings & WatsonxAuth = { + ...auth, + model: modelName + } + + if (truncateInputTokens) obj.truncateInputTokens = parseInt(truncateInputTokens, 10) + if (maxRetries) obj.maxRetries = parseInt(maxRetries, 10) + if (maxConcurrency) obj.maxConcurrency = parseInt(maxConcurrency, 10) + + const model = new WatsonxEmbeddings(obj) + return model + } +} + +module.exports = { nodeClass: IBMWatsonx_Embeddings } diff --git a/packages/components/nodes/embeddings/IBMWatsonxEmbedding/ibm.png b/packages/components/nodes/embeddings/IBMWatsonxEmbedding/ibm.png new file mode 100644 index 0000000000000000000000000000000000000000..a3a4be5810029b11d16789aaeca68d48e00e6649 GIT binary patch literal 24591 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 iS5i)!+20ia1^h2z2#!}zOc`?k0000