AbstractIntegratedModule 0.5.4__tar.gz → 0.5.6__tar.gz

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.
Files changed (25) hide show
  1. abstractintegratedmodule-0.5.6/AbstractIntegratedModule.cp313-win_amd64.pyd +0 -0
  2. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/AbstractIntegratedModule.cpython-310-aarch64-linux-gnu.so +0 -0
  3. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/AbstractIntegratedModule.cpython-312-x86_64-linux-gnu.so +0 -0
  4. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6/AbstractIntegratedModule.egg-info}/PKG-INFO +15 -10
  5. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/AbstractIntegratedModule.py +248 -55
  6. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/AbstractOptimizedModules.c +2689 -1307
  7. abstractintegratedmodule-0.5.6/AbstractOptimizedModules.cp313-win_amd64.pyd +0 -0
  8. abstractintegratedmodule-0.5.6/AbstractOptimizedModules.cpython-310-aarch64-linux-gnu.so +0 -0
  9. abstractintegratedmodule-0.5.6/AbstractOptimizedModules.cpython-312-x86_64-linux-gnu.so +0 -0
  10. abstractintegratedmodule-0.5.6/AbstractOptimizedModules.pyx +283 -0
  11. {abstractintegratedmodule-0.5.4/AbstractIntegratedModule.egg-info → abstractintegratedmodule-0.5.6}/PKG-INFO +15 -10
  12. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/README.md +13 -8
  13. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/setup.py +2 -2
  14. abstractintegratedmodule-0.5.4/AbstractIntegratedModule.cp313-win_amd64.pyd +0 -0
  15. abstractintegratedmodule-0.5.4/AbstractOptimizedModules.cp313-win_amd64.pyd +0 -0
  16. abstractintegratedmodule-0.5.4/AbstractOptimizedModules.cpython-310-aarch64-linux-gnu.so +0 -0
  17. abstractintegratedmodule-0.5.4/AbstractOptimizedModules.cpython-312-x86_64-linux-gnu.so +0 -0
  18. abstractintegratedmodule-0.5.4/AbstractOptimizedModules.pyx +0 -197
  19. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/AbstractIntegratedModule.egg-info/SOURCES.txt +0 -0
  20. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/AbstractIntegratedModule.egg-info/dependency_links.txt +0 -0
  21. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/AbstractIntegratedModule.egg-info/requires.txt +0 -0
  22. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/AbstractIntegratedModule.egg-info/top_level.txt +0 -0
  23. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/MANIFEST.in +0 -0
  24. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/pyproject.toml +0 -0
  25. {abstractintegratedmodule-0.5.4 → abstractintegratedmodule-0.5.6}/setup.cfg +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AbstractIntegratedModule
3
- Version: 0.5.4
4
- Summary: Framework for Advanced Integrated Non-LLM AI Module library - Backend Framework For Non-LLM AI Agent
3
+ Version: 0.5.6
4
+ Summary: Library for Advanced Integrated Non-LLM AI Models - Optimized Backend Framework For Non-LLM AI Agent
5
5
  Author: Micro-Novelty
6
6
  Author-email: hernikpuspita5@gmail.com
7
7
  License: MIT
@@ -42,7 +42,7 @@ https://github.com/Micro-Novelty/IntegratedPipeline-Specialized-Non-LLM-AI-Agent
42
42
  #### Note: The README here you are reading is a direct copy from my README Repository, to download the necessary files, you can visit my Repository with the provided link above.
43
43
 
44
44
  ### Library Short Description:
45
- - Development Stage: Beta, 0.5.4.
45
+ - Development Stage: 0.5.6 Official Release.
46
46
  - Maintainer: Micro-Novelty.
47
47
  - library Source-Code is Open-sourced on github.
48
48
  - Purpose: Specifically Designed for providing Non-LLM AI Agent Framework for edge Devices, Optimized for ARM64 architecture.
@@ -59,19 +59,22 @@ https://github.com/Micro-Novelty/IntegratedPipeline-Specialized-Non-LLM-AI-Agent
59
59
  if you don't have the necessary python, don't worry since you could use our regular pip download.
60
60
 
61
61
  - Proven Capabilities:
