AbstractIntegratedModule 0.8.3__tar.gz → 0.8.5__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 (23) hide show
  1. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/AbstractIntegratedModule.egg-info/PKG-INFO +10 -11
  2. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/AbstractIntegratedModule.py +125 -71
  3. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/AbstractOptimizedModules.c +2860 -1143
  4. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/AbstractOptimizedModules.pyx +140 -1
  5. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/PKG-INFO +10 -11
  6. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/README.md +9 -10
  7. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/setup.py +1 -1
  8. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/AbstractIntegratedModule.egg-info/SOURCES.txt +0 -0
  9. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/AbstractIntegratedModule.egg-info/dependency_links.txt +0 -0
  10. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/AbstractIntegratedModule.egg-info/requires.txt +0 -0
  11. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/AbstractIntegratedModule.egg-info/top_level.txt +0 -0
  12. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/MANIFEST.in +0 -0
  13. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/abstract_model_storage/Cargo.toml +0 -0
  14. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/abstract_model_storage/pyproject.toml +0 -0
  15. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/abstract_model_storage/src/lib.rs +0 -0
  16. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/abstract_model_storage/target/debug/build/libsqlite3-sys-ed07b882cd2aa5e2/out/bindgen.rs +0 -0
  17. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/abstract_model_storage/target/debug/build/serde_core-ebc15f2e9cad7f5f/out/private.rs +0 -0
  18. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/abstract_model_storage/target/debug/build/target-lexicon-08527f45de28143d/out/host.rs +0 -0
  19. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/abstract_model_storage/target/release/build/libsqlite3-sys-bf0400df4523274c/out/bindgen.rs +0 -0
  20. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/abstract_model_storage/target/release/build/serde_core-5cdb76131825e4af/out/private.rs +0 -0
  21. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/abstract_model_storage/target/release/build/target-lexicon-43eb95a0588bf457/out/host.rs +0 -0
  22. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/pyproject.toml +0 -0
  23. {abstractintegratedmodule-0.8.3 → abstractintegratedmodule-0.8.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AbstractIntegratedModule
3
- Version: 0.8.3
3
+ Version: 0.8.5
4
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
@@ -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: 0.8.3 Official Release.
45
+ - Development Stage: 0.8.5 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.
@@ -80,17 +80,16 @@ https://github.com/Micro-Novelty/IntegratedPipeline-Specialized-Non-LLM-AI-Agent
80
80
  - Transformer Optimized using Cython, to reduce Memory overhead and Reduce CPU Usage, With Reduced Training Time.
81
81
  ______________
82
82
  - Changelog:
83
- - v0.8.3:
83
+ - v0.8.5:
84
84
  - [=] New features:
85
-
86
- - Added more robust inhomogenous shape handling for handling input_ids in Transformer and AccurateAnswerCache architecture.
85
+ - Added new Optimization module using Cython maths for dynamic weighted ensemble function.
87
86
  - Fixed P2P Vulnerabilities:
88
- - Empty allowed_ips in PRODUCTION/HARDENED mode now DENIES external IPs instead of allowing all
89
- - Startup validation warns about dangerous config combinations
90
- - Loopback (127.0.0.1) always permitted for local agent comms
91
- - DEVELOPMENT/STAGING retains allow-all behavior with explicit warning since local P2P testing requires it
92
- - pickle.loads() replaced by json.loads with utf-8 encoding order.
93
- - generate self signed cert fixes and added client.crt for fallback when users dont provide any SSL cert and key for both server and client.
87
+ - Empty allowed_ips in PRODUCTION/HARDENED mode now DENIES external IPs instead of allowing all
88
+ - Startup validation warns about dangerous config combinations
89
+ - Loopback (127.0.0.1) always permitted for local agent comms
90
+ - DEVELOPMENT/STAGING retains allow-all behavior with explicit warning since local P2P testing requires it
91
+ - pickle.loads() replaced by json.loads with utf-8 encoding order.
92
+ - generate self signed cert fixes and added client.crt for fallback when users dont provide any SSL cert and key for both server and client.
94
93
 
95
94
  ____________
96
95
  <img width="1280" height="600" alt="WhatsApp Image 2026-05-27 at 07 16 32" src="https://github.com/user-attachments/assets/4b58a556-45a3-419b-96fd-9c1b76cac574" />
@@ -61,7 +61,8 @@ try:
61
61
  optimized_ame_encoder,
62
62
  optimized_anisotropy,
63
63
  optimized_cosine_similarity,
64
- optimized_softmax_2d
64
+ optimized_softmax_2d,
65
+ optimized_dynamic_weighted_ensemble
65
66
  )
