Spaces:
Sleeping
Sleeping
File size: 5,190 Bytes
39bbca0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | """
Decision Engine for VeriLens AI
Combines ML prediction, verification similarity, source credibility,
and NLP analysis into a final verdict.
"""
from __future__ import annotations
from dataclasses import dataclass, field
@dataclass
class Decision:
prediction: str # "REAL", "FAKE", or "UNCERTAIN"
confidence: int # 0 β 100
explanation: str
factors: dict = field(default_factory=dict)
def make_decision(
ml_label: str,
ml_confidence: float,
similarity_score: float,
sources_verified: bool,
suspicious_info: dict,
high_trust_count: int = 0,
low_trust_count: int = 0,
) -> Decision:
"""Weighted decision combining multiple signals."""
# ββ ML score contribution (0-45) ββββββββββββββββββββββββββββββββββββββββ
if ml_label == "FAKE":
ml_score = (1 - ml_confidence) * 45
elif ml_label == "REAL":
ml_score = ml_confidence * 45
else:
ml_score = 22.5
# ββ Verification score contribution (0-25) ββββββββββββββββββββββββββββββ
if sources_verified:
verify_score = similarity_score * 25
else:
verify_score = 12.5
# ββ Source credibility contribution (0-15) ββββββββββββββββββββββββββββββ
if high_trust_count + low_trust_count > 0:
cred_ratio = high_trust_count / (high_trust_count + low_trust_count)
cred_score = cred_ratio * 15
elif sources_verified:
cred_score = 7.5
else:
cred_score = 7.5
# ββ Suspicious language penalty (0-15) ββββββββββββββββββββββββββββββββββ
sus_count = suspicious_info.get("total_suspicious_count", 0)
if sus_count == 0:
sus_score = 15
elif sus_count <= 2:
sus_score = 10
elif sus_count <= 5:
sus_score = 5
else:
sus_score = 0
# ββ Aggregate βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
total = ml_score + verify_score + cred_score + sus_score
total = max(0, min(100, total))
# ββ Guard: prevent FAKE ML prediction from flipping to Real βββββββββ
ml_fake_overridden = False
if ml_label == "FAKE" and ml_confidence >= 0.6 and total >= 65:
total = 55
ml_fake_overridden = True
# ββ Decide verdict (STANDARDIZED TO UPPERCASE) ββββββββββββββββββββββ
if total >= 65:
prediction = "REAL"
elif total <= 40:
prediction = "FAKE"
else:
prediction = "UNCERTAIN"
# ββ Confidence relative to the prediction βββββββββββββββββββββββββββ
if prediction == "REAL":
confidence = int(round(total))
elif prediction == "FAKE":
confidence = 100 - int(round(total))
else:
distance = abs(total - 52.5)
confidence = max(30, min(50, int(round(50 - distance))))
# ββ Build explanation βββββββββββββββββββββββββββββββββββββββββββββββββββ
explanations: list[str] = []
if ml_label == "FAKE":
explanations.append(f"The AI model classified this as FAKE with {ml_confidence:.0%} confidence.")
if ml_fake_overridden:
explanations.append("Although related articles exist online, they may be debunking the claim rather than confirming it.")
elif ml_label == "REAL":
explanations.append(f"The AI model classified this as REAL with {ml_confidence:.0%} confidence.")
else:
explanations.append("The AI model could not reach a strong conclusion.")
if sources_verified:
if similarity_score > 0.6:
explanations.append("The claim is well-corroborated by multiple online sources.")
elif similarity_score > 0.3:
explanations.append("Some related articles were found, but corroboration is partial.")
else:
explanations.append("Very few matching sources were found online.")
else:
explanations.append("Internet verification was not available; the verdict relies on AI analysis.")
if sus_count > 3:
explanations.append("High levels of suspicious, sensationalist, or emotional language detected.")
elif sus_count > 0:
explanations.append("Minor suspicious language patterns were noted.")
explanation = " ".join(explanations)
factors = {
"ml_score": round(ml_score, 2),
"verification_score": round(verify_score, 2),
"credibility_score": round(cred_score, 2),
"language_score": round(sus_score, 2),
}
return Decision(
prediction=prediction,
confidence=confidence,
explanation=explanation,
factors=factors,
) |