62
+ - The library has been thoroughly tested in Multiple Environments from Windows to ARM64 Environment. The library is now Robust for Wider use and Deployment.
62
63
  - Proven Works on ARM64 Environment, Training and Prediction works efficient on Docker ARM64 environment with QEMU, good parallelizing behavior is guaranteed.
63
64
  - P2P Works efficiently in ARM64 Docker + QEMU, No conflicting socket and all prediction works efficiently.
64
65
  - AWE setup Proven Efficient on Hard-uncontrolled dataset such as Activity Recognition from the given Database.
65
66
  - LSTM is Optimized efficiently for scarce data with AWE method.
66
67
  - Robust Advanced prediction capabilities proven effective on ARM64 Using MLP + LSTM Architectures.
67
- - Transformer Optimized using Cython, to reduce Memory overhead and Reduce CPU Usage, With Reduced Training Time.
68
+ - Transformer Modules Optimized using Cython, to reduce Memory overhead and Reduce CPU Usage, With Reduced Training Time.
68
69
  - Changelog:
69
- - v0.5.4:
70
+ - v0.5.6:
70
71
  - [=] New features:
71
- - New cache management system for Transformers Cache
72
- - Optimized Transformer Training time with less Computational overhead.
73
- - Optimized Transformer attention quality computing with more newer Conditional gate for quality computing.
74
- - Fixed bug of possible Index error caused by looping attention weights.
72
+ - Added Anisotropy measurement optimization in Cython to handle complex logic.
73
+ - Added Cython softmax for Transformer to reduce CPU consumption.
74
+ - Added Cython Cosine similarity to reduce ensemble prediction time needed for prediction.
75
+ - Added safety guards for Cosine similarity to prevent string arrays to cause further errors.
76
+ - Refined csv load labels function to accept path dir, so users can finnaly find their Training labels without much restrictions and errors.
77
+
75
78
 
76
79
  -----
77
80
 
@@ -544,7 +547,9 @@ _______________________________________
544
547
 
545
548
  main_prediction = PipelinePredictionManager(
546
549
  main_model, # your initialized pipeline
547
- label_csv='example_manual_training.txt', # your .txt file that contains CSV format.
550
+ label_csv='C:\users\yourdevice\example_manual_training.txt',
551
+ # or /home/yourdevice/example_manual_training.txt.
552
+ #your path dir that contains the .txt file that contains CSV format.
548
553
  target_title='window_title', label='label')
549
554
 
550
555
  # example_manual_training is a .txt file that contain csv format like above example.
@@ -41,6 +41,7 @@ import aiohttp
41
41
  import psutil
42
42
  from sklearn.preprocessing import StandardScaler
43
43
  import io
44
+ from importlib import resources
44
45
 
45
46
  # Optimized Modules In Cython implementation.
46
47
  try:
@@ -50,13 +51,16 @@ try:
50
51
  optimized_tanh_deriv,
51
52
  optimized_lstm_cell_forward,
52
53
  optimized_project_heads,
53
- optimized_ame_encoder
54
+ optimized_ame_encoder,
55
+ optimized_anisotropy,
56
+ optimized_cosine_similarity,
57
+ optimized_softmax_2d
54
58
  )
55
59
  _OPT_AVAILABLE = True
56
60
  print('[=] Cython acceleration loaded ✅')
57
- except ImportError:
61
+ except ImportError as e:
58
62
  _OPT_AVAILABLE = False
59
- print('[=] Cython not available, using numpy fallback')
63
+ print(f'[=] Cython not available: {e}, using numpy fallback')
60
64
 
61
65
  # initial Setup logging for AgentDistributedInference and ModelStorage class logger and security logger
62
66
  logger = logging.getLogger(__name__)
@@ -383,6 +387,9 @@ class GeometricWeightShaping:
383
387
  # abstract modelling error provides the model how to better process weights when the data complexity has little geometric complexity
384
388
  def AME_Encoder(self, x):
385
389
  X = np.asarray(x)
390
+ if _OPT_AVAILABLE and np.asarray(X).ndim == 2:
391
+ return optimized_ame_encoder(np.asarray(X, dtype=np.float64))
392
+
386
393
  try:
387
394
  gradient = np.gradient(x)
388
395
  except:
