snow-flow 2.8.4 → 2.8.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.
|
@@ -505,7 +505,9 @@ class ServiceNowMachineLearningMCP {
|
|
|
505
505
|
* Uses PI if available, otherwise uses custom TensorFlow.js
|
|
506
506
|
*/
|
|
507
507
|
async trainIncidentClassifier(args) {
|
|
508
|
-
const { sample_size = 1000, epochs = 50, validation_split = 0.2, query = '', intelligent_selection = true, focus_categories = [], batch_size = 100,
|
|
508
|
+
const { sample_size = 1000, epochs = 50, validation_split = 0.2, query = '', intelligent_selection = true, focus_categories = [], batch_size = 100, streaming_mode = true } = args;
|
|
509
|
+
// CRITICAL FIX: Ensure max_vocabulary_size is ALWAYS valid
|
|
510
|
+
const max_vocabulary_size = Math.max(1000, args.max_vocabulary_size || 5000);
|
|
509
511
|
try {
|
|
510
512
|
// Wait for ML API check if not complete
|
|
511
513
|
if (!this.mlAPICheckComplete) {
|
|
@@ -626,18 +628,22 @@ class ServiceNowMachineLearningMCP {
|
|
|
626
628
|
}]
|
|
627
629
|
};
|
|
628
630
|
}
|
|
629
|
-
// Get vocabulary size from tokenizer Map
|
|
630
|
-
const vocabularySize = tokenizer.get('_vocabulary_size')
|
|
631
|
+
// Get vocabulary size from tokenizer Map - MUST match the size used in prepareIncidentDataOptimized
|
|
632
|
+
const vocabularySize = tokenizer.get('_vocabulary_size');
|
|
631
633
|
if (!vocabularySize || vocabularySize <= 0) {
|
|
632
|
-
throw new Error(
|
|
634
|
+
throw new Error(`Invalid vocabulary size from tokenizer: ${vocabularySize}. Cannot create embedding layer.`);
|
|
635
|
+
}
|
|
636
|
+
// CRITICAL: Validate vocabulary size is reasonable
|
|
637
|
+
if (vocabularySize < 1000) {
|
|
638
|
+
this.logger.warn(`Vocabulary size ${vocabularySize} is very small, using minimum of 1000`);
|
|
633
639
|
}
|
|
634
640
|
this.logger.info(`Creating model with vocabulary size: ${vocabularySize}, categories: ${categories.length}`);
|
|
635
|
-
// Create neural network model
|
|
641
|
+
// Create neural network model with VALIDATED vocabulary size
|
|
636
642
|
const model = tf.sequential({
|
|
637
643
|
layers: [
|
|
638
|
-
// Embedding layer for text
|
|
644
|
+
// Embedding layer for text - inputDim MUST match the vocabulary size used in data preparation
|
|
639
645
|
tf.layers.embedding({
|
|
640
|
-
inputDim: vocabularySize, // Use the
|
|
646
|
+
inputDim: vocabularySize, // Use the EXACT vocabulary size from data preparation
|
|
641
647
|
outputDim: 128,
|
|
642
648
|
inputLength: 100 // Max sequence length
|
|
643
649
|
}),
|
|
@@ -1424,7 +1430,9 @@ class ServiceNowMachineLearningMCP {
|
|
|
1424
1430
|
* Train model using streaming to handle large datasets efficiently
|
|
1425
1431
|
*/
|
|
1426
1432
|
async trainWithStreaming(args) {
|
|
1427
|
-
const { sample_size, batch_size, epochs, validation_split, query, intelligent_selection, focus_categories
|
|
1433
|
+
const { sample_size, batch_size, epochs, validation_split, query, intelligent_selection, focus_categories } = args;
|
|
1434
|
+
// CRITICAL FIX: Ensure max_vocabulary_size is ALWAYS valid in streaming mode too
|
|
1435
|
+
const max_vocabulary_size = Math.max(1000, args.max_vocabulary_size || 5000);
|
|
1428
1436
|
this.logger.info(`Starting streaming training with batch size ${batch_size}`);
|
|
1429
1437
|
// First, fetch initial batch to determine categories and validate data access
|
|
1430
1438
|
let allCategories = new Set();
|
|
@@ -1583,8 +1591,10 @@ class ServiceNowMachineLearningMCP {
|
|
|
1583
1591
|
* Create feature hasher for memory-efficient vocabulary management
|
|
1584
1592
|
*/
|
|
1585
1593
|
createFeatureHasher(maxFeatures) {
|
|
1594
|
+
// CRITICAL: Ensure maxFeatures is valid
|
|
1595
|
+
const validMaxFeatures = Math.max(1000, maxFeatures || 5000);
|
|
1586
1596
|
return (text) => {
|
|
1587
|
-
const words = text.toLowerCase().split(/\s+/);
|
|
1597
|
+
const words = (text || '').toLowerCase().split(/\s+/).filter(w => w.length > 0);
|
|
1588
1598
|
const features = new Array(100).fill(0); // Fixed sequence length
|
|
1589
1599
|
words.slice(0, 100).forEach((word, idx) => {
|
|
1590
1600
|
// Simple hash function
|
|
@@ -1593,8 +1603,9 @@ class ServiceNowMachineLearningMCP {
|
|
|
1593
1603
|
hash = ((hash << 5) - hash) + word.charCodeAt(i);
|
|
1594
1604
|
hash = hash & hash; // Convert to 32-bit integer
|
|
1595
1605
|
}
|
|
1596
|
-
// Map to vocabulary size
|
|
1597
|
-
|
|
1606
|
+
// Map to vocabulary size - ensure within valid range [0, validMaxFeatures-1]
|
|
1607
|
+
const index = Math.abs(hash) % validMaxFeatures;
|
|
1608
|
+
features[idx] = Math.max(0, Math.min(validMaxFeatures - 1, index));
|
|
1598
1609
|
});
|
|
1599
1610
|
return features;
|
|
1600
1611
|
};
|
|
@@ -1698,25 +1709,49 @@ class ServiceNowMachineLearningMCP {
|
|
|
1698
1709
|
* Optimized data preparation with feature hashing
|
|
1699
1710
|
*/
|
|
1700
1711
|
async prepareIncidentDataOptimized(incidents, maxVocabularySize) {
|
|
1701
|
-
|
|
1702
|
-
|
|
1712
|
+
// Ensure we have valid data
|
|
1713
|
+
if (!incidents || incidents.length === 0) {
|
|
1714
|
+
throw new Error('No incidents provided for data preparation');
|
|
1715
|
+
}
|
|
1716
|
+
// CRITICAL FIX: Ensure vocabulary size is ALWAYS valid and non-zero
|
|
1717
|
+
const validVocabularySize = Math.max(1000, maxVocabularySize || 5000);
|
|
1718
|
+
this.logger.info(`Using vocabulary size: ${validVocabularySize} for data preparation`);
|
|
1719
|
+
const hasher = this.createFeatureHasher(validVocabularySize);
|
|
1720
|
+
const categories = [...new Set(incidents.map(i => i.category))].filter(c => c); // Filter out empty categories
|
|
1721
|
+
if (categories.length === 0) {
|
|
1722
|
+
categories.push('uncategorized'); // Ensure at least one category
|
|
1723
|
+
}
|
|
1703
1724
|
const sequences = [];
|
|
1704
1725
|
const labels = [];
|
|
1705
1726
|
for (const incident of incidents) {
|
|
1706
|
-
const text = `${incident.short_description} ${incident.description}`;
|
|
1727
|
+
const text = `${incident.short_description || ''} ${incident.description || ''}`;
|
|
1707
1728
|
const sequence = hasher(text);
|
|
1708
|
-
|
|
1729
|
+
// Validate sequence values are within bounds
|
|
1730
|
+
const validatedSequence = sequence.map(idx => {
|
|
1731
|
+
if (idx < 0 || idx >= validVocabularySize) {
|
|
1732
|
+
this.logger.warn(`Index ${idx} out of bounds, clamping to valid range`);
|
|
1733
|
+
return Math.max(0, Math.min(validVocabularySize - 1, idx));
|
|
1734
|
+
}
|
|
1735
|
+
return idx;
|
|
1736
|
+
});
|
|
1737
|
+
sequences.push(validatedSequence);
|
|
1709
1738
|
// One-hot encode category
|
|
1710
|
-
const
|
|
1739
|
+
const category = incident.category || 'uncategorized';
|
|
1740
|
+
const categoryIndex = categories.indexOf(category);
|
|
1711
1741
|
const label = new Array(categories.length).fill(0);
|
|
1712
1742
|
if (categoryIndex >= 0) {
|
|
1713
1743
|
label[categoryIndex] = 1;
|
|
1714
1744
|
}
|
|
1715
1745
|
labels.push(label);
|
|
1716
1746
|
}
|
|
1717
|
-
//
|
|
1747
|
+
// Validate sequences before creating tensors
|
|
1748
|
+
if (sequences.length === 0 || sequences[0].length === 0) {
|
|
1749
|
+
throw new Error('Failed to create valid sequences from incident data');
|
|
1750
|
+
}
|
|
1751
|
+
// Create a minimal Map for compatibility - use the SAME vocabulary size everywhere
|
|
1718
1752
|
const tokenizerMap = new Map();
|
|
1719
|
-
tokenizerMap.set('_vocabulary_size',
|
|
1753
|
+
tokenizerMap.set('_vocabulary_size', validVocabularySize);
|
|
1754
|
+
this.logger.info(`Prepared ${sequences.length} sequences with vocabulary size ${validVocabularySize}`);
|
|
1720
1755
|
return {
|
|
1721
1756
|
features: tf.tensor2d(sequences),
|
|
1722
1757
|
labels: tf.tensor2d(labels),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snow-flow",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.5",
|
|
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",
|