66
67
  _OPT_AVAILABLE = True
67
68
  print('[=] Cython acceleration loaded ✅')
@@ -3020,82 +3021,116 @@ class WeightedEnsemblePredictor:
3020
3021
 
3021
3022
  return anisotropy
3022
3023
 
3023
- def _dynamic_weighted_ensemble(self, trans_probs, mlp_probs, attn_weights, input_ids, lstm_probs,
3024
- lstm_weight_hint):
3025
- batch_size = trans_probs.shape[0]
3026
-
3024
+ def _dynamic_weighted_ensemble(self, trans_probs, mlp_probs, attn_weights,
3025
+ input_ids, lstm_probs=None, lstm_weight_hint=0.0):
3026
+ # normalize all inputs to guaranteed 2D float64
3027
3027
  try:
3028
- n_trans_classes = trans_probs.shape[1]
3029
- n_mlp_classes = mlp_probs.shape[1]
3030
- n_lstm_classes = lstm_probs.shape[1]
3031
- except:
3032
- n_trans_classes = trans_probs.shape[-1]
3033
- n_mlp_classes = mlp_probs.shape[-1]
3034
- n_lstm_classes = lstm_probs.shape[-1]
3028
+ trans_probs = np.asarray(trans_probs, dtype=np.float64)
3029
+ mlp_probs = np.asarray(mlp_probs, dtype=np.float64)
3035
3030
 
3036
- n_classes = max(n_trans_classes, n_mlp_classes)
3037
-
3038
- print(f"🔄 Aligning classes: {n_trans_classes} and {n_mlp_classes} → {n_classes}")
3039
- ensemble = np.zeros((batch_size, n_classes))
3040
- for i in range(batch_size):
3041
- trans_row = np.zeros(n_classes)
3042
- mlp_row = np.zeros(n_classes)
3043
-
3044
- trans_row[:n_trans_classes] = trans_probs[i]
3045
- mlp_row[:n_mlp_classes] = mlp_probs[i]
3046
-
3047
- trans_row = trans_row / (trans_row.sum() + 1e-8)
3048
- mlp_row = mlp_row / (mlp_row.sum() + 1e-8)
3049
-
3050
- trans_pred = np.argmax(trans_probs[i])
3051
- mlp_pred = np.argmax(mlp_probs[i])
3052
- agreement = 1.0 if trans_pred == mlp_pred else 0.3
3031
+ if trans_probs.ndim == 1: trans_probs = trans_probs[np.newaxis, :]
3032
+ if mlp_probs.ndim == 1: mlp_probs = mlp_probs[np.newaxis, :]
3053
3033
 
3054
- if attn_weights is not None and i < len(attn_weights):
3055
- print('🔄 Sophisticated confidence assembling')
3056
- attn = attn_weights[i]
3057
- anisotropy = self.anisotropy_measurement(attn)
3034
+ B = trans_probs.shape[0]
3058
3035
 
3059
- attn_focus = np.std(attn) if attn.size > 0 else 0.5
3060
- attn_growth = 1.0 / (1.0 + np.exp(-attn_focus))
3061
- attn_limit = (1.0 - attn_focus + attn_growth) * anisotropy
3036
+ n_trans = trans_probs.shape[1]
3037
+ n_mlp = mlp_probs.shape[1]
3062
3038
 
