n8n-nodes-fasttext-lang 1.0.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.
@@ -0,0 +1,5 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class FastTextNode implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FastTextNode = void 0;
37
+ const n8n_workflow_1 = require("n8n-workflow");
38
+ const path = __importStar(require("path"));
39
+ const fs = __importStar(require("fs"));
40
+ // Переопределяем fetch для корректной работы с путями к файлам
41
+ if (typeof globalThis.fetch === 'function') {
42
+ const originalFetch = globalThis.fetch;
43
+ globalThis.fetch = function (input, init) {
44
+ if (typeof input === 'string') {
45
+ const isLocalFile = (!input.startsWith('http://') &&
46
+ !input.startsWith('https://') &&
47
+ !input.startsWith('file://') &&
48
+ (input.startsWith('/') || input.startsWith('./') || input.startsWith('../') || path.isAbsolute(input)));
49
+ if (isLocalFile) {
50
+ return new Promise(function (resolve, reject) {
51
+ try {
52
+ const bin = fs.readFileSync(input);
53
+ const response = new Response(bin.buffer.slice(bin.byteOffset, bin.byteOffset + bin.byteLength), {
54
+ status: 200,
55
+ statusText: 'OK',
56
+ headers: {
57
+ 'Content-Type': 'application/wasm'
58
+ }
59
+ });
60
+ resolve(response);
61
+ }
62
+ catch (e) {
63
+ reject(e);
64
+ }
65
+ });
66
+ }
67
+ }
68
+ return originalFetch.call(this, input, init);
69
+ };
70
+ }
71
+ const FastText = require('fasttext.js');
72
+ class FastTextNode {
73
+ constructor() {
74
+ this.description = {
75
+ displayName: 'FastText',
76
+ name: 'fastText',
77
+ icon: 'file:fasttext.svg',
78
+ group: ['transform'],
79
+ version: 1,
80
+ subtitle: '={{$parameter["operation"]}}',
81
+ description: 'Detect language using FastText',
82
+ defaults: {
83
+ name: 'FastText',
84
+ },
85
+ inputs: ['main'],
86
+ outputs: ['main'],
87
+ properties: [
88
+ {
89
+ displayName: 'Operation',
90
+ name: 'operation',
91
+ type: 'options',
92
+ noDataExpression: true,
93
+ options: [
94
+ {
95
+ name: 'Detect Language',
96
+ value: 'detectLanguage',
97
+ description: 'Detect the language of the input text',
98
+ action: 'Detect language',
99
+ },
100
+ ],
101
+ default: 'detectLanguage',
102
+ },
103
+ {
104
+ displayName: 'Text',
105
+ name: 'text',
106
+ type: 'string',
107
+ default: '',
108
+ required: true,
109
+ displayOptions: {
110
+ show: {
111
+ operation: ['detectLanguage'],
112
+ },
113
+ },
114
+ description: 'Text to detect language for',
115
+ },
116
+ {
117
+ displayName: 'Model Path',
118
+ name: 'modelPath',
119
+ type: 'string',
120
+ default: '',
121
+ placeholder: 'lid.176.bin',
122
+ displayOptions: {
123
+ show: {
124
+ operation: ['detectLanguage'],
125
+ },
126
+ },
127
+ description: 'Path to FastText language detection model (lid.176.bin). Leave empty to use default.',
128
+ },
129
+ ],
130
+ };
131
+ }
132
+ async execute() {
133
+ const items = this.getInputData();
134
+ const returnData = [];
135
+ const operation = this.getNodeParameter('operation', 0);
136
+ for (let i = 0; i < items.length; i++) {
137
+ try {
138
+ if (operation === 'detectLanguage') {
139
+ const text = this.getNodeParameter('text', i);
140
+ let modelPath = this.getNodeParameter('modelPath', i);
141
+ // Если путь к модели не указан, используем путь по умолчанию
142
+ if (!modelPath) {
143
+ // В n8n используем относительный путь от корня проекта
144
+ modelPath = path.join(process.cwd(), 'lid.176.bin');
145
+ }
146
+ // Проверяем существование модели
147
+ if (!fs.existsSync(modelPath)) {
148
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Model not found at path: ${modelPath}`, {
149
+ itemIndex: i,
150
+ });
151
+ }
152
+ // Создаем экземпляр FastText
153
+ const fastText = new FastText({
154
+ loadModel: modelPath,
155
+ predict: {
156
+ wasm: true,
157
+ mostlikely: 1,
158
+ verbosity: 0,
159
+ normalize: false,
160
+ },
161
+ });
162
+ // Загружаем модель
163
+ await fastText.load();
164
+ // Определяем язык
165
+ const predictions = await fastText.predict(text);
166
+ // Обрабатываем результат
167
+ if (Array.isArray(predictions) && predictions.length > 0) {
168
+ const prediction = predictions[0];
169
+ let label, score;
170
+ if (Array.isArray(prediction)) {
171
+ label = String(prediction[0] || '');
172
+ score = Number(prediction[1] || 0);
173
+ }
174
+ else if (prediction && typeof prediction === 'object') {
175
+ label = String(prediction.label || prediction[0] || '');
176
+ const scoreValue = prediction.score || prediction.probability || prediction.value || prediction[1];
177
+ score = typeof scoreValue === 'string' ? parseFloat(scoreValue) : Number(scoreValue || 0);
178
+ }
179
+ else {
180
+ label = String(prediction || '');
181
+ score = 0;
182
+ }
183
+ // Убираем префикс __label__ если есть
184
+ const cleanLabel = label.replace(/^__label__/, '');
185
+ returnData.push({
186
+ json: {
187
+ language: cleanLabel,
188
+ confidence: score,
189
+ text: text,
190
+ confidencePercent: (score * 100).toFixed(2),
191
+ },
192
+ });
193
+ }
194
+ else {
195
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to detect language', {
196
+ itemIndex: i,
197
+ });
198
+ }
199
+ // Выгружаем модель
200
+ fastText.unload();
201
+ }
202
+ }
203
+ catch (error) {
204
+ if (this.continueOnFail()) {
205
+ const errorMessage = error instanceof Error ? error.message : String(error);
206
+ returnData.push({
207
+ json: {
208
+ error: errorMessage,
209
+ },
210
+ });
211
+ continue;
212
+ }
213
+ throw error;
214
+ }
215
+ }
216
+ return [returnData];
217
+ }
218
+ }
219
+ exports.FastTextNode = FastTextNode;
package/index.js ADDED
@@ -0,0 +1,7 @@
1
+ const FastText = require('./dist/nodes/FastText/FastText.node.js');
2
+
3
+ module.exports = {
4
+ nodes: [
5
+ FastText,
6
+ ],
7
+ };
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "n8n-nodes-fasttext-lang",
3
+ "version": "1.0.0",
4
+ "description": "n8n community node for FastText language detection",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "fasttext",
8
+ "language-detection",
9
+ "nlp"
10
+ ],
11
+ "license": "MIT",
12
+ "homepage": "https://github.com/yourusername/n8n-node-fasttext",
13
+ "author": {
14
+ "name": "Your Name",
15
+ "email": "your.email@example.com"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/yourusername/n8n-node-fasttext.git"
20
+ },
21
+ "main": "index.js",
22
+ "scripts": {
23
+ "build": "tsc && gulp build:icons",
24
+ "dev": "tsc --watch",
25
+ "format": "prettier nodes --write",
26
+ "lint": "eslint nodes",
27
+ "lintfix": "eslint nodes --fix",
28
+ "prepublishOnly": "npm run build && npm run lint -s"
29
+ },
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "n8n": {
34
+ "n8nApiVersion": "1.20.0",
35
+ "nodes": [
36
+ "dist/nodes/FastText/FastText.node.js"
37
+ ]
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.10.0",
41
+ "@typescript-eslint/parser": "^5.45.0",
42
+ "eslint-plugin-n8n-nodes-base": "~1.11.0",
43
+ "gulp": "^4.0.2",
44
+ "n8n-workflow": "*",
45
+ "prettier": "^2.7.1",
46
+ "typescript": "^5.3.3"
47
+ },
48
+ "dependencies": {
49
+ "fasttext.js": "^1.1.4",
50
+ "n8n-workflow": "*"
51
+ },
52
+ "peerDependencies": {
53
+ "n8n-workflow": "*"
54
+ }
55
+ }