AbstractIntegratedModule 1.3.1__tar.gz → 1.3.2__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-1.3.1 → abstractintegratedmodule-1.3.2}/AbstractIntegratedModule.egg-info/PKG-INFO +2 -2
  2. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/AbstractIntegratedModule.py +85 -57
  3. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/AbstractOptimizedModules.c +567 -451
  4. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/AbstractOptimizedModules.pyx +6 -10
  5. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/PKG-INFO +2 -2
  6. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/README.md +125 -103
  7. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/pyproject.toml +2 -2
  8. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/setup.py +2 -2
  9. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/AbstractIntegratedModule.egg-info/SOURCES.txt +0 -0
  10. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/AbstractIntegratedModule.egg-info/dependency_links.txt +0 -0
  11. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/AbstractIntegratedModule.egg-info/requires.txt +0 -0
  12. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/AbstractIntegratedModule.egg-info/top_level.txt +0 -0
  13. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/MANIFEST.in +0 -0
  14. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/abstract_model_storage/Cargo.toml +0 -0
  15. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/abstract_model_storage/pyproject.toml +0 -0
  16. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/abstract_model_storage/src/lib.rs +0 -0
  17. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/abstract_model_storage/target/debug/build/libsqlite3-sys-ed07b882cd2aa5e2/out/bindgen.rs +0 -0
  18. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/abstract_model_storage/target/debug/build/serde_core-ebc15f2e9cad7f5f/out/private.rs +0 -0
  19. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/abstract_model_storage/target/debug/build/target-lexicon-08527f45de28143d/out/host.rs +0 -0
  20. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/abstract_model_storage/target/release/build/libsqlite3-sys-bf0400df4523274c/out/bindgen.rs +0 -0
  21. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/abstract_model_storage/target/release/build/serde_core-5cdb76131825e4af/out/private.rs +0 -0
  22. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/abstract_model_storage/target/release/build/target-lexicon-43eb95a0588bf457/out/host.rs +0 -0
  23. {abstractintegratedmodule-1.3.1 → abstractintegratedmodule-1.3.2}/setup.cfg +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AbstractIntegratedModule
3
- Version: 1.3.1
4
- Summary: Integrated Pipeline with Specialized Non-LLM AI Agent Framework for ARM64 architecture
3
+ Version: 1.3.2
4
+ Summary: IntegratedPipeline Specifically provide a Framework to build Stateful continual learning Machine Learning Models optimized for Edge devices (ARM64).
5
5
  Author: Micro-Novelty
6
6
  Author-email: Micro-Novelty <hernikpuspita5@gmail.com>
7
7
  License-Expression: MIT
@@ -2725,11 +2725,20 @@ class Transformer(TargetMemoryMixin):
2725
2725
 
2726
2726
  # Optimized Project heads with Cython implementation.
2727
2727
  if _OPT_AVAILABLE:
2728
- B, S, D = batch_size, seq_len, d_model
2729
- M = D // self.n_heads
2730
- Q = optimized_project_heads(x, W_q_mix, B, S, self.n_heads, D, M)
2731
- K = optimized_project_heads(x, W_k_mix, B, S, self.n_heads, D, M)
2732
- V = optimized_project_heads(x, W_v_mix, B, S, self.n_heads, D, M)
2728
+ try:
2729
+ x_c = np.ascontiguousarray(x, dtype=np.float64)
2730
+ Wq_c = np.ascontiguousarray(W_q_mix, dtype=np.float64)
2731
+ Wk_c = np.ascontiguousarray(W_k_mix, dtype=np.float64)
2732
+ Wv_c = np.ascontiguousarray(W_v_mix, dtype=np.float64)
2733
+
2734
+ B, S, D = batch_size, seq_len, d_model
2735
+ M = D // self.n_heads
2736
+ Q = optimized_project_heads(x, Wq_c, B, S, self.n_heads, D, M)
2737
+ K = optimized_project_heads(x, Wk_c, B, S, self.n_heads, D, M)
2738
+ V = optimized_project_heads(x, Wv_c, B, S, self.n_heads, D, M)
2739
+ except Exception as e:
2740
+ print(f'[>] Error in optimize project head: {e}')
2741
+ continue
2733
2742
 
2734
2743
  else:
2735
2744
  Q = np.einsum('bsd,hdm->bhsm', x, W_q_mix)