@@ -400,6 +407,10 @@ class GeometricWeightShaping:
400
407
  # anisotropy provides the model the standard complexity of the data geometry, allowing it to know how complex the data needs to be processed.
401
408
  def anisotropy_measurement(self, x):
402
409
  eps = 1e-5
410
+ if _OPT_AVAILABLE:
411
+ x = x.reshape(x.shape[0], -1)
412
+ return optimized_anisotropy(np.asarray(x, dtype=np.float64))
413
+
403
414
  try:
404
415
  gradient = np.gradient(x)
405
416
  except:
@@ -496,6 +507,8 @@ class Activation:
496
507
 
497
508
  @staticmethod
498
509
  def softmax(x):
510
+ if _OPT_AVAILABLE:
511
+ return optimized_softmax_2d(np.asarray(x, dtype=np.float64))
499
512
  # numerical stability
500
513
  if x.ndim > 1:
501
514
  exp_x = np.exp(x - np.max(x, axis=1, keepdims=True))
@@ -691,6 +704,9 @@ class Transformer:
691
704
 
692
705
 
693
706
  def softmax(self, x):
707
+ if _OPT_AVAILABLE:
708
+ return optimized_softmax_2d(np.asarray(x, dtype=np.float64))
709
+
694
710
  if x.ndim == 3:
695
711
  shifted = x - np.max(x, axis=-1, keepdims=True)
696
712
  else:
@@ -1166,6 +1182,7 @@ class Transformer:
1166
1182
 
1167
1183
  return grads, total_norm
1168
1184
 
1185
+
1169
1186
  def batch_padding_utility(self, sequences, pad_token_id=0):
1170
1187
  # sequences: list of 1-D np arrays of varying length
1171
1188
  max_len = max(len(s) for s in sequences)
@@ -1353,6 +1370,10 @@ class Transformer:
1353
1370
 
1354
1371
  def anisotropy_measurement(self, x):
1355
1372
  eps = 1e-5
1373
+ if _OPT_AVAILABLE:
1374
+ x = x.reshape(x.shape[0], -1)
1375
+ return optimized_anisotropy(np.asarray(x, dtype=np.float64))
1376
+
1356
1377
  try:
1357
1378
  gradient = np.gradient(x)
1358
1379
  except:
@@ -1637,6 +1658,8 @@ class MLP:
1637
1658
 
1638
1659
  def AME_Encoder(self, x):
1639
1660
  X = np.asarray(x)
1661
+ if _OPT_AVAILABLE and np.asarray(X).ndim == 2:
1662
+ return optimized_ame_encoder(np.asarray(X, dtype=np.float64))
1640
1663
 
1641
1664
  if x.shape[1] == 1:
1642
1665
  x = x.T
@@ -1652,6 +1675,10 @@ class MLP:
1652
1675
 
1653
1676
  def anisotropy_measurement(self, x):
1654
1677
  eps = 1e-5
1678
+ if _OPT_AVAILABLE:
1679
+ x = x.reshape(x.shape[0], -1)
1680
+ return optimized_anisotropy(np.asarray(x, dtype=np.float64))
1681
+
1655
1682
  try:
1656
1683
  gradient = np.gradient(x)
1657
1684
  except:
@@ -2771,6 +2798,10 @@ class WeightedEnsemblePredictor:
2771
2798
 
2772
2799
  def anisotropy_measurement(self, x):
2773
2800
  eps = 1e-5
2801
+ if _OPT_AVAILABLE:
2802
+ x = x.reshape(x.shape[0], -1)
2803
+ return optimized_anisotropy(np.asarray(x, dtype=np.float64))
2804
+
2774
2805
  try:
2775
2806
  try:
2776
2807
  grads = np.gradient(x)
@@ -3671,6 +3702,9 @@ class ExplainabilityModule:
3671
3702
 
3672
3703
  def AME_Encoder(self, x):
3673
3704
  X = np.asarray(x)
3705
+ if _OPT_AVAILABLE and np.asarray(X).ndim == 2:
3706
+ return optimized_ame_encoder(np.asarray(X, dtype=np.float64))
3707
+
3674
3708
 
3675
3709
  try:
3676
3710
  gradient = np.gradient(x, axis=-1)
@@ -8099,6 +8133,26 @@ class IntegratedPipeline:
8099
8133
  print('[!] Value is single scalar! returning 0.0 similarity')
