n8n-nodes-fasttext-language-detector 0.1.4 → 0.1.5

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.
@@ -201,25 +201,34 @@ class FastTextLanguageDetector {
201
201
  try {
202
202
  // Используем require для загрузки CommonJS модуля
203
203
  // eslint-disable-next-line @typescript-eslint/no-var-requires
204
- const fastText = require('fasttext.js');
205
- resolve(fastText);
204
+ const FastText = require('fasttext.js');
205
+ resolve(FastText);
206
206
  }
207
207
  catch (error) {
208
208
  reject(error);
209
209
  }
210
210
  });
211
- // Обрабатываем разные варианты экспорта (CommonJS/ESM)
212
- // fasttext.js может экспортировать через default или напрямую
213
- const FastTextClassifier = fastTextModule.Classifier ||
214
- (fastTextModule.default && fastTextModule.default.Classifier) ||
215
- fastTextModule.default;
216
- if (!FastTextClassifier || typeof FastTextClassifier !== 'function') {
211
+ // fasttext.js экспортирует класс FastText напрямую
212
+ const FastTextClass = fastTextModule ||
213
+ fastTextModule.default ||
214
+ (fastTextModule.default && fastTextModule.default.default);
215
+ if (!FastTextClass || typeof FastTextClass !== 'function') {
217
216
  const availableExports = Object.keys(fastTextModule).join(', ');
218
- throw new n8n_workflow_1.ApplicationError(`Failed to load fastText module: Classifier not found. Available exports: ${availableExports}`, { level: 'error' });
217
+ throw new n8n_workflow_1.ApplicationError(`Failed to load fastText module: FastText class not found. Available exports: ${availableExports}`, { level: 'error' });
219
218
  }
220
- const loadedModel = new FastTextClassifier(modelPath);
221
- model = loadedModel;
222
- FastTextLanguageDetector.modelCache.set(modelPath, loadedModel);
219
+ // Создаем экземпляр FastText с путем к модели
220
+ const fastTextInstance = new FastTextClass({
221
+ loadModel: modelPath,
222
+ predict: {
223
+ mostlikely: topK,
224
+ verbosity: 0,
225
+ normalize: false
226
+ }
227
+ });
228
+ // Загружаем модель
229
+ await fastTextInstance.load();
230
+ model = fastTextInstance;
231
+ FastTextLanguageDetector.modelCache.set(modelPath, fastTextInstance);
223
232
  }
224
233
  }
225
234
  catch (error) {
@@ -265,19 +274,48 @@ class FastTextLanguageDetector {
265
274
  throw new n8n_workflow_1.ApplicationError('Model not initialized', { level: 'error' });
266
275
  }
267
276
  // Определяем язык
268
- const predictions = await model.predict(processedText, topK);
277
+ // fasttext.js возвращает массив массивов [label, probability] или массив объектов
278
+ const predictionsRaw = await model.predict(processedText);
279
+ if (!Array.isArray(predictionsRaw) || predictionsRaw.length === 0) {
280
+ throw new n8n_workflow_1.ApplicationError('No predictions returned from fastText model', { level: 'error' });
281
+ }
282
+ // Преобразуем формат ответа fasttext.js в наш формат
283
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
284
+ const predictions = predictionsRaw.map((pred) => {
285
+ // fasttext.js возвращает либо [label, value], либо объект
286
+ let label;
287
+ let probability;
288
+ if (Array.isArray(pred)) {
289
+ label = String(pred[0] || '');
290
+ probability = Number(pred[1] || 0);
291
+ }
292
+ else if (pred && typeof pred === 'object') {
293
+ label = String(pred.label || pred[0] || '');
294
+ probability = Number(pred.value || pred.probability || pred[1] || 0);
295
+ }
296
+ else {
297
+ label = String(pred || '');
298
+ probability = 0;
299
+ }
300
+ // Убираем префикс __label__ если есть
301
+ const cleanLabel = label.replace(/^__label__/, '');
302
+ return {
303
+ label: cleanLabel,
304
+ probability: probability
305
+ };
306
+ });
269
307
  // Фильтруем по порогу уверенности
270
308
  const filteredPredictions = predictions.filter((pred) => pred.probability >= confidenceThreshold);
271
309
  if (filteredPredictions.length === 0) {
272
310
  // Если нет предсказаний выше порога, возвращаем лучшее
273
311
  const result = {
274
312
  ...json,
275
- [outputField]: predictions[0]?.label?.replace('__label__', '') || 'unknown',
313
+ [outputField]: predictions[0]?.label || 'unknown',
276
314
  };
277
315
  if (includeConfidence) {
278
316
  result[`${outputField}Confidence`] = predictions[0]?.probability || 0;
279
317
  result[`${outputField}All`] = predictions.map((p) => ({
280
- language: p.label?.replace('__label__', '') || 'unknown',
318
+ language: p.label || 'unknown',
281
319
  confidence: p.probability || 0,
282
320
  }));
283
321
  }
@@ -288,7 +326,7 @@ class FastTextLanguageDetector {
288
326
  const topPrediction = filteredPredictions[0];
289
327
  const result = {
290
328
  ...json,
291
- [outputField]: topPrediction.label?.replace('__label__', '') || 'unknown',
329
+ [outputField]: topPrediction.label || 'unknown',
292
330
  };
293
331
  if (includeConfidence) {
294
332
  result[`${outputField}Confidence`] = topPrediction.probability || 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-fasttext-language-detector",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "n8n node for language detection using fastText",
5
5
  "author": {
6
6
  "name": "Your Name",