@@ -2880,13 +2889,12 @@ class Transformer(TargetMemoryMixin):
2880
2889
  def forward(self, input_ids, AME=None, _update_quality_matrix=None, embedded=False, pad_token_id=0, training=True, attn_dropout=0.1, ffn_dropout=0.1):
2881
2890
  eps = 1e-3
2882
2891
  self._forward_count += 1
2883
-
2884
2892
 
2885
2893
  # Clean up old cache entries before storing new ones
2886
2894
  self._clear_forward_cache(keep_essential=True, max_age_forward_passes=5)
2887
2895
 
2888
2896
  if embedded:
2889
- x = self._handle_indices(input_ids, dtype=np.int64)
2897
+ x = self._handle_indices(input_ids, dtype=np.float64)
2890
2898
  if x.ndim == 2:
2891
2899
  x = x[np.newaxis, ...]
2892
2900
  batch_size, seq_len, _ = x.shape
@@ -2894,7 +2902,7 @@ class Transformer(TargetMemoryMixin):
2894
2902
  self.cache['input_ids'] = None
2895
2903
  mask = None
2896
2904
  else:
2897
- input_ids = self._handle_indices(input_ids, dtype=np.int32)
2905
+ input_ids = self._handle_indices(input_ids, dtype=np.float32)
2898
2906
  if input_ids.ndim == 1:
2899
2907
  input_ids = input_ids[np.newaxis, :]
2900
2908
 
@@ -10384,6 +10392,7 @@ class AgentDistributedInference:
10384
10392
  self._health_check_interval = 30 # seconds
10385
10393
 
10386
10394
  self.use_async = use_async
10395
+ self.agent_id = id(self)
10387
10396
 
10388
10397
  # Register message handlers
10389
10398
  print('[=++=] Initiating message Queue')
@@ -11372,7 +11381,12 @@ class AgentDistributedInference:
11372
11381
 
11373
11382
  if not text and not test_titles:
11374
11383
  print('[INFO] No text or test_titles in message payload.')
11375
-
11384
+
11385
+ if test_titles is not None and self.predict_manager is None:
11386
+ raise RuntimeError('[>] predict manager not set; cannot run advanced prediction method')
11387
+ if text is None and test_titles is None:
11388
+ raise ValueError('[>] Payload has neither text or titles.')
11389
+
11376
11390
  # Run the actual prediction
11377
11391
  print(f'[=] Initiating prediction method')
11378
11392
  try:
@@ -11405,8 +11419,10 @@ class AgentDistributedInference:
11405
11419
 
11406
11420
  else:
11407
11421
  print('[=] Iniatiting basic prediction...')