8100
8134
  return 0.0
8101
8135
 
8136
+ if isinstance(a, (str, np.str_)):
8137
+ clean_str = str(a).replace('[', '').replace(']', '')
8138
+ a = np.fromstring(clean_str, sep=' ')
8139
+ if isinstance(a, np.ndarray) and np.issubdtype(a.dtype, np.character):
8140
+ # catches arrays filled with string text
8141
+ clean_str = ' '.join(a.astype(str).flatten()).replace('[', '').replace(']', '')
8142
+ a = np.fromiter(
8143
+ (v for v in clean_str.split() if a != "..."), dtype=float
8144
+ )
8145
+
8146
+ if isinstance(b, (str, np.str_)):
8147
+ clean_str = str(b).replace('[', '').replace(']', '')
8148
+ b = np.fromstring(clean_str, sep=' ')
8149
+ if isinstance(b, np.ndarray) and np.issubdtype(b.dtype, np.character):
8150
+ # catches arrays filled with string text
8151
+ clean_str = ' '.join(b.astype(str).flatten()).replace('[', '').replace(']', '')
8152
+ b = np.fromiter(
8153
+ (v for v in clean_str.split() if b != "..."), dtype=float
8154
+ )
8155
+
8102
8156
  if isinstance(a[0], (np.ndarray, list)):
8103
8157
  norm_a = np.linalg.norm(a[0])
8104
8158
  else:
@@ -8108,7 +8162,16 @@ class IntegratedPipeline:
8108
8162
  norm_b = np.linalg.norm(b[0])
8109
8163
  else:
8110
8164
  norm_b = np.linalg.norm(b)
8111
-
8165
+
8166
+ if _OPT_AVAILABLE:
8167
+ if len(a.shape) > 1:
8168
+ a = np.asarray(a)
8169
+ a = a.reshape(-1)
8170
+ if len(b.shape) > 1:
8171
+ b = np.asarray(b)
8172
+ b = b.reshape(-1)
8173
+ return optimized_cosine_similarity(np.asarray(a, dtype=np.float64), np.asarray(b, dtype=np.float64))
8174
+
8112
8175
  try:
8113
8176
  dot_product = np.dot(a, b)
8114
8177
  except:
@@ -8316,12 +8379,42 @@ class IntegratedPipeline:
8316
8379
 
8317
8380
  def cosine_similarity(self, a, b):
8318
8381
  eps = 1e-5
8382
+ if isinstance(a, (str, np.str_)):
8383
+ clean_str = str(a).replace('[', '').replace(']', '')
8384
+ a = np.fromstring(clean_str, sep=' ')
8385
+ if isinstance(a, np.ndarray) and np.issubdtype(a.dtype, np.character):
8386
+ # catches arrays filled with string text
8387
+ clean_str = ' '.join(a.astype(str).flatten()).replace('[', '').replace(']', '')
8388
+ a = np.fromiter(
8389
+ (v for v in clean_str.split() if a != "..."), dtype=float
8390
+ )
8391
+
8392
+ if isinstance(b, (str, np.str_)):
8393
+ clean_str = str(b).replace('[', '').replace(']', '')
8394
+ b = np.fromstring(clean_str, sep=' ')
8395
+ if isinstance(b, np.ndarray) and np.issubdtype(b.dtype, np.character):
8396
+ # catches arrays filled with string text
8397
+ clean_str = ' '.join(b.astype(str).flatten()).replace('[', '').replace(']', '')
8398
+ b = np.fromiter(
8399
+ (v for v in clean_str.split() if b != "..."), dtype=float
8400
+ )
8401
+
8319
8402
  if isinstance(b, (float, int)) or isinstance(a, (float, int)):
8320
8403
  print('[!] Value is single scalar! returning 0.0 similarity')
8321
8404
  return 0.0
8322
8405
 
8323
8406
  b = b[0]
8324
-
8407
+
8408
+ if _OPT_AVAILABLE:
8409
+ if len(a.shape) > 1:
8410
+ a = np.asarray(a)
8411
+ a = a.reshape(-1)
8412
+ if len(b.shape) > 1:
8413
+ b = np.asarray(b)
8414
+ b = b.reshape(-1)
8415
+
8416
+ return optimized_cosine_similarity(np.asarray(a, dtype=np.float64), np.asarray(b, dtype=np.float64))
8417
+
8325
8418
  try:
