UNPKG

n8n-nodes-ionos

Version:

n8n nodes for IONOS DNS, Domain, SSL/Certificate management, Cloud AI, Cloud Infrastructure, Container Registry, Database as a Service, CDN, VPN Gateway, Activity Log, Billing, Logging, Monitoring, Object Storage Management, Network File Storage, Identity

1,250 lines 60.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IonosCloudAi = void 0; const n8n_workflow_1 = require("n8n-workflow"); class IonosCloudAi { description = { displayName: 'IONOS Cloud AI', name: 'ionosCloudAi', icon: 'file:ionos.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', description: 'Interact with IONOS Cloud AI Model Hub API. Developped with Love by Ascenzia (ascenzia.fr)', defaults: { name: 'IONOS Cloud AI', }, inputs: ['main'], outputs: ['main'], credentials: [ { name: 'ionosCloud', required: true, }, ], properties: [ { displayName: 'API Type', name: 'apiType', type: 'options', options: [ { name: 'Native API', value: 'native', description: 'IONOS AI Model Hub native API', }, { name: 'OpenAI Compatible', value: 'openai', description: 'OpenAI-compatible API endpoints', }, ], default: 'native', description: 'The type of API to use for AI Model Hub', }, { displayName: 'Region', name: 'region', type: 'options', options: [ { name: 'Berlin (de-txl)', value: 'de-txl', }, ], default: 'de-txl', description: 'The region for AI Model Hub API', }, { displayName: 'Resource', name: 'resource', type: 'options', noDataExpression: true, displayOptions: { show: { apiType: ['native'], }, }, options: [ { name: 'Foundation Model', value: 'model', }, { name: 'Collection', value: 'collection', }, { name: 'Document', value: 'document', }, ], default: 'model', description: 'Choose a resource for Native API operations', }, { displayName: 'Resource', name: 'resource', type: 'options', noDataExpression: true, displayOptions: { show: { apiType: ['openai'], }, }, options: [ { name: 'OpenAI Compatible', value: 'openai', }, ], default: 'openai', description: 'OpenAI Compatible API endpoints', }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['model'], }, }, options: [ { name: 'Get Many', value: 'getAll', description: 'Get all available models', action: 'Get all models', }, { name: 'Send Request', value: 'predict', description: 'Send a request to an AI model', action: 'Send a request', }, ], default: 'getAll', }, { displayName: 'Model ID', name: 'modelId', type: 'string', required: true, displayOptions: { show: { resource: ['model'], operation: ['predict'], }, }, default: '', placeholder: '4b71d0fe-d992-463e-82a1-de337d88ac2d', description: 'The ID of the model to use for prediction', }, { displayName: 'Input', name: 'input', type: 'string', required: true, displayOptions: { show: { resource: ['model'], operation: ['predict'], }, }, typeOptions: { rows: 4, }, default: '', placeholder: 'Please provide some suggestion names for my business', description: 'The input text for the model', }, { displayName: 'Additional Options', name: 'additionalOptions', type: 'collection', placeholder: 'Add Option', default: {}, displayOptions: { show: { resource: ['model'], operation: ['predict'], }, }, options: [ { displayName: 'Collection ID', name: 'collectionId', type: 'string', default: '', description: 'ID of the collection to use for RAG', }, { displayName: 'Collection Query', name: 'collectionQuery', type: 'string', default: '', description: 'Query for the collection', }, { displayName: 'Max Length', name: 'max_length', type: 'number', default: 300, description: 'Maximum length of the generated text', }, { displayName: 'Temperature', name: 'temperature', type: 'number', default: 0.7, typeOptions: { minValue: 0, maxValue: 2, numberPrecision: 2, }, description: 'Sampling temperature (0-2)', }, ], }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['collection'], }, }, options: [ { name: 'Create', value: 'create', description: 'Create a new collection', action: 'Create a collection', }, { name: 'Delete', value: 'delete', description: 'Delete a collection', action: 'Delete a collection', }, { name: 'Get', value: 'get', description: 'Get a collection', action: 'Get a collection', }, { name: 'Get Many', value: 'getAll', description: 'Get all collections', action: 'Get many collections', }, { name: 'Query', value: 'query', description: 'Query a collection for related content', action: 'Query a collection', }, { name: 'Update', value: 'update', description: 'Update a collection', action: 'Update a collection', }, ], default: 'getAll', }, { displayName: 'Collection Name', name: 'collectionName', type: 'string', required: true, displayOptions: { show: { resource: ['collection'], operation: ['create'], }, }, default: '', placeholder: 'my-collection', description: 'The name of the collection (3-256 characters)', }, { displayName: 'Additional Fields', name: 'additionalFields', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { resource: ['collection'], operation: ['create'], }, }, options: [ { displayName: 'Description', name: 'description', type: 'string', default: '', description: 'Description of the collection (max 1024 characters)', }, { displayName: 'Embedding Model', name: 'embeddingModel', type: 'string', default: 'BAAI/bge-large-en-v1.5', description: 'The embedding model to use', }, { displayName: 'Database Type', name: 'dbType', type: 'options', options: [ { name: 'ChromaDB', value: 'chromadb', }, { name: 'PGVector', value: 'pgvector', }, ], default: 'chromadb', description: 'Type of database to use', }, { displayName: 'Enable Chunking', name: 'enableChunking', type: 'boolean', default: false, description: 'Whether to enable document chunking', }, { displayName: 'Chunk Size', name: 'chunkSize', type: 'number', default: 128, description: 'Size of each chunk (minimum 128)', }, { displayName: 'Chunk Overlap', name: 'chunkOverlap', type: 'number', default: 50, description: 'Overlap between consecutive chunks (minimum 50)', }, ], }, { displayName: 'Collection ID', name: 'collectionId', type: 'string', required: true, displayOptions: { show: { resource: ['collection'], operation: ['get', 'update', 'delete', 'query'], }, }, default: '', placeholder: '550e8400-e29b-41d4-a716-446655440000', description: 'The ID of the collection', }, { displayName: 'Update Fields', name: 'updateFields', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { resource: ['collection'], operation: ['update'], }, }, options: [ { displayName: 'Name', name: 'name', type: 'string', default: '', description: 'The new name of the collection', }, { displayName: 'Description', name: 'description', type: 'string', default: '', description: 'The new description of the collection', }, ], }, { displayName: 'Query', name: 'query', type: 'string', required: true, displayOptions: { show: { resource: ['collection'], operation: ['query'], }, }, typeOptions: { rows: 2, }, default: '', placeholder: 'What is Managed Kubernetes?', description: 'The search query string', }, { displayName: 'Limit', name: 'limit', type: 'number', displayOptions: { show: { resource: ['collection'], operation: ['query'], }, }, default: 10, description: 'Maximum number of matches to return', }, { displayName: 'Return All', name: 'returnAll', type: 'boolean', displayOptions: { show: { resource: ['collection'], operation: ['getAll'], }, }, default: false, description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', name: 'limit', type: 'number', displayOptions: { show: { resource: ['collection'], operation: ['getAll'], returnAll: [false], }, }, typeOptions: { minValue: 1, maxValue: 100, }, default: 50, description: 'Max number of results to return', }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['document'], }, }, options: [ { name: 'Add', value: 'add', description: 'Add documents to a collection', action: 'Add documents', }, { name: 'Delete', value: 'delete', description: 'Delete a document', action: 'Delete a document', }, { name: 'Delete All', value: 'deleteAll', description: 'Delete all documents in a collection', action: 'Delete all documents', }, { name: 'Get', value: 'get', description: 'Get a document', action: 'Get a document', }, { name: 'Get Many', value: 'getAll', description: 'Get all documents in a collection', action: 'Get many documents', }, { name: 'Update', value: 'update', description: 'Update a document', action: 'Update a document', }, ], default: 'getAll', }, { displayName: 'Collection ID', name: 'collectionId', type: 'string', required: true, displayOptions: { show: { resource: ['document'], }, }, default: '', placeholder: '550e8400-e29b-41d4-a716-446655440000', description: 'The ID of the collection', }, { displayName: 'Documents', name: 'documents', type: 'fixedCollection', typeOptions: { multipleValues: true, }, displayOptions: { show: { resource: ['document'], operation: ['add'], }, }, default: {}, placeholder: 'Add Document', options: [ { name: 'documentValues', displayName: 'Document', values: [ { displayName: 'Name', name: 'name', type: 'string', default: '', required: true, description: 'Document name (3-256 characters)', }, { displayName: 'Content', name: 'content', type: 'string', typeOptions: { rows: 4, }, default: '', required: true, description: 'Document content (will be base64 encoded automatically)', }, { displayName: 'Content Type', name: 'contentType', type: 'options', options: [ { name: 'Text/Plain', value: 'text/plain', }, ], default: 'text/plain', description: 'The content type of the document', }, { displayName: 'Description', name: 'description', type: 'string', default: '', description: 'Document description (max 1024 characters)', }, ], }, ], }, { displayName: 'Document ID', name: 'documentId', type: 'string', required: true, displayOptions: { show: { resource: ['document'], operation: ['get', 'update', 'delete'], }, }, default: '', placeholder: '4b71d0fe-d992-463e-82a1-de337d88ac2d', description: 'The ID of the document', }, { displayName: 'Update Fields', name: 'updateFields', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { resource: ['document'], operation: ['update'], }, }, options: [ { displayName: 'Name', name: 'name', type: 'string', default: '', description: 'The new name of the document', }, { displayName: 'Content', name: 'content', type: 'string', typeOptions: { rows: 4, }, default: '', description: 'The new content of the document (will be base64 encoded)', }, { displayName: 'Description', name: 'description', type: 'string', default: '', description: 'The new description of the document', }, ], }, { displayName: 'Return All', name: 'returnAll', type: 'boolean', displayOptions: { show: { resource: ['document'], operation: ['getAll'], }, }, default: false, description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', name: 'limit', type: 'number', displayOptions: { show: { resource: ['document'], operation: ['getAll'], returnAll: [false], }, }, typeOptions: { minValue: 1, maxValue: 100, }, default: 50, description: 'Max number of results to return', }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['openai'], }, }, options: [ { name: 'Chat Completion', value: 'chatCompletion', description: 'Create a chat completion', action: 'Create chat completion', }, { name: 'Completion', value: 'completion', description: 'Create a text completion', action: 'Create completion', }, { name: 'Embedding', value: 'embedding', description: 'Create embeddings', action: 'Create embeddings', }, { name: 'Generate Image', value: 'imageGeneration', description: 'Generate an image', action: 'Generate image', }, { name: 'Get Models', value: 'getModels', description: 'Get available models', action: 'Get models', }, ], default: 'chatCompletion', }, { displayName: 'Model', name: 'model', type: 'string', required: true, displayOptions: { show: { resource: ['openai'], operation: ['chatCompletion'], }, }, default: 'meta-llama/Llama-3.3-70B-Instruct', placeholder: 'meta-llama/Llama-3.3-70B-Instruct', description: 'The model to use for chat completion', }, { displayName: 'Messages', name: 'messages', type: 'fixedCollection', typeOptions: { multipleValues: true, }, displayOptions: { show: { resource: ['openai'], operation: ['chatCompletion'], }, }, default: {}, placeholder: 'Add Message', options: [ { name: 'messageValues', displayName: 'Message', values: [ { displayName: 'Role', name: 'role', type: 'options', options: [ { name: 'System', value: 'system', }, { name: 'User', value: 'user', }, { name: 'Assistant', value: 'assistant', }, ], default: 'user', description: 'The role of the message author', }, { displayName: 'Content', name: 'content', type: 'string', typeOptions: { rows: 2, }, default: '', description: 'The content of the message', }, ], }, ], }, { displayName: 'Additional Options', name: 'additionalOptions', type: 'collection', placeholder: 'Add Option', default: {}, displayOptions: { show: { resource: ['openai'], operation: ['chatCompletion'], }, }, options: [ { displayName: 'Temperature', name: 'temperature', type: 'number', default: 1.0, typeOptions: { minValue: 0, maxValue: 2, numberPrecision: 2, }, description: 'Sampling temperature (0-2)', }, { displayName: 'Max Tokens', name: 'max_tokens', type: 'number', default: 1000, description: 'Maximum number of tokens to generate', }, { displayName: 'Top P', name: 'top_p', type: 'number', default: 1, typeOptions: { minValue: 0, maxValue: 1, numberPrecision: 2, }, description: 'Nucleus sampling parameter', }, ], }, { displayName: 'Model', name: 'model', type: 'string', required: true, displayOptions: { show: { resource: ['openai'], operation: ['completion'], }, }, default: 'meta-llama/Llama-3.3-70B-Instruct', placeholder: 'meta-llama/Llama-3.3-70B-Instruct', description: 'The model to use for completion', }, { displayName: 'Prompt', name: 'prompt', type: 'string', required: true, displayOptions: { show: { resource: ['openai'], operation: ['completion'], }, }, typeOptions: { rows: 4, }, default: '', placeholder: 'Say this is a test', description: 'The prompt to generate completions from', }, { displayName: 'Additional Options', name: 'additionalOptions', type: 'collection', placeholder: 'Add Option', default: {}, displayOptions: { show: { resource: ['openai'], operation: ['completion'], }, }, options: [ { displayName: 'Temperature', name: 'temperature', type: 'number', default: 1.0, typeOptions: { minValue: 0, maxValue: 2, numberPrecision: 2, }, description: 'Sampling temperature (0-2)', }, { displayName: 'Max Tokens', name: 'max_tokens', type: 'number', default: 1000, description: 'Maximum number of tokens to generate', }, ], }, { displayName: 'Model', name: 'model', type: 'string', required: true, displayOptions: { show: { resource: ['openai'], operation: ['embedding'], }, }, default: 'intfloat/e5-large-v2', placeholder: 'intfloat/e5-large-v2', description: 'The model to use for embeddings', }, { displayName: 'Input', name: 'input', type: 'string', required: true, displayOptions: { show: { resource: ['openai'], operation: ['embedding'], }, }, typeOptions: { rows: 2, }, default: '', placeholder: 'The food was delicious and the waiter was friendly.', description: 'The text to create embeddings for', }, { displayName: 'Model', name: 'model', type: 'string', required: true, displayOptions: { show: { resource: ['openai'], operation: ['imageGeneration'], }, }, default: 'stabilityai/stable-diffusion-xl-base-1.0', placeholder: 'stabilityai/stable-diffusion-xl-base-1.0', description: 'The model to use for image generation', }, { displayName: 'Prompt', name: 'prompt', type: 'string', required: true, displayOptions: { show: { resource: ['openai'], operation: ['imageGeneration'], }, }, typeOptions: { rows: 2, }, default: '', placeholder: 'A beautiful sunset over the ocean', description: 'The prompt to generate the image from', }, { displayName: 'Additional Options', name: 'additionalOptions', type: 'collection', placeholder: 'Add Option', default: {}, displayOptions: { show: { resource: ['openai'], operation: ['imageGeneration'], }, }, options: [ { displayName: 'Size', name: 'size', type: 'options', options: [ { name: '1024x1024', value: '1024*1024', }, { name: '1792x1024', value: '1792*1024', }, { name: '1024x1792', value: '1024*1792', }, ], default: '1024*1024', description: 'The size of the image to generate', }, { displayName: 'Number of Images', name: 'n', type: 'number', default: 1, description: 'Number of images to generate', }, ], }, ], }; async execute() { const items = this.getInputData(); const returnData = []; const apiType = this.getNodeParameter('apiType', 0); const region = this.getNodeParameter('region', 0); const resource = this.getNodeParameter('resource', 0); const operation = this.getNodeParameter('operation', 0); const baseURL = apiType === 'openai' ? `https://openai.inference.${region}.ionos.com` : `https://inference.${region}.ionos.com`; for (let i = 0; i < items.length; i++) { try { if (resource === 'model') { if (operation === 'getAll') { const options = { method: 'GET', url: `${baseURL}/models`, headers: { Accept: 'application/json', }, }; const response = await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', options); const models = response.items; models.forEach((model) => { returnData.push({ json: model }); }); } if (operation === 'predict') { const modelId = this.getNodeParameter('modelId', i); const input = this.getNodeParameter('input', i); const additionalOptions = this.getNodeParameter('additionalOptions', i); const body = { type: 'prediction', properties: { input, }, }; const options = {}; if (additionalOptions.max_length) options.max_length = String(additionalOptions.max_length); if (additionalOptions.temperature) options.temperature = String(additionalOptions.temperature); if (Object.keys(options).length > 0) { body.properties.options = options; } if (additionalOptions.collectionId) { body.properties.collectionId = additionalOptions.collectionId; } if (additionalOptions.collectionQuery) { body.properties.collectionQuery = additionalOptions.collectionQuery; } const requestOptions = { method: 'POST', url: `${baseURL}/models/${modelId}/predictions`, headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body, }; const response = await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', requestOptions); returnData.push({ json: response }); } } if (resource === 'collection') { if (operation === 'create') { const collectionName = this.getNodeParameter('collectionName', i); const additionalFields = this.getNodeParameter('additionalFields', i); const body = { type: 'collection', properties: { name: collectionName, }, }; if (additionalFields.description) { body.properties.description = additionalFields.description; } if (additionalFields.embeddingModel) { body.properties.embedding = { model: additionalFields.embeddingModel, }; } if (additionalFields.dbType) { body.properties.engine = { db_type: additionalFields.dbType, }; } if (additionalFields.enableChunking) { const config = {}; if (additionalFields.chunkSize) { config.chunk_size = additionalFields.chunkSize; } if (additionalFields.chunkOverlap) { config.chunk_overlap = additionalFields.chunkOverlap; } const chunking = { enabled: true, strategy: { name: 'fixed_size', config, }, }; body.properties.chunking = chunking; } const options = { method: 'POST', url: `${baseURL}/collections`, headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body, }; const response = await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', options); returnData.push({ json: response }); } if (operation === 'get') { const collectionId = this.getNodeParameter('collectionId', i); const options = { method: 'GET', url: `${baseURL}/collections/${collectionId}`, headers: { Accept: 'application/json', }, }; const response = await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', options); returnData.push({ json: response }); } if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i); const limit = this.getNodeParameter('limit', i, 50); const options = { method: 'GET', url: `${baseURL}/collections`, headers: { Accept: 'application/json', }, qs: { limit: returnAll ? 1000 : limit, }, }; const response = await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', options); const collections = response.items; collections.forEach((collection) => { returnData.push({ json: collection }); }); } if (operation === 'update') { const collectionId = this.getNodeParameter('collectionId', i); const updateFields = this.getNodeParameter('updateFields', i); const body = { properties: {}, }; if (updateFields.name) { body.properties.name = updateFields.name; } if (updateFields.description) { body.properties.description = updateFields.description; } const options = { method: 'PUT', url: `${baseURL}/collections/${collectionId}`, headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body, }; const response = await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', options); returnData.push({ json: response }); } if (operation === 'delete') { const collectionId = this.getNodeParameter('collectionId', i); const options = { method: 'DELETE', url: `${baseURL}/collections/${collectionId}`, headers: { Accept: 'application/json', }, }; await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', options); returnData.push({ json: { success: true, collectionId } }); } if (operation === 'query') { const collectionId = this.getNodeParameter('collectionId', i); const query = this.getNodeParameter('query', i); const limit = this.getNodeParameter('limit', i, 10); const body = { query, limit, }; const options = { method: 'POST', url: `${baseURL}/collections/${collectionId}/query`, headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body, }; const response = await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', options); returnData.push({ json: response }); } } if (resource === 'document') { const collectionId = this.getNodeParameter('collectionId', i); if (operation === 'add') { const documents = this.getNodeParameter('documents', i); const documentValues = documents.documentValues || []; const items = documentValues.map((doc) => { const content = Buffer.from(doc.content, 'utf-8').toString('base64'); return { type: 'document', properties: { name: doc.name, contentType: doc.contentType || 'text/plain', content, ...(doc.description && { description: doc.description }), }, }; }); const body = { type: 'collection', items, }; const options = { method: 'PUT', url: `${baseURL}/collections/${collectionId}/documents`, headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body, }; const response = await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', options); returnData.push({ json: response }); } if (operation === 'get') { const documentId = this.getNodeParameter('documentId', i); const options = { method: 'GET', url: `${baseURL}/collections/${collectionId}/documents/${documentId}`, headers: { Accept: 'application/json', }, }; const response = await this.helpers.httpRequestWithAuthentication.call(this, 'ionosCloud', options); returnData.push({ json: response }); } if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i); const limit = this.getN