AbstractIntegratedModule 0.8.5__tar.gz → 0.8.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.
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/AbstractIntegratedModule.egg-info/PKG-INFO +4 -3
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/AbstractIntegratedModule.py +183 -68
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/AbstractOptimizedModules.c +200 -200
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/PKG-INFO +4 -3
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/README.md +3 -2
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/setup.py +1 -1
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/AbstractIntegratedModule.egg-info/SOURCES.txt +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/AbstractIntegratedModule.egg-info/dependency_links.txt +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/AbstractIntegratedModule.egg-info/requires.txt +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/AbstractIntegratedModule.egg-info/top_level.txt +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/AbstractOptimizedModules.pyx +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/MANIFEST.in +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/abstract_model_storage/Cargo.toml +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/abstract_model_storage/pyproject.toml +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/abstract_model_storage/src/lib.rs +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/abstract_model_storage/target/debug/build/libsqlite3-sys-ed07b882cd2aa5e2/out/bindgen.rs +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/abstract_model_storage/target/debug/build/serde_core-ebc15f2e9cad7f5f/out/private.rs +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/abstract_model_storage/target/debug/build/target-lexicon-08527f45de28143d/out/host.rs +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/abstract_model_storage/target/release/build/libsqlite3-sys-bf0400df4523274c/out/bindgen.rs +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/abstract_model_storage/target/release/build/serde_core-5cdb76131825e4af/out/private.rs +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/abstract_model_storage/target/release/build/target-lexicon-43eb95a0588bf457/out/host.rs +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/pyproject.toml +0 -0
- {abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: AbstractIntegratedModule
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.6
|
|
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.
|
|
45
|
+
- Development Stage: 0.8.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.
|
|
@@ -80,9 +80,10 @@ 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.
|
|
83
|
+
- v0.8.6:
|
|
84
84
|
- [=] New features:
|
|
85
85
|
- Added new Optimization module using Cython maths for dynamic weighted ensemble function.
|
|
86
|
+
- Added Penalty for wrong prediction in both single advanced prediction and advanced batch prediction to reduce repetitive errors.
|
|
86
87
|
- Fixed P2P Vulnerabilities:
|
|
87
88
|
- Empty allowed_ips in PRODUCTION/HARDENED mode now DENIES external IPs instead of allowing all
|
|
88
89
|
- Startup validation warns about dangerous config combinations
|
{abstractintegratedmodule-0.8.5 → abstractintegratedmodule-0.8.6}/AbstractIntegratedModule.py
RENAMED
|
@@ -8544,6 +8544,7 @@ class IntegratedPipeline:
|
|
|
8544
8544
|
self.temperature = 1.0
|
|
8545
8545
|
self.transformer_lr = 0.1
|
|
8546
8546
|
self.max_seq_len = 16
|
|
8547
|
+
self.error_decay = 0.85
|
|
8547
8548
|
|
|
8548
8549
|
self.memory_name = memory_name
|
|
8549
8550
|
|
|
@@ -13517,41 +13518,51 @@ class PipelineAsyncManager:
|
|
|
13517
13518
|
self._save_state()
|
|
13518
13519
|
|
|
13519
13520
|
|
|
13520
|
-
def advanced_batch_prediction(self, test_titles, label_map, rules,
|
|
13521
|
+
def advanced_batch_prediction(self, test_titles, label_map, rules,
|
|
13522
|
+
X=None, y=None, api_key=None, client_ip=None):
|
|
13521
13523
|
try:
|
|
13522
|
-
attn_weights
|
|
13523
|
-
final_idx
|
|
13524
|
+
attn_weights = None
|
|
13525
|
+
final_idx = None
|
|
13524
13526
|
attn_weight_rate = None
|
|
13525
|
-
|
|
13527
|
+
confidence = None
|
|
13528
|
+
chosen_label = None
|
|
13526
13529
|
|
|
13527
13530
|
reverse_label_map = {v: k for k, v in label_map.items()}
|
|
13531
|
+
n_classes = len(label_map)
|
|
13528
13532
|
|
|
13529
13533
|
if 'attn_weights' in self.pipeline.model2.cache:
|
|
13530
13534
|
attn_weights = self.pipeline.model2.cache['attn_weights']
|
|
13531
13535
|
if attn_weights is not None:
|
|
13532
13536
|
attn_weight_growth = 1.0 / (1.0 + np.exp(-attn_weights[0]))
|
|
13533
|
-
attn_weight_rate
|
|
13537
|
+
attn_weight_rate = float(np.std(attn_weight_growth))
|
|
13534
13538
|
|
|
13535
|
-
|
|
13536
|
-
|
|
13537
|
-
expected_labels = [text[1] for text in test_titles] # Your ground truth
|
|
13539
|
+
texts = [text[0] for text in test_titles]
|
|
13540
|
+
expected_labels = [text[1] for text in test_titles]
|
|
13538
13541
|
predicted_output = []
|
|
13539
13542
|
|
|
13540
|
-
|
|
13543
|
+
text_payload = {
|
|
13544
|
+
"test_titles" : test_titles,
|
|
13545
|
+
"label_map" : label_map,
|
|
13546
|
+
"rules" : rules,
|
|
13547
|
+
"X" : X,
|
|
13548
|
+
"y" : y,
|
|
13549
|
+
"use_transformer": True
|
|
13550
|
+
}
|
|
13541
13551
|
|
|
13542
13552
|
if not self.pipeline.intents:
|
|
13543
|
-
result
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13548
|
-
|
|
13549
|
-
)
|
|
13553
|
+
result = self.predict(
|
|
13554
|
+
text_payload,
|
|
13555
|
+
timeout=self.pipeline.timeout,
|
|
13556
|
+
retries=None,
|
|
13557
|
+
api_key=api_key,
|
|
13558
|
+
client_ip=client_ip,
|
|
13559
|
+
)
|
|
13560
|
+
confidence = None # no confidence from this path
|
|
13550
13561
|
else:
|
|
13551
13562
|
result, chosen_label, confidence = self.advanced_prediction_method(
|
|
13552
|
-
self.prediction_manager, test_titles, label_map, rules,
|
|
13553
|
-
X=X, y=y, method='Transformer_included'
|
|
13554
|
-
|
|
13563
|
+
self.prediction_manager, test_titles, label_map, rules,
|
|
13564
|
+
X=X, y=y, method='Transformer_included'
|
|
13565
|
+
)
|
|
13555
13566
|
try:
|
|
13556
13567
|
if isinstance(result, list) and len(result) > 0:
|
|
13557
13568
|
final_idx = result[0].get('index')
|
|
@@ -13560,62 +13571,107 @@ class PipelineAsyncManager:
|
|
|
13560
13571
|
except (KeyError, IndexError):
|
|
13561
13572
|
final_idx = None
|
|
13562
13573
|
|
|
13563
|
-
print(f'[=+=] Local single advanced
|
|
13574
|
+
print(f'[=+=] Local single advanced prediction: {result}')
|
|
13575
|
+
print('[=] Initiating batch prediction...')
|
|
13564
13576
|
|
|
13565
|
-
print('[=] Initiating Batch prediction for multiple texts...')
|
|
13566
13577
|
results = self.predict_batch(
|
|
13567
13578
|
texts=texts,
|
|
13568
13579
|
timeout=self.pipeline.timeout,
|
|
13569
|
-
api_key=api_key
|
|
13580
|
+
api_key=api_key
|
|
13581
|
+
)
|
|
13582
|
+
|
|
13583
|
+
# class reputation track: how many times each class
|
|
13584
|
+
# was predicted wrong vs total predictions so far
|
|
13585
|
+
# error_rate[c] ∈ [0,1] — higher = this class is unreliable recently
|
|
13586
|
+
error_counts = np.zeros(n_classes, dtype=np.float64)
|
|
13587
|
+
pred_counts = np.zeros(n_classes, dtype=np.float64)
|
|
13588
|
+
decay = self.pipeline.error_decay # how fast old errors fade — tunable
|
|
13570
13589
|
|
|
13571
13590
|
print("========📊 PREDICTION RESULTS============")
|
|
13572
|
-
|
|
13573
|
-
for text, expected, probs in
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13578
|
-
|
|
13579
|
-
|
|
13580
|
-
|
|
13581
|
-
|
|
13591
|
+
|
|
13592
|
+
for idx, (text, expected, probs) in enumerate(
|
|
13593
|
+
zip(texts, expected_labels, results)
|
|
13594
|
+
):
|
|
13595
|
+
probs = np.asarray(probs, dtype=np.float64).copy()
|
|
13596
|
+
|
|
13597
|
+
# ── calibrate with single-prediction context ──────────────
|
|
13598
|
+
if (confidence is not None and
|
|
13599
|
+
attn_weight_rate is not None and
|
|
13600
|
+
final_idx is not None):
|
|
13601
|
+
|
|
13602
|
+
if 0 <= final_idx < len(probs):
|
|
13603
|
+
boost = (1.0 - attn_weight_rate) * confidence
|
|
13604
|
+
probs[final_idx] = min(probs[final_idx] + boost, 0.95)
|
|
13582
13605
|
else:
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
|
|
13606
|
+
boost = (1.0 - attn_weight_rate) * confidence
|
|
13607
|
+
probs = np.clip(probs + boost, 0.0, 0.95)
|
|
13608
|
+
|
|
13609
|
+
# ── apply class reputation penalty ────────────────────────
|
|
13610
|
+
# ounded reputation-based penalty
|
|
13611
|
+
# classes with high recent error rate get their probs dampened
|
|
13612
|
+
for c in range(n_classes):
|
|
13613
|
+
if pred_counts[c] > 0:
|
|
13614
|
+
error_rate = error_counts[c] / (pred_counts[c] + 1e-8)
|
|
13615
|
+
# sigmoid-shaped dampening — never goes negative
|
|
13616
|
+
# error_rate=0.0 → multiplier=1.0 (no change)
|
|
13617
|
+
# error_rate=0.5 → multiplier≈0.67
|
|
13618
|
+
# error_rate=1.0 → multiplier≈0.5
|
|
13619
|
+
reputation = 1.0 / (1.0 + error_rate)
|
|
13620
|
+
probs[c] *= reputation
|
|
13621
|
+
|
|
13622
|
+
# renormalize after reputation dampening
|
|
13623
|
+
prob_sum = probs.sum()
|
|
13624
|
+
if prob_sum > 1e-8:
|
|
13625
|
+
probs /= prob_sum
|
|
13626
|
+
|
|
13627
|
+
predicted_index = int(np.argmax(probs))
|
|
13628
|
+
predicted_label = reverse_label_map.get(
|
|
13629
|
+
predicted_index, f"class_{predicted_index}"
|
|
13630
|
+
)
|
|
13631
|
+
pred_conf = float(probs[predicted_index])
|
|
13632
|
+
|
|
13633
|
+
top_3_indices = np.argsort(probs)[-3:][::-1]
|
|
13634
|
+
top_3 = [
|
|
13635
|
+
(reverse_label_map.get(int(i), f"class_{i}"), float(probs[i]))
|
|
13636
|
+
for i in top_3_indices
|
|
13637
|
+
]
|
|
13587
13638
|
|
|
13588
|
-
predicted_index = np.argmax(calibrated_probs) # Get index with highest probability
|
|
13589
|
-
predicted_label = reverse_label_map.get(predicted_index, f"class_{predicted_index}")
|
|
13590
|
-
confidence = calibrated_probs[predicted_index]
|
|
13591
|
-
|
|
13592
|
-
# Get top 3 predictions for more insight
|
|
13593
|
-
top_3_indices = np.argsort(calibrated_probs)[-3:][::-1]
|
|
13594
|
-
top_3 = [(reverse_label_map.get(idx, f"class_{idx}"), calibrated_probs[idx]) for idx in top_3_indices]
|
|
13595
|
-
|
|
13596
13639
|
print(f"\n📌 Input: '{text}'")
|
|
13597
13640
|
print(f" [=] Expected: {expected}")
|
|
13598
|
-
print(f" 🎯 Predicted: {predicted_label} ({
|
|
13599
|
-
|
|
13600
|
-
# Show top 3 possibilities
|
|
13641
|
+
print(f" 🎯 Predicted: {predicted_label} ({pred_conf:.1%})")
|
|
13601
13642
|
print(f" 🔍 Top possibilities:")
|
|
13602
13643
|
for label, conf in top_3:
|
|
13603
13644
|
bar = '█' * int(conf * 20)
|
|
13604
13645
|
print(f"[•] {label:<25} {bar} {conf:.1%}")
|
|
13605
|
-
|
|
13606
|
-
# Match expected vs predicted
|
|
13646
|
+
|
|
13607
13647
|
print('===== COMPARISON MATCHING =====')
|
|
13608
|
-
|
|
13609
|
-
|
|
13648
|
+
is_correct = predicted_label == expected
|
|
13649
|
+
|
|
13650
|
+
# update class reputation — decay old counts first..
|
|
13651
|
+
error_counts *= decay
|
|
13652
|
+
pred_counts *= decay
|
|
13653
|
+
|
|
13654
|
+
pred_counts[predicted_index] += 1.0
|
|
13655
|
+
if not is_correct:
|
|
13656
|
+
print(f"[❌] INCORRECT (expected: {expected})")
|
|
13657
|
+
error_counts[predicted_index] += 1.0
|
|
13610
13658
|
else:
|
|
13611
|
-
print(f"[
|
|
13659
|
+
print(f"[✅] CORRECT!")
|
|
13612
13660
|
|
|
13613
|
-
predicted_output.append(
|
|
13661
|
+
predicted_output.append(
|
|
13662
|
+
f'{text} -> {predicted_label} With {pred_conf:.1%} Confidence'
|
|
13663
|
+
)
|
|
13614
13664
|
|
|
13615
|
-
#
|
|
13665
|
+
# batch accuracy summary
|
|
13666
|
+
correct = sum(
|
|
13667
|
+
1 for text, exp in zip(texts, expected_labels)
|
|
13668
|
+
for po in [predicted_output]
|
|
13669
|
+
if f'-> {exp}' in po
|
|
13670
|
+
)
|
|
13671
|
+
print(f"\n[=] Batch complete")
|
|
13616
13672
|
print(f"[=] Stats: {self.get_stats()}")
|
|
13617
|
-
print('[=] Returning predicted output
|
|
13618
|
-
return predicted_output
|
|
13673
|
+
print('[=] Returning predicted output.')
|
|
13674
|
+
return predicted_output
|
|
13619
13675
|
|
|
13620
13676
|
except Exception as e:
|
|
13621
13677
|
print(f'[=] Error in advanced batch prediction: {e}')
|
|
@@ -13891,7 +13947,14 @@ class PipelinePredictionManager:
|
|
|
13891
13947
|
self.titles, self.y_raw, self.label_map = self.load_labels_from_csv(label_csv, target_title, label)
|
|
13892
13948
|
except Exception as e:
|
|
13893
13949
|
print(f"Error loading labels: {e}")
|
|
13894
|
-
self.titles, self.y_raw, self.label_map =
|
|
13950
|
+
self.titles, self.y_raw, self.label_map = None, None, None
|
|
13951
|
+
|
|
13952
|
+
if self.label_map is not None:
|
|
13953
|
+
self.error_counts = np.zeros(len(self.label_map), dtype=np.float64)
|
|
13954
|
+
self.pred_counts = np.zeros(len(self.label_map), dtype=np.float64)
|
|
13955
|
+
self.decay = self.pipeline.error_decay # how fast old errors fade — tunable
|
|
13956
|
+
else:
|
|
13957
|
+
raise Warning('[!] Label map is None, consider adding label map!')
|
|
13895
13958
|
|
|
13896
13959
|
print(f"✅ Loaded {len(self.titles)} labeled examples")
|
|
13897
13960
|
|
|
@@ -14726,7 +14789,8 @@ class PipelinePredictionManager:
|
|
|
14726
14789
|
final_probs = mlp_weight * target_probs[i][:len(calibration)] + trans_weight * calibration[i][:len(calibration)] + lstm_weight * calibration[i][:len(calibration)]
|
|
14727
14790
|
else:
|
|
14728
14791
|
final_probs = mlp_weight * target_probs[i][:len(calibration)] + trans_weight * calibration[i][:len(calibration)]
|
|
14729
|
-
|
|
14792
|
+
|
|
14793
|
+
final_probs = self.calibration_penalized_check(final_probs, target_class_idx)
|
|
14730
14794
|
final_class_idx = target_class_idx
|
|
14731
14795
|
try:
|
|
14732
14796
|
final_confidence = final_probs[final_class_idx]
|
|
@@ -14740,6 +14804,8 @@ class PipelinePredictionManager:
|
|
|
14740
14804
|
agreement = mlp_class_idx == trans_class_idx
|
|
14741
14805
|
else:
|
|
14742
14806
|
final_probs = mlp_probs[i]
|
|
14807
|
+
final_probs = self.calibration_penalized_check(final_probs, mlp_class_idx)
|
|
14808
|
+
|
|
14743
14809
|
final_class_idx = mlp_class_idx
|
|
14744
14810
|
final_confidence = mlp_confidence[0] if isinstance(mlp_confidence, np.ndarray) else mlp_confidence
|
|
14745
14811
|
if isinstance(final_confidence, np.ndarray) or isinstance(final_confidence, list):
|
|
@@ -14843,7 +14909,9 @@ class PipelinePredictionManager:
|
|
|
14843
14909
|
print("\n[⚠️] Disagreement detected between MLP and Transformer predictions. Using calibrated probabilities for final decision.")
|
|
14844
14910
|
if not self.pipeline.autonomous and need_peer_condition:
|
|
14845
14911
|
print('|| Uncertain advanced prediction, requesting peer assistance if allowed...')
|
|
14846
|
-
final_probs = self.pipeline._handle_distributed_connections(final_probs, attn_weights, input_ids, agreement)
|
|
14912
|
+
final_probs = self.pipeline._handle_distributed_connections(final_probs, attn_weights, input_ids, agreement)
|
|
14913
|
+
|
|
14914
|
+
final_probs = self.calibration_penalized_check(final_probs, final_class_idx)
|
|
14847
14915
|
final_idx = final_probs[0].argmax()
|
|
14848
14916
|
original_idx = final_idx
|
|
14849
14917
|
|
|
@@ -14865,8 +14933,10 @@ class PipelinePredictionManager:
|
|
|
14865
14933
|
|
|
14866
14934
|
print('[||] Iniating local peer output search in database for best output...')
|
|
14867
14935
|
final_probs = self.pipeline.distribution._handle_peer_agent_request(final_probs, attn_weights, input_ids, type='DevicePeer', agreement=agreement)
|
|
14936
|
+
|
|
14937
|
+
final_probs = self.calibration_penalized_check(final_probs, final_class_idx)
|
|
14868
14938
|
final_idx = final_probs[0].argmax()
|
|
14869
|
-
original_idx = final_idx
|
|
14939
|
+
original_idx = final_idx
|
|
14870
14940
|
|
|
14871
14941
|
if final_idx > len(reverse_map):
|
|
14872
14942
|
final_idx = int(np.argmax(final_probs[:len(reverse_map)-1]))
|
|
@@ -14884,9 +14954,11 @@ class PipelinePredictionManager:
|
|
|
14884
14954
|
if final_confidence is not None and confidence < self.pipeline.confidence_threshold:
|
|
14885
14955
|
print("\n[⚠️] Low confidence detected, but both models don't agree. Using calibrated probabilities for final decision to ensure robustness.")
|
|
14886
14956
|
final_probs = self.pipeline.hybrid_prediction(rules, input_ids, dataset)
|
|
14957
|
+
|
|
14958
|
+
final_probs = self.calibration_penalized_check(final_probs, final_class_idx)
|
|
14887
14959
|
final_idx = final_probs[0].argmax()
|
|
14888
14960
|
original_idx = final_idx
|
|
14889
|
-
|
|
14961
|
+
|
|
14890
14962
|
if final_idx > len(reverse_map):
|
|
14891
14963
|
final_idx = int(np.argmax(final_probs[:len(reverse_map)-1]))
|
|
14892
14964
|
print(f"[⚠️] Clamping {final_idx} → {final_idx}")
|
|
@@ -14894,9 +14966,10 @@ class PipelinePredictionManager:
|
|
|
14894
14966
|
else:
|
|
14895
14967
|
print('[🎯] Stable confidence established, But both Models doesnt Agree, Re-evaluating...')
|
|
14896
14968
|
final_probs = self.pipeline.hybrid_prediction(rules, input_ids, dataset)
|
|
14969
|
+
|
|
14970
|
+
final_probs = self.calibration_penalized_check(final_probs, final_class_idx)
|
|
14897
14971
|
final_idx = final_probs[0].argmax()
|
|
14898
14972
|
original_idx = final_idx
|
|
14899
|
-
|
|
14900
14973
|
if final_idx > len(reverse_map):
|
|
14901
14974
|
final_idx = int(np.argmax(final_probs[:len(reverse_map)-1]))
|
|
14902
14975
|
print(f"[⚠️] Clamping {final_idx} → {final_idx}")
|
|
@@ -14912,6 +14985,8 @@ class PipelinePredictionManager:
|
|
|
14912
14985
|
print("\n[⚠️] Uncertain confidence and disagreement detected. Using ensemble method for final decision.")
|
|
14913
14986
|
input_forward = sequence_ids if sequence_ids is not None else input_ids
|
|
14914
14987
|
final_probs, details = self.pipeline.ensemble.predict_ensemble(input_forward, X, y, method='dynamic', embedded=True)
|
|
14988
|
+
|
|
14989
|
+
final_probs = self.calibration_penalized_check(final_probs, final_class_idx)
|
|
14915
14990
|
final_idx = final_probs[0].argmax()
|
|
14916
14991
|
original_idx = final_idx
|
|
14917
14992
|
|
|
@@ -14927,8 +15002,9 @@ class PipelinePredictionManager:
|
|
|
14927
15002
|
confidence = float(final_probs[0][len(reverse_map)-1]) if isinstance(final_probs[0], (float, int)) else 0.0
|
|
14928
15003
|
else:
|
|
14929
15004
|
input_forward = sequence_ids if sequence_ids is not None else input_ids
|
|
15005
|
+
final_probs = self.calibration_penalized_check(final_probs, final_class_idx)
|
|
14930
15006
|
final_idx = final_probs[0].argmax() if final_probs is not None else target_probs[0].argmax()
|
|
14931
|
-
|
|
15007
|
+
|
|
14932
15008
|
original_idx = final_idx
|
|
14933
15009
|
|
|
14934
15010
|
if final_idx > len(reverse_map):
|
|
@@ -14952,6 +15028,7 @@ class PipelinePredictionManager:
|
|
|
14952
15028
|
confidence = self.pipeline.confidence_threshold
|
|
14953
15029
|
|
|
14954
15030
|
elif confidence < self.pipeline.confidence_threshold and not self.pipeline.agreement and not results[0].get('models_agree', True):
|
|
15031
|
+
final_probs = self.calibration_penalized_check(final_probs, final_class_idx)
|
|
14955
15032
|
if trans_probs is not None:
|
|
14956
15033
|
prob_entropy = self.calculate_entropy(final_probs)
|
|
14957
15034
|
normalized_entropy = prob_entropy / np.log(prob_entropy.shape[-1]) if prob_entropy.shape[-1] > 1 else 0
|
|
@@ -14998,6 +15075,7 @@ class PipelinePredictionManager:
|
|
|
14998
15075
|
final_probs = target_probs.copy()
|
|
14999
15076
|
else:
|
|
15000
15077
|
print("\n[🎯] Using initial Regular final prediction as final decision.")
|
|
15078
|
+
final_probs = self.calibration_penalized_check(final_probs, final_class_idx)
|
|
15001
15079
|
final_idx = final_probs[0].argmax()
|
|
15002
15080
|
|
|
15003
15081
|
if final_idx > len(reverse_map):
|
|
@@ -15010,7 +15088,8 @@ class PipelinePredictionManager:
|
|
|
15010
15088
|
confidence = float(final_probs[0][final_idx])
|
|
15011
15089
|
except:
|
|
15012
15090
|
confidence = float(final_probs[0][len(reverse_map)-1]) if isinstance(final_probs[0], (float, int)) else 0.0
|
|
15013
|
-
|
|
15091
|
+
|
|
15092
|
+
|
|
15014
15093
|
if isinstance(chosen_label, str) and chosen_label.startswith("unknown") or float(confidence) < self.pipeline.confidence_threshold:
|
|
15015
15094
|
if chosen_label.startswith("unknown"):
|
|
15016
15095
|
chosen_label = 'Unknown'
|
|
@@ -15022,6 +15101,7 @@ class PipelinePredictionManager:
|
|
|
15022
15101
|
|
|
15023
15102
|
try:
|
|
15024
15103
|
consecutive_probs = self.pipeline.distribution._handle_peer_agent_request(target_probs, attn_weights, input_ids, type='DevicePeer', agreement=agreement)
|
|
15104
|
+
consecutive_probs = self.calibration_penalized_check(consecutive_probs, final_class_idx)
|
|
15025
15105
|
sec_final_idx = consecutive_probs[0].argmax()
|
|
15026
15106
|
|
|
15027
15107
|
if sec_final_idx > len(reverse_map):
|
|
@@ -15084,7 +15164,7 @@ class PipelinePredictionManager:
|
|
|
15084
15164
|
'X_samples': X,
|
|
15085
15165
|
'input_ids': input_ids
|
|
15086
15166
|
}
|
|
15087
|
-
correct, sec_correct = self.display_hybrid_results(payload, results, top_k, verbose=True)
|
|
15167
|
+
correct, sec_correct = self.display_hybrid_results(payload, final_class_idx, results, top_k, verbose=True)
|
|
15088
15168
|
if sec_chosen_label and sec_correct > correct:
|
|
15089
15169
|
print(f'[⚡] Second Prediction: {sec_chosen_label} has higher accuracies, relying on: {sec_chosen_label} as final label.')
|
|
15090
15170
|
chosen_label = sec_chosen_label # overrides previous chosen label if accuracy is higher
|
|
@@ -15097,18 +15177,48 @@ class PipelinePredictionManager:
|
|
|
15097
15177
|
self.pipeline.cache.clear()
|
|
15098
15178
|
|
|
15099
15179
|
return results, chosen_label, confidence
|
|
15180
|
+
|
|
15181
|
+
|
|
15182
|
+
def calibration_penalized_check(self, final_probs, predicted_index):
|
|
15183
|
+
# update class reputation.
|
|
15184
|
+
try:
|
|
15185
|
+
decay = self.pipeline.error_decay
|
|
15186
|
+
self.error_counts *= decay
|
|
15187
|
+
self.pred_counts *= decay
|
|
15188
|
+
|
|
15189
|
+
self.pred_counts[predicted_index] += 1.0
|
|
15190
|
+
n_classes = len(self.label_map)
|
|
15191
|
+
|
|
15192
|
+
for c in range(n_classes):
|
|
15193
|
+
if self.pred_counts[c] > 0:
|
|
15194
|
+
error_rate = self.error_counts[c] / (self.pred_counts[c] + 1e-8)
|
|
15195
|
+
# sigmoid-shaped dampening — never goes negative
|
|
15196
|
+
# error_rate=0.0 → multiplier=1.0 (no change)
|
|
15197
|
+
# error_rate=0.5 → multiplier≈0.67
|
|
15198
|
+
# error_rate=1.0 → multiplier≈0.5
|
|
15199
|
+
reputation = 1.0 / (1.0 + error_rate)
|
|
15200
|
+
final_probs[c] *= reputation
|
|
15201
|
+
|
|
15202
|
+
prob_sum = final_probs.sum()
|
|
15203
|
+
if prob_sum > 1e-8:
|
|
15204
|
+
final_probs /= prob_sum
|
|
15205
|
+
|
|
15206
|
+
except Exception as e:
|
|
15207
|
+
print(f'[!] Cant check and calibrate probs based on penalty due to: {e}')
|
|
15100
15208
|
|
|
15209
|
+
return final_probs
|
|
15210
|
+
|
|
15101
15211
|
|
|
15102
|
-
def display_hybrid_results(self, payload, results, top_k=3, verbose=False):
|
|
15212
|
+
def display_hybrid_results(self, payload, predicted_index, results, top_k=3, verbose=False):
|
|
15103
15213
|
print("\n" + "="*80)
|
|
15104
15214
|
print("[🎯] == PREDICTION RESULTS == ")
|
|
15105
15215
|
print("="*80)
|
|
15106
|
-
|
|
15216
|
+
|
|
15107
15217
|
correct = 0
|
|
15108
15218
|
sec_correct = 0
|
|
15109
15219
|
total_with_expected = 0
|
|
15110
15220
|
X_samples, input_ids = payload['X_samples'], payload['input_ids']
|
|
15111
|
-
|
|
15221
|
+
|
|
15112
15222
|
for idx, result in enumerate(results):
|
|
15113
15223
|
print(f"\n{idx+1}. 📌 '{result['title']}'")
|
|
15114
15224
|
|
|
@@ -15116,6 +15226,7 @@ class PipelinePredictionManager:
|
|
|
15116
15226
|
total_with_expected += 1
|
|
15117
15227
|
status = ": ✅" if result['predicted'] == result['expected'] else ": ❌"
|
|
15118
15228
|
print(f"[=] First Expectation: {result['expected']} || Model Answer: {status}")
|
|
15229
|
+
|
|
15119
15230
|
if 'sec_predicted' in result:
|
|
15120
15231
|
sec_status = ": ✅" if result['sec_predicted'] == result['expected'] else ": ❌"
|
|
15121
15232
|
print(f"[=] Second Expectation: {result['expected']} || Model Answer: {sec_status}")
|
|
@@ -15126,6 +15237,8 @@ class PipelinePredictionManager:
|
|
|
15126
15237
|
source='automatic_verified')
|
|
15127
15238
|
|
|
15128
15239
|
sec_correct += 1
|
|
15240
|
+
else:
|
|
15241
|
+
self.error_counts[predicted_index] += 1.0
|
|
15129
15242
|
|
|
15130
15243
|
if result['predicted'] == result['expected']:
|
|
15131
15244
|
if result['sec_index'] is None:
|
|
@@ -15137,6 +15250,8 @@ class PipelinePredictionManager:
|
|
|
15137
15250
|
source='automatic_verified')
|
|
15138
15251
|
|
|
15139
15252
|
correct += 1
|
|
15253
|
+
else:
|
|
15254
|
+
self.error_counts[predicted_index] += 1.0
|
|
15140
15255
|
|
|
15141
15256
|
# Agreement indicator
|
|
15142
15257
|
agree_symbol = "✓" if result.get('models_agree', True) else "⚠️"
|