3063
- trans_conf_factor = attn_growth + attn_limit * attn_focus
3039
+ has_lstm = lstm_probs is not None
3040
+ if has_lstm:
3041
+ lstm_probs = np.asarray(lstm_probs, dtype=np.float64)
3042
+ if lstm_probs.ndim == 1: lstm_probs = lstm_probs[np.newaxis, :]
3043
+ n_lstm = lstm_probs.shape[1]
3064
3044
  else:
3065
- attn_growth = 1.0 / (1.0 + np.exp(-attn_weights))
3066
- anisotropy = self.anisotropy_measurement(attn_weights)
3067
- trans_conf_factor = attn_growth * anisotropy
3045
+ lstm_probs = np.zeros((B, 1), dtype=np.float64) # dummy, not used
3046
+ n_lstm = 0
3068
3047
 
3069
- mlp_entropy = -np.sum(mlp_probs[i] * np.log(mlp_probs[i] + 1e-8))
3070
- mlp_conf_factor = 1.0 / (1.0 + mlp_entropy) # Lower entropy = higher confidence
3071
-
3072
- trans_weight = trans_conf_factor * (1.0 + agreement) / 2
3073
- mlp_weight = mlp_conf_factor * (1.0 + agreement) / 2
3048
+ n_classes = max(n_trans, n_mlp, n_lstm)
3049
+ print(f"🔄 Aligning classes: trans={n_trans} mlp={n_mlp} "
3050
+ f"lstm={n_lstm} → {n_classes}")
3074
3051
 
3075
- if lstm_probs is not None:
3076
- lstm_row = np.zeros(n_classes)
3077
- lstm_row[:n_lstm_classes] = lstm_probs[i]
3078
- lstm_row = lstm_row / (lstm_row.sum() + 1e-8)
3052
+ if attn_weights is not None:
3053
+ attn_arr = np.asarray(attn_weights, dtype=np.float64)
3054
+ attn_flat = attn_arr.reshape(B, -1) if attn_arr.ndim > 1 \
3055
+ else np.tile(attn_arr.ravel(), (B, 1))
3056
+ else:
3057
+ attn_flat = np.full((B, 1), 0.5, dtype=np.float64)
3079
3058
 
