snow-flow 2.9.6 → 2.9.7
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.
|
@@ -1375,13 +1375,19 @@ class ServiceNowMachineLearningMCP {
|
|
|
1375
1375
|
// Create tokenizer
|
|
1376
1376
|
const tokenizer = new Map();
|
|
1377
1377
|
let tokenIndex = 1;
|
|
1378
|
-
// Get unique categories
|
|
1379
|
-
|
|
1378
|
+
// Get unique categories with fallback
|
|
1379
|
+
let categories = [...new Set(incidents.map(i => i.category).filter(c => c))];
|
|
1380
|
+
// CRITICAL FIX: Ensure we have at least 2 categories to prevent shape (1,1) error
|
|
1381
|
+
if (categories.length < 2) {
|
|
1382
|
+
categories = [...categories, 'other', 'uncategorized'];
|
|
1383
|
+
this.logger.warn(`Only ${categories.length - 2} unique categories found, added fallback categories`);
|
|
1384
|
+
}
|
|
1385
|
+
this.logger.info(`Training with ${categories.length} categories: ${categories.join(', ')}`);
|
|
1380
1386
|
// Tokenize all text
|
|
1381
1387
|
const sequences = [];
|
|
1382
1388
|
for (const incident of incidents) {
|
|
1383
|
-
const text = `${incident.short_description} ${incident.description}`.toLowerCase();
|
|
1384
|
-
const words = text.split(/\s+/);
|
|
1389
|
+
const text = `${incident.short_description || ''} ${incident.description || ''}`.toLowerCase();
|
|
1390
|
+
const words = text.split(/\s+/).filter(w => w.length > 0);
|
|
1385
1391
|
const sequence = [];
|
|
1386
1392
|
for (const word of words) {
|
|
1387
1393
|
if (!tokenizer.has(word)) {
|
|
@@ -1401,9 +1407,27 @@ class ServiceNowMachineLearningMCP {
|
|
|
1401
1407
|
return [...seq, ...new Array(maxLength - seq.length).fill(0)];
|
|
1402
1408
|
}
|
|
1403
1409
|
});
|
|
1410
|
+
// Create category indices with improved error handling
|
|
1411
|
+
const categoryIndices = incidents.map(incident => {
|
|
1412
|
+
const category = incident.category || 'uncategorized';
|
|
1413
|
+
const index = categories.indexOf(category);
|
|
1414
|
+
if (index >= 0) {
|
|
1415
|
+
return index;
|
|
1416
|
+
}
|
|
1417
|
+
else {
|
|
1418
|
+
// Fallback to 'other' or first category
|
|
1419
|
+
const otherIndex = categories.indexOf('other');
|
|
1420
|
+
return otherIndex >= 0 ? otherIndex : 0;
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
// Validate before creating tensors
|
|
1424
|
+
if (categories.length < 2) {
|
|
1425
|
+
throw new Error(`Insufficient categories for classification: ${categories.length}. Need at least 2 categories.`);
|
|
1426
|
+
}
|
|
1404
1427
|
// Create features and labels
|
|
1405
1428
|
const features = tf.tensor2d(paddedSequences);
|
|
1406
|
-
const labels = tf.oneHot(tf.tensor1d(
|
|
1429
|
+
const labels = tf.oneHot(tf.tensor1d(categoryIndices, 'int32'), categories.length);
|
|
1430
|
+
this.logger.info(`Prepared training data: features [${paddedSequences.length}, ${maxLength}], labels [${incidents.length}, ${categories.length}]`);
|
|
1407
1431
|
return { features, labels, tokenizer, categories };
|
|
1408
1432
|
}
|
|
1409
1433
|
tokenizeText(text, tokenizer, maxLength) {
|
|
@@ -1866,18 +1890,43 @@ class ServiceNowMachineLearningMCP {
|
|
|
1866
1890
|
processBatchWithHashing(incidents, categories, hasher) {
|
|
1867
1891
|
const sequences = [];
|
|
1868
1892
|
const labels = [];
|
|
1893
|
+
// CRITICAL FIX: Ensure we have at least 2 categories to prevent shape (1,1) error
|
|
1894
|
+
const validCategories = [...categories];
|
|
1895
|
+
if (validCategories.length < 2) {
|
|
1896
|
+
validCategories.push('other', 'uncategorized'); // Add fallback categories
|
|
1897
|
+
}
|
|
1898
|
+
this.logger.info(`Processing batch with ${incidents.length} incidents and ${validCategories.length} categories`);
|
|
1869
1899
|
for (const incident of incidents) {
|
|
1870
|
-
const text = `${incident.short_description} ${incident.description}`;
|
|
1900
|
+
const text = `${incident.short_description || ''} ${incident.description || ''}`;
|
|
1871
1901
|
const sequence = hasher(text);
|
|
1872
1902
|
sequences.push(sequence);
|
|
1873
|
-
// One-hot encode category
|
|
1874
|
-
const
|
|
1875
|
-
const
|
|
1903
|
+
// One-hot encode category with improved error handling
|
|
1904
|
+
const category = incident.category || 'uncategorized';
|
|
1905
|
+
const categoryIndex = validCategories.indexOf(category);
|
|
1906
|
+
const label = new Array(validCategories.length).fill(0);
|
|
1876
1907
|
if (categoryIndex >= 0) {
|
|
1877
1908
|
label[categoryIndex] = 1;
|
|
1878
1909
|
}
|
|
1910
|
+
else {
|
|
1911
|
+
// Fallback to 'other' category if not found
|
|
1912
|
+
const otherIndex = validCategories.indexOf('other');
|
|
1913
|
+
if (otherIndex >= 0) {
|
|
1914
|
+
label[otherIndex] = 1;
|
|
1915
|
+
}
|
|
1916
|
+
else {
|
|
1917
|
+
label[0] = 1; // Use first category as fallback
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1879
1920
|
labels.push(label);
|
|
1880
1921
|
}
|
|
1922
|
+
// Validate shapes before creating tensors
|
|
1923
|
+
if (sequences.length === 0 || labels.length === 0) {
|
|
1924
|
+
throw new Error('No valid data for training - empty sequences or labels');
|
|
1925
|
+
}
|
|
1926
|
+
if (labels[0].length < 2) {
|
|
1927
|
+
throw new Error(`Insufficient categories for classification: ${labels[0].length}. Need at least 2 categories.`);
|
|
1928
|
+
}
|
|
1929
|
+
this.logger.info(`Creating tensors: features [${sequences.length}, ${sequences[0]?.length}], labels [${labels.length}, ${labels[0]?.length}]`);
|
|
1881
1930
|
return {
|
|
1882
1931
|
features: tf.tensor2d(sequences),
|
|
1883
1932
|
labels: tf.tensor2d(labels)
|
|
@@ -1967,10 +2016,18 @@ class ServiceNowMachineLearningMCP {
|
|
|
1967
2016
|
const validVocabularySize = Math.max(1000, maxVocabularySize || 5000);
|
|
1968
2017
|
this.logger.info(`Using vocabulary size: ${validVocabularySize} for data preparation`);
|
|
1969
2018
|
const hasher = this.createFeatureHasher(validVocabularySize);
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
2019
|
+
let categories = [...new Set(incidents.map(i => i.category))].filter(c => c); // Filter out empty categories
|
|
2020
|
+
// CRITICAL FIX: Ensure we have at least 2 categories to prevent shape (1,1) error
|
|
2021
|
+
if (categories.length < 2) {
|
|
2022
|
+
if (categories.length === 0) {
|
|
2023
|
+
categories = ['uncategorized', 'other'];
|
|
2024
|
+
}
|
|
2025
|
+
else {
|
|
2026
|
+
categories.push('other');
|
|
2027
|
+
}
|
|
2028
|
+
this.logger.warn(`Insufficient categories found, using fallback categories: ${categories.join(', ')}`);
|
|
1973
2029
|
}
|
|
2030
|
+
this.logger.info(`Processing with ${categories.length} categories: ${categories.join(', ')}`);
|
|
1974
2031
|
const sequences = [];
|
|
1975
2032
|
const labels = [];
|
|
1976
2033
|
for (const incident of incidents) {
|
|
@@ -1985,13 +2042,23 @@ class ServiceNowMachineLearningMCP {
|
|
|
1985
2042
|
return idx;
|
|
1986
2043
|
});
|
|
1987
2044
|
sequences.push(validatedSequence);
|
|
1988
|
-
// One-hot encode category
|
|
2045
|
+
// One-hot encode category with improved error handling
|
|
1989
2046
|
const category = incident.category || 'uncategorized';
|
|
1990
2047
|
const categoryIndex = categories.indexOf(category);
|
|
1991
2048
|
const label = new Array(categories.length).fill(0);
|
|
1992
2049
|
if (categoryIndex >= 0) {
|
|
1993
2050
|
label[categoryIndex] = 1;
|
|
1994
2051
|
}
|
|
2052
|
+
else {
|
|
2053
|
+
// Fallback to 'other' category if not found
|
|
2054
|
+
const otherIndex = categories.indexOf('other');
|
|
2055
|
+
if (otherIndex >= 0) {
|
|
2056
|
+
label[otherIndex] = 1;
|
|
2057
|
+
}
|
|
2058
|
+
else {
|
|
2059
|
+
label[0] = 1; // Use first category as final fallback
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
1995
2062
|
labels.push(label);
|
|
1996
2063
|
}
|
|
1997
2064
|
// Validate sequences before creating tensors
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snow-flow",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.7",
|
|
4
4
|
"description": "Snow-Flow: ServiceNow Advanced Intelligence Platform - 100+ real MCP tools with AI-powered swarm orchestration and neural networks. Dynamic task categorization using AI. Machine learning for incident classification, change risk prediction, and anomaly detection. Zero Mock Data, 100% Real API Integration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "commonjs",
|