8326
8419
  # Handle variable b
8327
8420
  if isinstance(b, (str, np.str_)):
@@ -8402,12 +8495,27 @@ class IntegratedPipeline:
8402
8495
 
8403
8496
  def anisotropy_measurement(self, x):
8404
8497
  eps = 1e-5
8498
+
8499
+ if isinstance(x, (str, np.str_)):
8500
+ clean_str = str(x).replace('[', '').replace(']', '')
8501
+ x = np.fromstring(clean_str, sep=' ')
8502
+ if isinstance(x, np.ndarray) and np.issubdtype(x.dtype, np.character):
8503
+ # catches arrays filled with string text
8504
+ clean_str = ' '.join(x.astype(str).flatten()).replace('[', '').replace(']', '')
8505
+ x = np.fromiter(
8506
+ (v for v in clean_str.split() if x != "..."), dtype=float
8507
+ )
8508
+
8509
+ if _OPT_AVAILABLE:
8510
+ x = x.reshape(-1, 1)
8511
+ return optimized_anisotropy(np.asarray(x, dtype=np.float64))
8405
8512
 
8406
8513
  if isinstance(x, list):
8407
8514
  print(f'[=] Converting list to array with shape: {len(x)}')
8408
8515
  x = np.array(x)
8409
8516
  x = x.reshape(x.shape[0], -1) # Flatten if necessary
8410
8517
 
8518
+
8411
8519
  try:
8412
8520
  try:
8413
8521
  grads = np.gradient(x)
@@ -9524,37 +9632,46 @@ class IntegratedPipeline:
9524
9632
  batch_size = len(target_preds)
9525
9633
  eps = 1e-5
9526
9634
 
9527
- for i in range(batch_size):
9528
- mlp_target = target_preds[i]
9635
+ try:
9636
+ for i in range(batch_size):
9637
+ mlp_target = target_preds[i]
9529
9638
 
9530
- if attn_weights is None:
9531
- anisotropy = self.anisotropy_measurement(mlp_target)
9532
- else:
9533
- anisotropy = self.anisotropy_measurement(attn_weights[i])
9534
- if attn_weights is not None and i < len(attn_weights):
9535
- attn = attn_weights[i]
9536
-
9537
- score_quality = np.std(attn) if attn.size > 0 else self.confidence_threshold
9538
- abstract_score = self.confidence_threshold + score_quality * anisotropy
9639
+ if attn_weights is None:
9640
+ anisotropy = self.anisotropy_measurement(mlp_target)
9641
+ else:
9642
+ try:
9643
+ anisotropy = self.anisotropy_measurement(attn_weights[i])
9644
+ except:
9645
+ anisotropy = self.anisotropy_measurement(attn_weights)
9646
+
9647
+ if attn_weights is not None and i < len(attn_weights):
9648
+ attn = attn_weights[i]
9649
+
9650
+ score_quality = np.std(attn) if attn.size > 0 else self.confidence_threshold
9651
+ abstract_score = self.confidence_threshold + score_quality * anisotropy
9539
9652
 
9540
- else:
9541
- if attn_weights is not None:
9542
- score_quality = 1.0 / (1.0 + np.exp(-attn_weights[i]))
9543
9653
  else:
9544
- score_quality = 1.0 / (1.0 + np.exp(-mlp_target))
9654
+ if attn_weights is not None:
9655
+ score_quality = 1.0 / (1.0 + np.exp(-attn_weights[i]))
9656
+ else:
9657
+ score_quality = 1.0 / (1.0 + np.exp(-mlp_target))
9545
9658
 
9546
- abstract_score = (1.0 - score_quality) + eps
9659
+ abstract_score = (1.0 - score_quality) + eps
9547
9660
 
9548
- self.temperature = (1.0 - abstract_score) + score_quality * anisotropy
9549
- if isinstance(self.temperature, np.ndarray):
9550
- self.temperature = np.clip(np.mean(self.temperature), 1e-5, 5.0)
9661
+ self.temperature = (1.0 - abstract_score) + score_quality * anisotropy
9662
+ if isinstance(self.temperature, np.ndarray):
9663
+ self.temperature = np.clip(np.mean(self.temperature), 1e-5, 5.0)
9551
9664
 
