From 85cbfb64c0a2645c833c73a03624fdfd0adf2dab Mon Sep 17 00:00:00 2001 From: Benjamin Schroth <68321970+schrothbn@users.noreply.github.com> Date: Thu, 3 Apr 2025 10:10:16 +0200 Subject: [PATCH] feat: Add support for google vertex embeddings (#14359) Co-authored-by: Oleg Ivaniv --- .../EmbeddingsGoogleVertex.node.ts | 160 ++++++++++++++++++ .../EmbeddingsGoogleVertex/google.svg | 1 + packages/@n8n/nodes-langchain/package.json | 1 + 3 files changed, 162 insertions(+) create mode 100644 packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsGoogleVertex/EmbeddingsGoogleVertex.node.ts create mode 100644 packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsGoogleVertex/google.svg diff --git a/packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsGoogleVertex/EmbeddingsGoogleVertex.node.ts b/packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsGoogleVertex/EmbeddingsGoogleVertex.node.ts new file mode 100644 index 0000000000..3dc1af51cb --- /dev/null +++ b/packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsGoogleVertex/EmbeddingsGoogleVertex.node.ts @@ -0,0 +1,160 @@ +/* eslint-disable n8n-nodes-base/node-dirname-against-convention */ +import { ProjectsClient } from '@google-cloud/resource-manager'; +import { VertexAIEmbeddings } from '@langchain/google-vertexai'; +import { formatPrivateKey } from 'n8n-nodes-base/dist/utils/utilities'; +import { NodeConnectionTypes } from 'n8n-workflow'; +import type { + ILoadOptionsFunctions, + INodeType, + INodeTypeDescription, + ISupplyDataFunctions, + SupplyData, +} from 'n8n-workflow'; + +import { logWrapper } from '@utils/logWrapper'; +import { getConnectionHintNoticeField } from '@utils/sharedFields'; + +export class EmbeddingsGoogleVertex implements INodeType { + methods = { + listSearch: { + async gcpProjectsList(this: ILoadOptionsFunctions) { + const results: Array<{ name: string; value: string }> = []; + + const credentials = await this.getCredentials('googleApi'); + const privateKey = formatPrivateKey(credentials.privateKey as string); + const email = (credentials.email as string).trim(); + + const client = new ProjectsClient({ + credentials: { + client_email: email, + private_key: privateKey, + }, + }); + + const [projects] = await client.searchProjects(); + + for (const project of projects) { + if (project.projectId) { + results.push({ + name: project.displayName ?? project.projectId, + value: project.projectId, + }); + } + } + + return { results }; + }, + }, + }; + + description: INodeTypeDescription = { + displayName: 'Embeddings Google Vertex', + name: 'embeddingsGoogleVertex', + icon: 'file:google.svg', + group: ['transform'], + version: 1, + description: 'Use Google Vertex Embeddings', + defaults: { + name: 'Embeddings Google Vertex', + }, + requestDefaults: { + ignoreHttpStatusErrors: true, + baseURL: '={{ $credentials.host }}', + }, + credentials: [ + { + name: 'googleApi', + required: true, + }, + ], + codex: { + categories: ['AI'], + subcategories: { + AI: ['Embeddings'], + }, + resources: { + primaryDocumentation: [ + { + url: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.embeddingsgooglevertex/', + }, + ], + }, + }, + // eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node + inputs: [], + // eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong + outputs: [NodeConnectionTypes.AiEmbedding], + outputNames: ['Embeddings'], + + properties: [ + getConnectionHintNoticeField([NodeConnectionTypes.AiVectorStore]), + { + displayName: + 'Each model is using different dimensional density for embeddings. Please make sure to use the same dimensionality for your vector store. The default model is using 768-dimensional embeddings. You can find available models here.', + name: 'notice', + type: 'notice', + default: '', + }, + { + displayName: 'Project ID', + name: 'projectId', + type: 'resourceLocator', + default: { mode: 'list', value: '' }, + required: true, + description: 'Select or enter your Google Cloud project ID', + modes: [ + { + displayName: 'From List', + name: 'list', + type: 'list', + typeOptions: { + searchListMethod: 'gcpProjectsList', + }, + }, + { + displayName: 'ID', + name: 'id', + type: 'string', + }, + ], + }, + { + displayName: 'Model Name', + name: 'modelName', + type: 'string', + description: + 'The model which will generate the embeddings. Learn more.', + default: 'text-embedding-005', + }, + ], + }; + + async supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise { + const credentials = await this.getCredentials('googleApi'); + const privateKey = formatPrivateKey(credentials.privateKey as string); + const email = (credentials.email as string).trim(); + const region = credentials.region as string; + + const modelName = this.getNodeParameter('modelName', itemIndex) as string; + + const projectId = this.getNodeParameter('projectId', itemIndex, '', { + extractValue: true, + }) as string; + + const embeddings = new VertexAIEmbeddings({ + authOptions: { + projectId, + credentials: { + client_email: email, + private_key: privateKey, + }, + }, + location: region, + model: modelName, + }); + + return { + response: logWrapper(embeddings, this), + }; + } +} diff --git a/packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsGoogleVertex/google.svg b/packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsGoogleVertex/google.svg new file mode 100644 index 0000000000..38f3c22592 --- /dev/null +++ b/packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsGoogleVertex/google.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/@n8n/nodes-langchain/package.json b/packages/@n8n/nodes-langchain/package.json index 17a5122aa1..91f4407870 100644 --- a/packages/@n8n/nodes-langchain/package.json +++ b/packages/@n8n/nodes-langchain/package.json @@ -61,6 +61,7 @@ "dist/nodes/embeddings/EmbeddingsAwsBedrock/EmbeddingsAwsBedrock.node.js", "dist/nodes/embeddings/EmbeddingsAzureOpenAi/EmbeddingsAzureOpenAi.node.js", "dist/nodes/embeddings/EmbeddingsGoogleGemini/EmbeddingsGoogleGemini.node.js", + "dist/nodes/embeddings/EmbeddingsGoogleVertex/EmbeddingsGoogleVertex.node.js", "dist/nodes/embeddings/EmbeddingsHuggingFaceInference/EmbeddingsHuggingFaceInference.node.js", "dist/nodes/embeddings/EmbeddingsMistralCloud/EmbeddingsMistralCloud.node.js", "dist/nodes/embeddings/EmbeddingsOpenAI/EmbeddingsOpenAi.node.js",