n8n-nodes-vlm 3.1.2 → 3.2.0
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.
|
@@ -91,6 +91,25 @@ class VLMComplexityWorkflow {
|
|
|
91
91
|
placeholder: 'Add Option',
|
|
92
92
|
default: {},
|
|
93
93
|
options: [
|
|
94
|
+
{
|
|
95
|
+
displayName: 'Image Source',
|
|
96
|
+
name: 'imageSource',
|
|
97
|
+
type: 'options',
|
|
98
|
+
options: [
|
|
99
|
+
{
|
|
100
|
+
name: 'From Binary',
|
|
101
|
+
value: 'binary',
|
|
102
|
+
description: 'Extract image from binary field (n8n standard)',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'From Base64 Field',
|
|
106
|
+
value: 'base64field',
|
|
107
|
+
description: 'Use base64 string from JSON field (with or without Data URI prefix)',
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
default: 'binary',
|
|
111
|
+
description: 'Where to get the image data from',
|
|
112
|
+
},
|
|
94
113
|
{
|
|
95
114
|
displayName: 'Binary Field',
|
|
96
115
|
name: 'binaryField',
|
|
@@ -99,13 +118,40 @@ class VLMComplexityWorkflow {
|
|
|
99
118
|
placeholder: 'e.g. data (auto-detect if empty)',
|
|
100
119
|
description: 'Name of the binary field to use for classification. Leave empty to auto-detect first image.',
|
|
101
120
|
},
|
|
121
|
+
{
|
|
122
|
+
displayName: 'Base64 Field',
|
|
123
|
+
name: 'base64Field',
|
|
124
|
+
type: 'string',
|
|
125
|
+
default: 'data',
|
|
126
|
+
placeholder: 'e.g. data, base64Image',
|
|
127
|
+
description: 'JSON field containing base64 string (auto-detects Data URI prefix)',
|
|
128
|
+
},
|
|
102
129
|
{
|
|
103
130
|
displayName: 'Output Base64 Field',
|
|
104
131
|
name: 'outputBase64Field',
|
|
105
132
|
type: 'string',
|
|
106
133
|
default: '',
|
|
107
134
|
placeholder: 'e.g. base64Image',
|
|
108
|
-
description: 'If set, the base64 image
|
|
135
|
+
description: 'If set, the base64 image will be added to output JSON under this field name.',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
displayName: 'Output Base64 Format',
|
|
139
|
+
name: 'outputBase64Format',
|
|
140
|
+
type: 'options',
|
|
141
|
+
options: [
|
|
142
|
+
{
|
|
143
|
+
name: 'Raw Base64',
|
|
144
|
+
value: 'raw',
|
|
145
|
+
description: 'iVBORw0KGgo... (like n8n native)',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'Data URI',
|
|
149
|
+
value: 'datauri',
|
|
150
|
+
description: 'data:image/png;base64,iVBORw0KGgo...',
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
default: 'raw',
|
|
154
|
+
description: 'Format of the base64 output (only applies if Output Base64 Field is set)',
|
|
109
155
|
},
|
|
110
156
|
{
|
|
111
157
|
displayName: 'Request Timeout (ms)',
|
|
@@ -140,8 +186,11 @@ class VLMComplexityWorkflow {
|
|
|
140
186
|
const model = this.getNodeParameter('model', 0);
|
|
141
187
|
const options = this.getNodeParameter('options', 0, {});
|
|
142
188
|
const timeout = (_a = options.timeout) !== null && _a !== void 0 ? _a : 30000;
|
|
189
|
+
const imageSource = options.imageSource || 'binary';
|
|
143
190
|
const binaryField = options.binaryField || '';
|
|
191
|
+
const base64Field = options.base64Field || 'data';
|
|
144
192
|
const outputBase64Field = options.outputBase64Field || '';
|
|
193
|
+
const outputBase64Format = options.outputBase64Format || 'raw';
|
|
145
194
|
// Verify server has classifier capability (optional check)
|
|
146
195
|
const status = await (0, vlm_logic_1.checkServerStatus)(this, serverUrl, timeout);
|
|
147
196
|
if (status.status === 'error') {
|
|
@@ -156,31 +205,59 @@ class VLMComplexityWorkflow {
|
|
|
156
205
|
// Process each input item
|
|
157
206
|
for (let i = 0; i < items.length; i++) {
|
|
158
207
|
const item = items[i];
|
|
159
|
-
// Extract base64 image
|
|
160
|
-
let base64Image;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
208
|
+
// Extract base64 image - track both raw and Data URI formats
|
|
209
|
+
let base64Image; // Data URI format for API
|
|
210
|
+
let rawBase64; // Raw base64 without prefix
|
|
211
|
+
let mimeType = 'image/png';
|
|
212
|
+
if (imageSource === 'base64field') {
|
|
213
|
+
// Extract from JSON field
|
|
214
|
+
const fieldValue = item.json[base64Field];
|
|
215
|
+
if (fieldValue) {
|
|
216
|
+
// Auto-detect if it's already a Data URI
|
|
217
|
+
const dataUriMatch = fieldValue.match(/^data:([^;]+);base64,(.+)$/);
|
|
218
|
+
if (dataUriMatch) {
|
|
219
|
+
mimeType = dataUriMatch[1];
|
|
220
|
+
rawBase64 = dataUriMatch[2];
|
|
221
|
+
base64Image = fieldValue; // Already in Data URI format
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
// Raw base64, wrap in Data URI
|
|
225
|
+
rawBase64 = fieldValue;
|
|
226
|
+
base64Image = `data:${mimeType};base64,${rawBase64}`;
|
|
168
227
|
}
|
|
228
|
+
this.logger.debug(`Item ${i}: Using base64 from JSON field '${base64Field}' (${mimeType})`);
|
|
169
229
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
// Extract from binary (default)
|
|
233
|
+
if (item.binary) {
|
|
234
|
+
if (binaryField && item.binary[binaryField]) {
|
|
235
|
+
// Use specified binary field
|
|
236
|
+
const data = item.binary[binaryField];
|
|
237
|
+
if (data.data) {
|
|
238
|
+
mimeType = data.mimeType || 'image/png';
|
|
239
|
+
rawBase64 = data.data;
|
|
240
|
+
base64Image = `data:${mimeType};base64,${rawBase64}`;
|
|
241
|
+
this.logger.debug(`Item ${i}: Using specified binary field '${binaryField}' (${mimeType})`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
// Auto-detect first image (default behavior)
|
|
246
|
+
for (const [binaryKey, binaryData] of Object.entries(item.binary)) {
|
|
247
|
+
const data = binaryData;
|
|
248
|
+
if (data.mimeType && data.mimeType.startsWith('image/') && data.data) {
|
|
249
|
+
mimeType = data.mimeType;
|
|
250
|
+
rawBase64 = data.data;
|
|
251
|
+
base64Image = `data:${mimeType};base64,${rawBase64}`;
|
|
252
|
+
this.logger.debug(`Item ${i}: Auto-detected image from binary '${binaryKey}' (${mimeType})`);
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
178
255
|
}
|
|
179
256
|
}
|
|
180
257
|
}
|
|
181
258
|
}
|
|
182
259
|
if (!base64Image) {
|
|
183
|
-
this.logger.warn(`Item ${i}: No image found
|
|
260
|
+
this.logger.warn(`Item ${i}: No image found (source: ${imageSource})`);
|
|
184
261
|
}
|
|
185
262
|
// Classify the document
|
|
186
263
|
const classification = await (0, vlm_logic_1.classifySingleDocument)(this, {
|
|
@@ -189,6 +266,8 @@ class VLMComplexityWorkflow {
|
|
|
189
266
|
timeout,
|
|
190
267
|
});
|
|
191
268
|
this.logger.debug(`Item ${i}: Classified as ${classification.complexity} (confidence: ${classification.confidence})`);
|
|
269
|
+
// Determine base64 output value based on format preference
|
|
270
|
+
const outputBase64Value = outputBase64Format === 'raw' ? rawBase64 : base64Image;
|
|
192
271
|
// Build output item with BOTH json AND binary
|
|
193
272
|
const outputItem = {
|
|
194
273
|
json: {
|
|
@@ -201,8 +280,8 @@ class VLMComplexityWorkflow {
|
|
|
201
280
|
...item.json,
|
|
202
281
|
// Item tracking
|
|
203
282
|
_itemIndex: i,
|
|
204
|
-
// Optional: include base64 in output JSON
|
|
205
|
-
...(outputBase64Field &&
|
|
283
|
+
// Optional: include base64 in output JSON (format depends on outputBase64Format)
|
|
284
|
+
...(outputBase64Field && outputBase64Value ? { [outputBase64Field]: outputBase64Value } : {}),
|
|
206
285
|
},
|
|
207
286
|
// ALWAYS preserve binary data
|
|
208
287
|
binary: item.binary,
|
package/package.json
CHANGED