UNPKG

n8n-nodes-sap-ai-core

Version:

n8n nodes for SAP AI Core LLM and embeddings integration

335 lines 16 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.SapAiCoreEmbeddings = void 0; const n8n_workflow_1 = require("n8n-workflow"); class SapAiCoreEmbeddings { constructor() { this.description = { displayName: 'SAP AI Core Embeddings', name: 'sapAiCoreEmbeddings', icon: 'file:sapaicore.svg', group: ['transform'], version: 1, description: 'Use SAP AI Core for text embeddings with vector stores', defaults: { name: 'SAP AI Core Embeddings', }, codex: { categories: ['AI'], subcategories: { AI: ['Embeddings'], }, resources: { primaryDocumentation: [ { url: 'https://help.sap.com/docs/sap-ai-core', }, ], }, }, inputs: [], outputs: ["ai_embedding" /* NodeConnectionType.AiEmbedding */], outputNames: ['Embeddings'], credentials: [ { name: 'sapAiCoreApi', required: true, }, ], properties: [ { displayName: 'Use this node to connect SAP AI Core embeddings to vector stores and other AI components.', name: 'notice', type: 'notice', default: '', }, { displayName: 'Model', name: 'model', type: 'options', default: 'text-embedding-ada-002', description: 'The embedding model to use', required: true, options: [ { name: 'Text Embedding Ada 002', value: 'text-embedding-ada-002', description: 'OpenAI ada-002 embedding model (1536 dimensions)', }, { name: 'Text Embedding 3 Small', value: 'text-embedding-3-small', description: 'OpenAI text-embedding-3-small (configurable dimensions)', }, { name: 'Text Embedding 3 Large', value: 'text-embedding-3-large', description: 'OpenAI text-embedding-3-large (configurable dimensions)', }, ], }, { displayName: 'Deployment ID', name: 'deploymentId', type: 'string', default: '', description: 'SAP AI Core deployment ID for the embedding model', required: true, placeholder: 'e.g., dabcd1234567890', }, { displayName: 'Resource Group', name: 'resourceGroup', type: 'string', default: 'default', description: 'SAP AI Core resource group (optional, uses default if not specified)', required: false, }, { displayName: 'Options', name: 'options', placeholder: 'Add Option', description: 'Additional options to add', type: 'collection', default: {}, options: [ { displayName: 'Batch Size', name: 'batchSize', type: 'number', default: 512, typeOptions: { maxValue: 2048, minValue: 1, }, description: 'Maximum number of documents to send in each request', }, { displayName: 'Dimensions', name: 'dimensions', type: 'options', default: undefined, description: 'Number of dimensions for the embeddings (only supported in text-embedding-3 models)', options: [ { name: '256', value: 256, }, { name: '512', value: 512, }, { name: '1024', value: 1024, }, { name: '1536', value: 1536, }, { name: '3072', value: 3072, }, ], displayOptions: { show: { '/model': ['text-embedding-3-small', 'text-embedding-3-large'], }, }, }, { displayName: 'Strip New Lines', name: 'stripNewLines', type: 'boolean', default: true, description: 'Whether to strip new lines from the input text', }, { displayName: 'Timeout', name: 'timeout', type: 'number', default: 60000, description: 'Request timeout in milliseconds', }, { displayName: 'Max Retries', name: 'maxRetries', type: 'number', default: 2, description: 'Maximum number of retries for failed requests', }, ], }, ], }; } async supplyData(itemIndex) { try { // Import SAP AI SDK and n8n utilities const { AzureOpenAiEmbeddingClient } = await Promise.resolve().then(() => __importStar(require('@sap-ai-sdk/langchain'))); // Get parameters const credentials = await this.getCredentials('sapAiCoreApi'); const model = this.getNodeParameter('model', itemIndex); const deploymentId = this.getNodeParameter('deploymentId', itemIndex); const resourceGroup = this.getNodeParameter('resourceGroup', itemIndex, 'default'); const options = this.getNodeParameter('options', itemIndex, {}); // Set up environment for SAP AI SDK authentication process.env.AICORE_SERVICE_KEY = JSON.stringify({ clientid: credentials.clientId, clientsecret: credentials.clientSecret, url: credentials.oauthUrl, serviceurls: { AI_API_URL: credentials.baseUrl }, ai_api_url: credentials.baseUrl }); // Validate required credentials if (!credentials.clientId || !credentials.clientSecret || !credentials.oauthUrl || !credentials.baseUrl) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Incomplete SAP AI Core credentials. Please ensure all fields are filled:\n' + '- Client ID\n- Client Secret\n- OAuth URL\n- Base URL', { itemIndex }); } // Validate deployment ID if (!deploymentId || deploymentId.trim() === '') { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Deployment ID is required. Please provide your SAP AI Core embedding deployment ID.', { itemIndex }); } // Prepare embedding configuration (keeping original working config) const embeddingConfig = { modelName: model, deploymentId: deploymentId, resourceGroup: resourceGroup, }; // Add dimensions if specified (for text-embedding-3 models) if (options.dimensions && (model === 'text-embedding-3-small' || model === 'text-embedding-3-large')) { embeddingConfig.dimensions = options.dimensions; } // Add other options if (options.batchSize) { embeddingConfig.batchSize = options.batchSize; } if (options.stripNewLines !== undefined) { embeddingConfig.stripNewLines = options.stripNewLines; } // Create SAP AI SDK embeddings client let sapEmbeddings; try { sapEmbeddings = new AzureOpenAiEmbeddingClient(embeddingConfig); // Test the client initialization if (!sapEmbeddings) { throw new Error('Client creation returned null/undefined'); } if (typeof sapEmbeddings.embedQuery !== 'function') { throw new Error(`embedQuery method not available. Client type: ${typeof sapEmbeddings}, methods: ${Object.keys(sapEmbeddings || {}).join(', ')}`); } if (typeof sapEmbeddings.embedDocuments !== 'function') { throw new Error(`embedDocuments method not available. Client methods: ${Object.keys(sapEmbeddings || {}).join(', ')}`); } } catch (clientError) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to create SAP AI Core embeddings client: ${clientError instanceof Error ? clientError.message : String(clientError)}. Please check your SAP AI Core credentials and configuration.`, { itemIndex }); } // Create a wrapper that implements the full LangChain Embeddings interface const { Embeddings } = await Promise.resolve().then(() => __importStar(require('@langchain/core/embeddings'))); class SapEmbeddingsWrapper extends Embeddings { constructor(sapClient) { super({}); this.sapClient = sapClient; if (!this.sapClient) { throw new Error('SAP client is null or undefined'); } } async embedDocuments(texts) { if (!this.sapClient) { throw new Error('SAP client is not initialized'); } try { const result = await this.sapClient.embedDocuments(texts); return result; } catch (error) { throw new Error(`SAP embedDocuments failed: ${error instanceof Error ? error.message : String(error)}`); } } async embedQuery(text) { if (!this.sapClient) { throw new Error('SAP client is not initialized'); } try { const result = await this.sapClient.embedQuery(text); return result; } catch (error) { throw new Error(`SAP embedQuery failed: ${error instanceof Error ? error.message : String(error)}`); } } } const embeddings = new SapEmbeddingsWrapper(sapEmbeddings); // Import logWrapper for execution tracking (using local copy) try { const { logWrapper } = await Promise.resolve().then(() => __importStar(require('../../utils/logWrapper'))); const wrappedEmbeddings = logWrapper(embeddings, this); return { response: wrappedEmbeddings, }; } catch (logWrapperError) { // Fallback to unwrapped embeddings if logWrapper fails return { response: embeddings, }; } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; if (errorMessage.includes('Cannot find module') && errorMessage.includes('@sap-ai-sdk/langchain')) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'SAP AI SDK LangChain package is required. Please install it with:\n' + 'npm install @sap-ai-sdk/langchain', { itemIndex }); } // Enhanced error handling for SAP AI Core specific issues if (errorMessage.includes('authentication') || errorMessage.includes('401')) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'SAP AI Core authentication failed. Please check your credentials:\n' + '- Client ID\n- Client Secret\n- OAuth URL\n- Base URL', { itemIndex }); } if (errorMessage.includes('deployment') || errorMessage.includes('404')) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'SAP AI Core deployment not found. Please check:\n' + '- Deployment ID is correct\n- Model is deployed and active\n- Resource group has access', { itemIndex }); } throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to initialize SAP AI Core Embeddings: ${errorMessage}`, { itemIndex }); } } } exports.SapAiCoreEmbeddings = SapAiCoreEmbeddings; //# sourceMappingURL=SapAiCoreEmbeddings.node.js.map