3080
- # lstm_weight_hint already encodes residual_std confidence
3081
- lstm_pred = np.argmax(lstm_probs[i])
3082
- lstm_agreement = 1.0 if lstm_pred == trans_pred or lstm_pred == mlp_pred else self.pipeline.confidence_threshold
3083
- lstm_weight = lstm_weight_hint * (1.0 + lstm_agreement) / 2
3059
+ # per-sample lstm_weight_hints
3060
+ if isinstance(lstm_weight_hint, (int, float)):
3061
+ lstm_weight_hints = np.full(B, float(lstm_weight_hint), dtype=np.float64)
3062
+ else:
3063
+ lstm_weight_hints = np.asarray(lstm_weight_hint, dtype=np.float64)
3064
+ if lstm_weight_hints.ndim == 0:
3065
+ lstm_weight_hints = np.full(B, float(lstm_weight_hints))
3066
+
3067
+
3068
+ if _OPT_AVAILABLE:
3069
+ try:
3070
+ print('[+] Using Optimized Dynamic weighted ensemble Method.')
3071
+ return optimized_dynamic_weighted_ensemble(
3072
+ np.ascontiguousarray(trans_probs),
3073
+ np.ascontiguousarray(mlp_probs),
3074
+ np.ascontiguousarray(attn_flat),
3075
+ np.ascontiguousarray(lstm_probs),
3076
+ np.ascontiguousarray(lstm_weight_hints),
3077
+ float(self.pipeline.confidence_threshold),
3078
+ has_lstm
3079
+ )
3080
+ except Exception as e:
3081
+ print(f'[=] Error in optimized dynamic weighted ensemble: {e}, using regular dynamic ensemble method.')
3082
+ pass
3083
+
3084
+ # pure Python fallback
3085
+ ensemble = np.zeros((B, n_classes))
3086
+ for i in range(B):
3087
+ trans_row = np.zeros(n_classes)
3088
+ mlp_row = np.zeros(n_classes)
3089
+ trans_row[:n_trans] = trans_probs[i]
3090
+ mlp_row[:n_mlp] = mlp_probs[i]
3091
+ trans_row /= trans_row.sum() + 1e-8
3092
+ mlp_row /= mlp_row.sum() + 1e-8
3093
+
3094
+ trans_pred = int(np.argmax(trans_probs[i]))
3095
+ mlp_pred = int(np.argmax(mlp_probs[i]))
3096
+ agreement = 1.0 if trans_pred == mlp_pred else 0.3
3097
+
3098
+ attn = attn_flat[i]
3099
+ attn_focus = float(np.std(attn)) if attn.size > 1 else 0.5
3100
+ attn_growth = 1.0 / (1.0 + np.exp(-attn_focus))
3101
+ anisotropy = self.anisotropy_measurement(attn.reshape(1, -1))
3102
+ attn_limit = (1.0 - attn_focus + attn_growth) * anisotropy
3103
+ trans_cf = attn_growth + attn_limit * attn_focus
3104
+
3105
+ mlp_entropy = -np.sum(mlp_probs[i] * np.log(mlp_probs[i] + 1e-8))
3106
+ mlp_cf = 1.0 / (1.0 + mlp_entropy)
3107
+
3108
+ tw = trans_cf * (1.0 + agreement) / 2.0
3109
+ mw = mlp_cf * (1.0 + agreement) / 2.0
3110
+
3111
+ if has_lstm:
3112
+ lstm_row = np.zeros(n_classes)
3113
+ lstm_row[:n_lstm] = lstm_probs[i]
3114
+ lstm_row /= lstm_row.sum() + 1e-8
3115
+ lstm_pred = int(np.argmax(lstm_probs[i]))
3116
+ la = 1.0 if (lstm_pred == trans_pred or lstm_pred == mlp_pred) \
3117
+ else self.pipeline.confidence_threshold
3118
+ lw = float(lstm_weight_hints[i]) * (1.0 + la) / 2.0
3119
+ total = tw + mw + lw + 1e-8
3120
+ ensemble[i] = (tw/total) * trans_row + \
3121
+ (mw/total) * mlp_row + \
3122
+ (lw/total) * lstm_row
3123
+ else:
3124
+ total = tw + mw + 1e-8
3125
+ ensemble[i] = (tw/total) * trans_row + (mw/total) * mlp_row
3126
+
3127
+ return ensemble
3128
+
3129
+ except Exception as e:
3130
+ print(f'[!] Cant do ensemble prediction due ensemble prediction due to: {e}, returning MLP probabilities')
3131
+ return mlp_probs.copy()
3084
3132
 
3085
- total = trans_weight + mlp_weight + lstm_weight + 1e-8
3086
- trans_weight /= total
3087
- mlp_weight /= total
3088
- lstm_weight /= total
3089
3133
 
3090
- ensemble[i] = trans_weight * trans_row + mlp_weight * mlp_row + lstm_weight * lstm_row
3091
- else:
3092
- # original two-model path — unchanged
3093
- total = trans_weight + mlp_weight + 1e-8
3094
- trans_weight /= total
3095
- mlp_weight /= total
3096
- ensemble[i] = trans_weight * trans_row + mlp_weight * mlp_row
3097
-
3098
- return ensemble
3099
3134
 
3100
3135
  def _attention_weighted_ensemble(self, trans_probs, mlp_probs, attn_weights):
3101
3136
 
@@ -11687,6 +11722,12 @@ class AccurateAnswerCache:
11687
11722
  flat_ids_a = self.pipeline._safe_to_2d_float(ids_a)
11688
11723
  flat_ids_b = self.pipeline._safe_to_2d_float(ids_b)
11689
11724
 
