n8n-nodes-rckflr-ner
Version:
N8N node for Named Entity Recognition (NER) using Transformer.js
116 lines • 5.46 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NamedEntityRecognition = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const transformers_1 = require("@huggingface/transformers");
class NamedEntityRecognition {
constructor() {
this.description = {
displayName: 'Named Entity Recognition',
name: 'namedEntityRecognition',
icon: 'fa:tags',
group: ['ai'],
version: 1,
description: 'Extracts named entities (like persons, locations, organizations) from text using Transformers.js.',
defaults: {
name: 'Named Entity Recognition',
},
inputs: ["main" /* NodeConnectionType.Main */],
outputs: ["main" /* NodeConnectionType.Main */],
usableAsTool: true,
properties: [
{
displayName: 'Input Text',
name: 'inputText',
type: 'string',
typeOptions: {
rows: 5,
},
default: '',
required: true,
description: 'The text from which to extract named entities.',
placeholder: 'e.g., N8N is a workflow automation tool based in Berlin, developed by Johannes and a great team.',
},
{
displayName: 'Aggregation Strategy',
name: 'aggregationStrategy',
type: 'options',
options: [
{ name: 'None', value: 'none' },
{ name: 'Simple (Recommended)', value: 'simple' },
{ name: 'First', value: 'first' },
{ name: 'Average', value: 'average' },
{ name: 'Max', value: 'max' },
],
default: 'simple',
description: "Strategy to group token parts (e.g. B-PER, I-PER) into single entities. 'Simple' is often a good default.",
},
{
displayName: 'Output Field Name',
name: 'outputFieldName',
type: 'string',
default: 'entities',
required: true,
description: 'The field name where the array of extracted entities will be stored.',
},
],
};
}
async execute() {
const itemIndex = 0; // We will only ever process one item.
// Define the model to use
const model = 'Xenova/bert-base-NER';
// Get node parameters
const outputFieldName = this.getNodeParameter('outputFieldName', itemIndex, 'entities');
const aggregationStrategy = this.getNodeParameter('aggregationStrategy', itemIndex, 'simple');
const inputText = this.getNodeParameter('inputText', itemIndex, '');
if (!inputText || !inputText.trim()) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Input Text parameter is required. Please provide a static value or an expression.');
}
// Initialize the pipeline (cache it to avoid reloading)
let pipe = NamedEntityRecognition.pipelineCache.get(model);
if (!pipe) {
try {
this.logger.info(`Loading NER model: ${model}`);
pipe = await (0, transformers_1.pipeline)('token-classification', model);
NamedEntityRecognition.pipelineCache.set(model, pipe);
this.logger.info(`NER Model ${model} loaded successfully`);
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load NER model: ${error.message}`);
}
}
// Process the text
try {
this.logger.info(`Extracting entities from text...`);
const pipelineOptions = {};
if (aggregationStrategy && aggregationStrategy !== 'none') {
pipelineOptions.aggregation_strategy = aggregationStrategy;
}
const processedOutput = await pipe(inputText, pipelineOptions);
this.logger.info(`Raw NER output: ${JSON.stringify(processedOutput)}`);
if (!Array.isArray(processedOutput)) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'NER output is not in the expected array format.');
}
const resultJson = {};
resultJson[outputFieldName] = processedOutput;
return [this.helpers.returnJsonArray([{ json: resultJson }])];
}
catch (error) {
if (this.continueOnFail()) {
const errorItem = {
json: {
error: error.message,
},
};
return [this.helpers.returnJsonArray([errorItem])];
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message || String(error));
}
}
}
}
exports.NamedEntityRecognition = NamedEntityRecognition;
NamedEntityRecognition.pipelineCache = new Map();
//# sourceMappingURL=NamedEntityRecognition.node.js.map