9552
- try:
9553
- calibrated[i, mlp_target] = min(calibrated[i, mlp_target] * (1.5 * (1.0 - abstract_score)), 0.95)
9554
- except:
9555
- return calibrated
9665
+ try:
9666
+ calibrated[i, mlp_target] = min(calibrated[i, mlp_target] * (1.5 * (1.0 - abstract_score)), 0.95)
9667
+ except:
9668
+ return calibrated
9669
+
9670
+ calibrated[i] /= calibrated[i].sum()
9671
+ except Exception as e:
9672
+ print(f'[!] cant calibrate probability due to: {e}, returning regular probability.')
9673
+ calibrated = calibrated.copy()
9556
9674
 
9557
- calibrated[i] /= calibrated[i].sum()
9558
9675
  return calibrated
9559
9676
 
9560
9677
  def _softmax(self, x):
@@ -9778,6 +9895,8 @@ class IntegratedPipeline:
9778
9895
  X = np.fromiter(
9779
9896
  (x for x in clean_str.split() if x != "..."), dtype=float
9780
9897
  )
9898
+ if _OPT_AVAILABLE and np.asarray(X).ndim == 2:
9899
+ return optimized_ame_encoder(np.asarray(X, dtype=np.float64))
9781
9900
 
9782
9901
  X = np.squeeze(X)
9783
9902
  if X.ndim == 1:
@@ -12072,33 +12191,102 @@ class PipelinePredictionManager:
12072
12191
  print(f"✅ Loaded {len(self.titles)} labeled examples")
12073
12192
 
12074
12193
  def load_labels_from_csv(self, filename, target_title, label):
12075
- script_dir = os.path.dirname(os.path.abspath(__file__))
12076
- filepath = os.path.join(script_dir, filename)
12077
-
12078
- if not os.path.exists(filepath):
12079
- print(f"❌ File not found: {filepath}")
12194
+ """
12195
+ Load CSV from multiple common locations — no need to place
12196
+ file next to the script.
12197
+
12198
+ Search order:
12199
+ 1. Absolute path (if filename is already absolute)
12200
+ 2. Current working directory
12201
+ 3. Script directory
12202
+ 4. User home directory
12203
+ 5. Common data folders (Downloads, Documents, Desktop)
12204
+ """
12205
+ import os
12206
+ import sys
12207
+
12208
+ # build candidate paths
12209
+ candidates = []
12210
+
12211
+ # 1 — absolute path as-is
12212
+ if os.path.isabs(filename):
12213
+ candidates.append(filename)
12214
+ else:
12215
+ # 2 — current working directory
12216
+ candidates.append(os.path.join(os.getcwd(), filename))
12217
+
12218
+ # 3 — script directory
12219
+ try:
12220
+ script_dir = os.path.dirname(os.path.abspath(__file__))
12221
+ candidates.append(os.path.join(script_dir, filename))
12222
+ except NameError:
12223
+ pass
12224
+
12225
+ # 4 — home directory
12226
+ candidates.append(os.path.join(os.path.expanduser('~'), filename))
12227
+
12228
+ # 5 — common data folders
12229
+ home = os.path.expanduser('~')
12230
+ for folder in ['Downloads', 'Documents', 'Desktop', 'Data', 'data']:
12231
+ candidates.append(os.path.join(home, folder, filename))
12232
+
12233
+ # 6 — sys.path entries (useful in notebooks)
12234
+ for p in sys.path:
12235
+ if p:
12236
+ candidates.append(os.path.join(p, filename))
12237
+
12238
+ # find first existing path
12239
+ filepath = None
12240
+ for candidate in candidates:
12241
+ if os.path.exists(candidate):
12242
+ filepath = candidate
12243
+ break
12244
+
12245
+ if filepath is None:
12246
+ print(f"❌ Could not find '{filename}' in any of these locations:")
12247
+ for c in candidates[:6]: # show first 6 only
12248
+ print(f" {c}")
12249
+ print(f"\n💡 Tip: place your CSV in one of these folders or pass the full path:")
12250
+ print(f" {os.getcwd()}\\{filename}")
12251
+ print(f" {os.path.expanduser('~')}\\Downloads\\{filename}")
12080
12252
  return [], [], {}