11408
- result = await asyncio.to_thread(self.pipeline.predict_single, text)
11409
-
11422
+ result = await asyncio.to_thread(self.pipeline.predict_text, text)
11423
+ if not isinstance(result, dict):
11424
+ raise TypeError(f"[>] Predict single returned {type(result).__name__}: {result!r}")
11425
+
11410
11426
  return {
11411
11427
  'type': self.MSG_TYPES['PREDICT_RESPONSE'],
11412
11428
  'prediction': result.get('prediction'),
@@ -11418,7 +11434,7 @@ class AgentDistributedInference:
11418
11434
  else:
11419
11435
 
11420
11436
  print('[=] Basic prediction method')
11421
- result = await asyncio.to_thread(self.pipeline.predict_single, text)
11437
+ result = await asyncio.to_thread(self.pipeline.predict_text, text)
11422
11438
 
11423
11439
  return {
11424
11440
  'type': self.MSG_TYPES['PREDICT_RESPONSE'],
@@ -11799,7 +11815,7 @@ class AgentDistributedInference:
11799
11815
  msg_len = int.from_bytes(data_len, 'big')
11800
11816
  if msg_len > self.max_message_size:
11801
11817
  print('[=] message size exceeds maximum to be handled')
11802
- self.log_security_event('message_too_large', {'size': msg_len})
11818
+ self._log_security_event('message_too_large', {'size': msg_len})
11803
11819
  return None
11804
11820
 
11805
11821
  data = b''
@@ -13736,6 +13752,17 @@ class IntegratedPipeline:
13736
13752
  self.tfidf.fit_transform(text).toarray()
13737
13753
  vocab_size = len(self.tfidf.get_feature_names_out())
13738
13754
  self.vocab_size = vocab_size
13755
+
13756
+ def predict_text(self, text):
13757
+ probs = np.asarray(self.predict_single(text), dtype=np.float64).ravel()
13758
+ idx = int(np.argmax(probs))
13759
+ label_map = getattr(self.manager, 'label_map')
13760
+ reverse = {v: k for k, v in label_map.items()}
13761
+ return {
13762
+ 'prediction': reverse.get(idx, f'class_{idx}'),
13763
+ 'confidence': float(probs[idx]),
13764
+ 'probabilities': probs.tolist(),
13765
+ }
13739
13766
 
13740
13767
 
13741
13768
  def initialize_model_encoding(self, X, y_raw):
@@ -14856,40 +14883,37 @@ class IntegratedPipeline:
14856
14883
  return None
14857
14884
 
14858
14885
  def prediction_batch(self, texts):
14859
- self.initialize_fitting(texts)
14886
+ """Returns an ndarray of shape (len(texts), num_classes) with probabilities."""
14887
+ # normalise input
14888
+ if texts is None:
14889
+ return np.zeros((0, self._get_num_classes() or 1))
14890
+ if isinstance(texts, (str, np.str_)):
14891
+ texts = [texts]
14892
+ texts = [t[0] if isinstance(t, tuple) else t for t in texts]
14893
+ texts = ['' if t is None else str(t) for t in texts]
14860
14894
  if not texts:
14861
- return []
14862
-
14863
- # Prepare batch inputs
14895
+ return np.zeros((0, self._get_num_classes() or 1))
14864
14896
 
14865
- input_ids_list = []
14866
- X_raw_list = []
14897
+ if self.model3 is None:
14898
+ raise RuntimeError('[>] MLP model is not initialized/trained; cannot predict')
14867
14899
 
14868
- for text in texts:
14869
- # Prepare transformer input
14870
- input_ids = np.array([self.encode(text, self.vocab)])
14871
- input_ids_list.append(input_ids)
14872
-
14873
- # Prepare MLP input
14874
- if not hasattr(self, 'tfidf') or self.tfidf is None:
14875
- self.initialize_fitting([text])
14876
- X_raw = self.tfidf.transform([text]).toarray()
14877
- X_raw_list.append(X_raw)
14878
-
14879
- # Stack into batches
14880
- batch_input_ids = np.vstack(input_ids_list) # (batch_size, seq_len)
14881
- batch_X_raw = np.vstack(X_raw_list) # (batch_size, features)
14882
-
14883
- if self.labels is None and self.titles is None:
14884
- _, y_true = self.input_encoding(list(zip(texts, texts))) # No-value labels for y_true
14885
- else:
14886
- dataset, _ = self.data_preparation(self.titles, self.labels)
14887
- y_true = self.input_encoding(dataset)
14888
-
14889
- # Run batch prediction through your existing logic
14890
- return self._batch_prediction_core(batch_input_ids, batch_X_raw, y_true)
14900
+ # MLP features: same hashing vectorizer as training, never refit on request text
14901
+ _, X_raw = self.data_preparation(texts)
14902
+ X_raw = np.asarray(X_raw, dtype=np.float64)
14903
+
14904
+ first = self.model3.layers[0] if self.model3.layers else None
14905
+ input_dim = getattr(first, 'input_size', None)
14906
+ if input_dim and X_raw.shape[1] != input_dim:
14907
+ X_raw = self.shape_adaptation(X_raw, input_dim)
14891
14908
 
14909
+ # transformer token ids
14910
+ if not self.vocab:
14911
+ self.text_encoder(texts)
14912
+ ids = np.array([self.encode(t, self.vocab) for t in texts], dtype=np.int64)
14913
+ if self.model2 is not None and hasattr(self.model2, 'token_embedding'):
14914
+ ids = np.clip(ids, 0, self.model2.token_embedding.shape[0] - 1)
14892
14915
 
14916
+ return self._batch_prediction_core(ids, X_raw, batch_size=None, show_progress=False)
14893
14917
 
14894
14918
  def _batch_model_memory_gate(self, batch_input_ids, batch_X_raw):
14895
14919
  batch_probs = [None] * len(batch_input_ids)
@@ -15080,10 +15104,8 @@ class IntegratedPipeline:
15080
15104
  fresh_mlp_confidence = fresh_probs.max(axis=1, keepdims=True)
15081
15105
  fresh_trans_confidence = fresh_trans_probs.max(axis=1, keepdims=True)
15082
15106
 
15083
- if fresh_mlp_confidence >= fresh_trans_confidence:
15084
- fresh_probs = fresh_probs.copy()
15085
- else:
15086
- fresh_probs = fresh_trans_probs.copy()
15107
+ use_mlp = (fresh_mlp_confidence >= fresh_trans_confidence)
15108
+ fresh_probs = np.where(use_mlp, fresh_probs, fresh_trans_probs)
15087
15109
 
15088
15110
  if np.std(fresh_probs) < 0.3 or np.mean(fresh_probs) < 0.3:
15089
15111
  fresh_probs = self.predict_proba(
@@ -15215,18 +15237,20 @@ class IntegratedPipeline:
15215
15237
  return None
15216
15238
 
15217
15239
 
15218
- def predict_single(self, text):
15240
+ def predict_single(self, text, timeout=250):
15219
15241
  result = [None]
15242
+ done = threading.Event()
15220
15243
 
15221
15244
  def callback(r):
15222
15245
  result[0] = r
15246
+ done.set()
15223
15247
 
15224
15248
  self.predict_async(text, callback)
15225
-
15249
+ if not done.wait(timeout):
15250
+ raise TimeoutError('[>] Single async prediction timed out.')
15226
15251
  # Wait for result
15227
- while result[0] is None:
15228
- time.sleep(0.001)
15229
-
15252
+ if isinstance(result[0], BaseException):
15253
+ raise result[0]
15230
15254
  return result[0]
15231
15255
 
15232
15256
 
@@ -15276,10 +15300,8 @@ class IntegratedPipeline:
15276
15300
  fresh_mlp_confidence = fresh_probs.max(axis=1, keepdims=True)
15277
15301
  fresh_trans_confidence = fresh_trans_probs.max(axis=1, keepdims=True)
15278
15302
 
15279
- if fresh_mlp_confidence >= fresh_trans_confidence:
15280
- fresh_probs = fresh_probs.copy()
15281
- else:
15282
- fresh_probs = fresh_trans_probs.copy()
15303
+ use_mlp = (fresh_mlp_confidence >= fresh_trans_confidence)
15304
+ fresh_probs = np.where(use_mlp, fresh_probs, fresh_trans_probs)
15283
15305
 
15284
15306
  if np.std(fresh_probs) < 0.3 or np.mean(fresh_probs) < 0.3:
15285
15307
  fresh_probs, _ = self.ensemble.predict_ensemble(
@@ -19360,6 +19382,9 @@ class PipelineAsyncManager:
19360
19382
  self.max_workers = max_workers
19361
19383
  self.default_timeout = task_timeout
19362
19384
  self.max_retries = max_retries
19385
+
19386
+ self.pipeline.manager = self.prediction_manager
19387
+ self.pipeline.distribution.predict_manager = self.prediction_manager
19363
19388
 
19364
19389
  self.security_level = security_level
19365
19390
  self.config = self._get_config_for_level(security_level) or SecurityConfig()
@@ -24282,7 +24307,7 @@ class PipelinePredictionManager:
24282
24307
  total_with_expected = 0
24283
24308
  X_samples, input_ids = payload['X_samples'], payload['input_ids']
24284
24309
 
24285
- if len(self.error_counts) < 1:
24310
+ if self.error_counts is None or len(self.error_counts) < 1:
24286
24311
  self.error_counts = np.zeros(len(self.label_map), dtype=np.float32)
24287
24312
 
24288
24313
  for idx, result in enumerate(results):
@@ -24473,7 +24498,7 @@ class ConsecutivePeerAgent:
24473
24498
  print(f'[ConsecutivePeerAgent] Received a message!')
24474
24499
  except (json.JSONDecodeError, UnicodeDecodeError) as e:
24475
24500
  logger.warning(f'[=] Invalid JSON from peer: {e}')
24476
- self._log_security_event('invalid_json', {})
24501
+ self.pipeline.distribution._log_security_event('invalid_json', {})
24477
24502
  return None
24478
24503
 
24479
24504
  message = self._decode_arrays_from_wire(message)
@@ -24902,6 +24927,9 @@ class CohesiveAgentDeployment:
24902
24927
  target_title=target_title,
24903
24928
  label=label_name
24904
24929
  )
24930
+ self.pipeline.manager = self.manager
24931
+ self.pipeline.distribution.predict_manager = self.manager
24932
+
24905
24933
  if self.manager.config is None and predict_manager is not None:
24906
24934
  self.manager.config = predict_manager.config
24907
24935