n8n-nodes-vlm 2.0.4 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -207,23 +207,23 @@ class VLMComplexityWorkflow {
207
207
  name: 'outputFormat',
208
208
  type: 'options',
209
209
  options: [
210
- {
211
- name: 'Documents Array',
212
- value: 'documents',
213
- description: 'Return classified documents in an array',
214
- },
215
210
  {
216
211
  name: 'Separate Items',
217
212
  value: 'items',
218
- description: 'Return each document as a separate item',
213
+ description: 'Return each document as a separate item (recommended for binary data)',
219
214
  },
220
215
  {
221
216
  name: 'Original Format',
222
217
  value: 'original',
223
218
  description: 'Maintain original input structure with classifications added',
224
219
  },
220
+ {
221
+ name: 'Documents Array',
222
+ value: 'documents',
223
+ description: 'Return classified documents in an array',
224
+ },
225
225
  ],
226
- default: 'documents',
226
+ default: 'items',
227
227
  description: 'How to format the output',
228
228
  },
229
229
  ],
@@ -297,31 +297,88 @@ class VLMComplexityWorkflow {
297
297
  const fieldName = this.getNodeParameter('fieldName', 0);
298
298
  for (let i = 0; i < items.length; i++) {
299
299
  const fieldData = items[i].json[fieldName];
300
+ const extractedDocs = [];
300
301
  if (Array.isArray(fieldData)) {
301
- documents.push(...fieldData);
302
+ extractedDocs.push(...fieldData);
302
303
  }
303
304
  else if (fieldData) {
304
- documents.push(fieldData);
305
+ extractedDocs.push(fieldData);
305
306
  }
307
+ // For each extracted document, also attach binary data if available
308
+ extractedDocs.forEach((doc) => {
309
+ const enhancedDoc = typeof doc === 'object' ? { ...doc } : { content: doc };
310
+ // Extract binary image data from n8n item.binary
311
+ const itemBinary = items[i].binary;
312
+ if (itemBinary) {
313
+ enhancedDoc.metadata = enhancedDoc.metadata || {};
314
+ enhancedDoc.metadata._originalBinary = itemBinary;
315
+ enhancedDoc.metadata._itemIndex = i;
316
+ // Find first image in binary data
317
+ for (const [binaryKey, binaryData] of Object.entries(itemBinary)) {
318
+ const data = binaryData;
319
+ if (data.mimeType && data.mimeType.startsWith('image/')) {
320
+ const base64Data = data.data;
321
+ if (base64Data) {
322
+ enhancedDoc.base64Image = `data:${data.mimeType};base64,${base64Data}`;
323
+ enhancedDoc.metadata._binaryKey = binaryKey;
324
+ this.logger.debug(`Extracted image from binary '${binaryKey}' (${data.mimeType}) for item ${i} (field source)`);
325
+ break;
326
+ }
327
+ }
328
+ }
329
+ }
330
+ documents.push(enhancedDoc);
331
+ });
306
332
  }
307
333
  }
308
334
  else if (documentSource === 'expression') {
309
335
  // Extract from expression
310
336
  for (let i = 0; i < items.length; i++) {
311
337
  const expressionValue = this.getNodeParameter('documentsExpression', i);
338
+ const extractedDocs = [];
312
339
  if (Array.isArray(expressionValue)) {
313
- documents.push(...expressionValue);
340
+ extractedDocs.push(...expressionValue);
314
341
  }
315
342
  else if (expressionValue) {
316
- documents.push(expressionValue);
343
+ extractedDocs.push(expressionValue);
317
344
  }
345
+ // For each extracted document, also attach binary data if available
346
+ extractedDocs.forEach((doc) => {
347
+ const enhancedDoc = typeof doc === 'object' ? { ...doc } : { content: doc };
348
+ // Extract binary image data from n8n item.binary
349
+ const itemBinary = items[i].binary;
350
+ if (itemBinary) {
351
+ enhancedDoc.metadata = enhancedDoc.metadata || {};
352
+ enhancedDoc.metadata._originalBinary = itemBinary;
353
+ enhancedDoc.metadata._itemIndex = i;
354
+ // Find first image in binary data
355
+ for (const [binaryKey, binaryData] of Object.entries(itemBinary)) {
356
+ const data = binaryData;
357
+ if (data.mimeType && data.mimeType.startsWith('image/')) {
358
+ const base64Data = data.data;
359
+ if (base64Data) {
360
+ enhancedDoc.base64Image = `data:${data.mimeType};base64,${base64Data}`;
361
+ enhancedDoc.metadata._binaryKey = binaryKey;
362
+ this.logger.debug(`Extracted image from binary '${binaryKey}' (${data.mimeType}) for item ${i} (expression source)`);
363
+ break;
364
+ }
365
+ }
366
+ }
367
+ }
368
+ documents.push(enhancedDoc);
369
+ });
318
370
  }
319
371
  }