12081
-
12082
- # Read CSV file
12083
- df = pd.read_csv(filepath)
12084
-
12253
+
12254
+ print(f"✅ Found CSV at: {filepath}")
12255
+
12256
+ try:
12257
+ df = pd.read_csv(filepath)
12258
+ except Exception as e:
12259
+ print(f"❌ Failed to read CSV: {e}")
12260
+ return [], [], {}
12261
+
12262
+ # validate columns exist
12263
+ missing = [c for c in [target_title, label] if c not in df.columns]
12264
+ if missing:
12265
+ print(f"❌ Missing columns: {missing}")
12266
+ print(f" Available columns: {list(df.columns)}")
12267
+ return [], [], {}
12268
+
12085
12269
  print(f"✅ Loaded CSV with columns: {list(df.columns)}")
12086
-
12087
- # Extract titles and labels
12088
- titles = df[target_title].tolist()
12089
- string_labels = df[label].tolist()
12090
-
12091
- # Remove quotes if they're still there
12092
- titles = [t.strip('"') for t in titles]
12093
-
12270
+
12271
+ # drop rows with missing values in target columns
12272
+ before = len(df)
12273
+ df = df.dropna(subset=[target_title, label])
12274
+ dropped = before - len(df)
12275
+ if dropped > 0:
12276
+ print(f"⚠️ Dropped {dropped} rows with missing values")
12277
+
12278
+ # extract and clean
12279
+ titles = df[target_title].astype(str).str.strip('"').tolist()
12280
+ string_labels = df[label].astype(str).tolist()
12281
+
12094
12282
  print(f"📊 Found {len(titles)} examples")
12095
12283
  print(f"📊 Labels: {set(string_labels)}")
12096
-
12097
- # Create numeric labels
12284
+
12285
+ # create numeric label map
12098
12286
  unique_labels = sorted(set(string_labels))
12099
- label_map = {label: i for i, label in enumerate(unique_labels)}
12100
- y = [label_map[label] for label in string_labels]
12101
-
12287
+ label_map = {lbl: i for i, lbl in enumerate(unique_labels)}
12288
+ y = [label_map[lbl] for lbl in string_labels]
12289
+
12102
12290
  return titles, y, label_map
12103
12291
 
12104
12292
 
@@ -13131,6 +13319,10 @@ class PipelinePredictionManager:
13131
13319
  if self.pipeline.autonomous and sec_confidence > self.pipeline.confidence_threshold:
13132
13320
  print(f'[⚡] Autonomous Prediction used second predicted label: {sec_chosen_label}')
13133
13321
  chosen_label = sec_chosen_label
13322
+
13323
+ # delete pipelines cache
13324
+ print('[🔍] Pipelines Cache Cleaned!')
13325
+ self.pipeline.cache.clear()
13134
13326
 
13135
13327
  return results, chosen_label, confidence
13136
13328
 
@@ -13150,14 +13342,15 @@ class PipelinePredictionManager:
13150
13342
  if result.get('expected'):
13151
13343
  total_with_expected += 1
13152
13344
  status = ": ✅" if result['predicted'] == result['expected'] else ": ❌"
13153
- sec_status = ": ✅" if result['sec_predicted'] == result['expected'] else ": ❌"
13154
13345
  print(f"[=] First Expectation: {result['expected']} || Model Answer: {status}")
13155
- print(f"[=] Second Expectation: {result['expected']} || Model Answer: {sec_status}")
13346
+ if 'sec_predicted' in result:
13347
+ sec_status = ": ✅" if result['sec_predicted'] == result['expected'] else ": ❌"
13348
+ print(f"[=] Second Expectation: {result['expected']} || Model Answer: {sec_status}")
13349
+ if result['sec_predicted'] == result['expected']:
13350
+ sec_correct += 1
13156
13351
 
13157
13352
  if result['predicted'] == result['expected']:
13158
13353
  correct += 1
13159
- if result['sec_predicted'] == result['expected']:
13160
- sec_correct += 1
13161
13354
 
13162
13355
  # Agreement indicator
13163
13356
  agree_symbol = "✓" if result.get('models_agree', True) else "⚠️"