11725
+ if flat_ids_a.shape != flat_ids_b.shape:
11726
+ min_rows = min(flat_ids_a.shape[0], flat_ids_b.shape[0])
11727
+ min_cols = min(flat_ids_a.shape[1], flat_ids_b.shape[1])
11728
+ flat_ids_a = flat_ids_a[:min_rows, :min_cols]
11729
+ flat_ids_b = flat_ids_b[:min_rows, :min_cols]
11730
+
11690
11731
  return flat_ids_a, flat_ids_b
11691
11732
  except Exception as e:
11692
11733
  print(f'[!] cannot adapt indices shape due to: {e}')
@@ -11780,6 +11821,7 @@ class AccurateAnswerCache:
11780
11821
 
11781
11822
  if ids_a.shape != ids_b.shape:
11782
11823
  ids_a, ids_b = self._adapt_ids_shape(ids_a, ids_b)
11824
+
11783
11825
  min_len = min(len(ids_a), len(ids_b))
11784
11826
  if min_len > 0:
11785
11827
  seq_sim = float(np.mean(ids_a[:min_len] == ids_b[:min_len]))
@@ -13479,6 +13521,9 @@ class PipelineAsyncManager:
13479
13521
  try:
13480
13522
  attn_weights = None
13481
13523
  final_idx = None
13524
+ attn_weight_rate = None
13525
+ final_idx = None
13526
+
13482
13527
  reverse_label_map = {v: k for k, v in label_map.items()}
13483
13528
 
13484
13529
  if 'attn_weights' in self.pipeline.model2.cache:
@@ -13506,8 +13551,14 @@ class PipelineAsyncManager:
13506
13551
  result, chosen_label, confidence = self.advanced_prediction_method(
13507
13552
  self.prediction_manager, test_titles, label_map, rules,
13508
13553
  X=X, y=y, method='Transformer_included')
13509
- if result and 'index' in result[0]:
13510
- final_idx = result[0]['index']
13554
+
13555
+ try:
13556
+ if isinstance(result, list) and len(result) > 0:
13557
+ final_idx = result[0].get('index')
13558
+ elif isinstance(result, dict):
13559
+ final_idx = result.get('index')
13560
+ except (KeyError, IndexError):
13561
+ final_idx = None
13511
13562
 
13512
13563
  print(f'[=+=] Local single advanced Prediction result: {result}')
13513
13564
 
@@ -13529,7 +13580,10 @@ class PipelineAsyncManager:
13529
13580
  except IndexError:
13530
13581
  calibrated_probs = probs + (1.0 - attn_weight_rate) * confidence
13531
13582
  else:
13532
- calibrated_probs = probs + (1.0 - attn_weight_rate) * confidence
13583
+ try:
13584
+ calibrated_probs = probs + (1.0 - attn_weight_rate) * confidence
13585
+ except:
13586
+ calibrated_probs = calibrated_probs.copy()
13533
13587
 
13534
13588
  predicted_index = np.argmax(calibrated_probs) # Get index with highest probability
13535
13589
  predicted_label = reverse_label_map.get(predicted_index, f"class_{predicted_index}")
@@ -13556,7 +13610,7 @@ class PipelineAsyncManager:
13556
13610
  else:
13557
13611
  print(f"[❌] INCORRECT LABEL (expected: {expected})")
13558
13612
 
13559
- predicted_output.append(f'{text} -> {predicted_label} With {confidence} Confidence')
13613
+ predicted_output.append(f'{text} -> {predicted_label} With {confidence:.1%} Confidence')
13560
13614
 
13561
13615
  # Get stats
13562
13616
  print(f"[=] Stats: {self.get_stats()}")
@@ -15328,7 +15382,7 @@ class ConsecutivePeerAgent:
15328
15382
 
15329
15383
  response = self._receive_message(sock)
15330
15384
 
15331
- print(f'[ConsecutivePeerAgent] Got Authentication response from peer: {response} ')
15385
+ print(f'[ConsecutivePeerAgent] Got Authentication response from peer!')
15332
15386
  if not response or response.get('status') != 'ok':
15333
15387
  sock.close()
15334
15388
  print('[ConsecutivePeerAgent] Socket is closed!')