320
372
  if (documents.length === 0) {
321
373
  this.logger.debug('No documents found to classify');
322
374
  return [items];
323
375
  }
324
- this.logger.debug(`Classifying ${documents.length} documents with model: ${model}`);
376
+ // Debug: Log how many documents have images
377
+ const docsWithImages = documents.filter((doc) => doc.base64Image).length;
378
+ this.logger.debug(`Classifying ${documents.length} documents with model: ${model} (${docsWithImages} have images)`);
379
+ if (docsWithImages === 0) {
380
+ this.logger.warn('⚠️ No images found in documents! Binary extraction may have failed. Check that input items have binary data.');
381
+ }
325
382
  try {
326
383
  // Classify documents
327
384
  const classifiedDocs = await (0, vlm_logic_1.classifyDocuments)(this, {
@@ -40,6 +40,7 @@ async function checkServerStatus(context, serverUrl, timeout = 5000) {
40
40
  * Classify a single document's complexity using VLM Classifier API
41
41
  */
42
42
  async function classifyDocumentComplexity(context, serverUrl, document, timeout) {
43
+ var _a, _b, _c, _d, _e, _f, _g;
43
44
  try {
44
45
  // Prepare document content for classification
45
46
  const content = document.pageContent || JSON.stringify(document);
@@ -50,7 +51,12 @@ async function classifyDocumentComplexity(context, serverUrl, document, timeout)
50
51
  };
51
52
  if (hasImage) {
52
53
  requestBody.image = document.image || document.base64Image;
54
+ (_a = context.logger) === null || _a === void 0 ? void 0 : _a.debug(`VLM Classification: Sending request with image (${requestBody.image.substring(0, 50)}...)`);
53
55
  }
56
+ else {
57
+ (_b = context.logger) === null || _b === void 0 ? void 0 : _b.debug('VLM Classification: Sending request without image');
58
+ }
59
+ (_c = context.logger) === null || _c === void 0 ? void 0 : _c.debug(`VLM Classification: Calling ${serverUrl}/api/classify`);
54
60
  const response = await context.helpers.httpRequest({
55
61
  method: 'POST',
56
62
  url: `${serverUrl}/api/classify`,
@@ -62,6 +68,7 @@ async function classifyDocumentComplexity(context, serverUrl, document, timeout)
62
68
  json: true,
63
69
  timeout,
64
70
  });
71
+ (_d = context.logger) === null || _d === void 0 ? void 0 : _d.debug(`VLM Classification: Received response: ${JSON.stringify(response)}`);
65
72
  return {
66
73
  complexity: response.complexity || response.classification || 'LOW',
67
74
  confidence: response.confidence,
@@ -71,10 +78,16 @@ async function classifyDocumentComplexity(context, serverUrl, document, timeout)
71
78
  }
72
79
  catch (error) {
73
80
  // On error, default to LOW complexity to not filter out documents
81
+ (_e = context.logger) === null || _e === void 0 ? void 0 : _e.error(`VLM Classification FAILED: ${error.message}`, ((_f = error.response) === null || _f === void 0 ? void 0 : _f.body) || error);
74
82
  console.warn('Classification failed, defaulting to LOW complexity:', error.message);
83
+ if ((_g = error.response) === null || _g === void 0 ? void 0 : _g.body) {
84
+ console.warn('Error response body:', error.response.body);
85
+ }
75
86
  return {
76
87
  complexity: 'LOW',
77
88
  confidence: 0,
89
+ processingTime: undefined,
90
+ modelUsed: 'ERROR - Classification failed',
78
91
  };
79
92
  }
80
93
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-vlm",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "Vision-Language Models for n8n - Lightweight specialized VLMs for document analysis and classification",
5
5
  "main": "index.js",
6
6
  "author": "Gabriel BRUMENT",