UNPKG

n8n-nodes-local-ai-stack

Version:

n8n custom nodes for AI services including image captionning, OCR, face detection, and more AI-powered features

238 lines (237 loc) 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AIHub = void 0; class AIHub { constructor() { this.description = { displayName: "Local AI Stack", name: "localAIStack", icon: "file:local_ai_stack.png", group: ["transform"], version: 1, description: "Local AI Stack services", subtitle: '={{ $parameter["services"] && $parameter["services"].length > 0 ' + '? $parameter["services"].join(", ") ' + ': "[Aucun service sélectionné]" }}', defaults: { name: "Local AI Stack", }, inputs: ["main"], outputs: ["main"], properties: [ { displayName: "🚀 Débloquez des fonctionnalités Premium : Audio Transcription, Vision LLM, Text-to-Speech, traitement d'images/vidéos avancé, Embeddings multimodaux, Vector DB et plus encore. <a href='https://tally.so/r/w76z7A' target='_blank'>Rejoignez la liste d'attente ici</a>", name: "premiumNotice", type: "notice", default: "", }, { displayName: "Services", name: "services", type: "multiOptions", options: [ { name: "Extract Text from an image", value: "ocr", description: "Extract text from images using OCR", }, { name: "Describe an image", value: "image_caption", description: "Generate a caption describing the content of an image", }, { name: "Detect Faces from an image", value: "faces", description: "Detect and analyze faces in images", }, { name: "💎 Audio Transcription (Speech-to-Text)", value: "audio_transcription", description: "Premium feature - Not available in free tier", }, { name: "💎 Visual Question Answering (Vision LLM)", value: "visual_qa", description: "Premium feature - Not available in free tier", }, { name: "💎 Text-to-Speech", value: "text_to_speech", description: "Premium feature - Not available in free tier", }, { name: "💎 Image Utils (Upscale, Edit...)", value: "image_utils", description: "Premium feature - Not available in free tier", }, { name: "💎 Video Utils (Trim, Edit...)", value: "video_utils", description: "Premium feature - Not available in free tier", }, { name: "💎 Multimodal Embeddings (Text-Image Similarity...)", value: "multimodal_embeddings", description: "Premium feature - Not available in free tier", }, { name: "💎 Vector DB", value: "vector_db", description: "Premium feature - Not available in free tier", }, ], default: ["ocr"], required: true, description: "Select one or more AI services to use (they will run in parallel)", }, { displayName: "Image Source", name: "imageSource", type: "options", options: [ { name: "URL", value: "url", }, { name: "Upload File", value: "file", }, ], default: "url", description: "Choose whether to provide an image URL or upload a file", }, { displayName: "Image URL", name: "imageUrl", type: "string", default: "", placeholder: "https://example.com/image.jpg", required: true, description: "URL of the image to send to the AI service", displayOptions: { show: { imageSource: ["url"], }, }, }, { displayName: "Image File", name: "imageFile", type: "string", default: "data", required: true, description: "The input binary field containing the image file to process", displayOptions: { show: { imageSource: ["file"], }, }, hint: "The name of the binary property that contains the image data", }, { displayName: "Server URL", name: "serverUrl", type: "string", default: "http://127.0.0.1:9454", placeholder: "http://127.0.0.1:9454", required: false, description: "AI-Hub server URL (optional)", }, ], }; } async execute() { const items = this.getInputData(); const returnData = []; // Liste des services premium const premiumServices = ["audio_transcription", "visual_qa", "text_to_speech", "image_utils", "video_utils", "multimodal_embeddings", "vector_db"]; for (let i = 0; i < items.length; i++) { try { const serverUrl = this.getNodeParameter("serverUrl", i, "http://localhost:9454"); const services = this.getNodeParameter("services", i); const imageSource = this.getNodeParameter("imageSource", i); // Vérifier si des services premium sont sélectionnés const selectedPremiumServices = services.filter((service) => premiumServices.includes(service)); if (selectedPremiumServices.length > 0) { throw new Error("⚠️ Les services suivants ne sont disponibles qu'en version Premium : " + selectedPremiumServices.join(", ") + ". " + "Rejoignez notre liste d'attente pour être parmi les premiers à bénéficier de ces fonctionnalités : https://tally.so/r/w76z7A"); } // Build the base URL const baseUrl = serverUrl.endsWith("/") ? serverUrl.slice(0, -1) : serverUrl; // Fonction pour exécuter un service const executeService = async (service) => { const fullUrl = `${baseUrl}/${service}/detect`; if (imageSource === "url") { // Use image URL const imageUrl = this.getNodeParameter("imageUrl", i); return await this.helpers.request({ method: "POST", uri: fullUrl, body: { image_url: imageUrl }, json: true, }); } else { // Use uploaded file const binaryPropertyName = this.getNodeParameter("imageFile", i); const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName); const buffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName); return await this.helpers.request({ method: "POST", uri: fullUrl, formData: { image_file: { value: buffer, options: { filename: binaryData.fileName || "image.jpg", contentType: binaryData.mimeType || "image/jpeg", }, }, }, json: true, }); } }; // Exécuter tous les services en parallèle const results = await Promise.all(services.map(async (service) => { try { const result = await executeService(service); return { service, result, error: null }; } catch (error) { return { service, result: null, error: error.message }; } })); // Si une erreur est présente dans un service, arrêter et lancer une exception for (const { service, error } of results) { if (error) { throw new Error(`Erreur lors de l'exécution du service '${service}': ${error}`); } } // Si tout est OK, merger les résultats normalement const mergedResults = {}; for (const { service, result } of results) { mergedResults[service] = result; } returnData.push({ json: mergedResults, }); } catch (error) { if (this.continueOnFail()) { returnData.push({ json: { error: error.message, }, }); continue; } throw error; } } return [returnData]; } } exports.AIHub = AIHub;