Spaces:
Sleeping
Sleeping
Merge pull request #4 from suraj-gupta-01/phase2
Browse files- src/adaptive_alert_triage/utils.py +11 -0
- tasks/easy.py +12 -6
- tasks/hard.py +10 -8
- tasks/medium.py +10 -6
src/adaptive_alert_triage/utils.py
CHANGED
|
@@ -235,6 +235,15 @@ def generate_alert(
|
|
| 235 |
# Observable severity (noisy)
|
| 236 |
visible_severity: float = add_observation_noise(true_severity, confidence)
|
| 237 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
return Alert(
|
| 239 |
id=alert_id,
|
| 240 |
visible_severity=visible_severity,
|
|
@@ -246,10 +255,12 @@ def generate_alert(
|
|
| 246 |
metadata={
|
| 247 |
"false_positive": is_fp,
|
| 248 |
"generated_at_step": step,
|
|
|
|
| 249 |
},
|
| 250 |
)
|
| 251 |
|
| 252 |
|
|
|
|
| 253 |
# ---------------------------------------------------------------------------
|
| 254 |
# Correlated-alert chain generation
|
| 255 |
# ---------------------------------------------------------------------------
|
|
|
|
| 235 |
# Observable severity (noisy)
|
| 236 |
visible_severity: float = add_observation_noise(true_severity, confidence)
|
| 237 |
|
| 238 |
+
# --- Extreme Outlier Logic (stochastic noise for score variance) ---
|
| 239 |
+
# Adds a 2% chance of a "rogue" alert that contradicts its indicators,
|
| 240 |
+
# ensuring that even perfect agents have some score variance < 1.0.
|
| 241 |
+
if np.random.random() < 0.02:
|
| 242 |
+
if true_severity >= 0.8:
|
| 243 |
+
visible_severity = float(np.random.uniform(0.0, 0.2)) # "Hidden Critical"
|
| 244 |
+
elif true_severity <= 0.2:
|
| 245 |
+
visible_severity = float(np.random.uniform(0.8, 1.0)) # "Phantom Critical"
|
| 246 |
+
|
| 247 |
return Alert(
|
| 248 |
id=alert_id,
|
| 249 |
visible_severity=visible_severity,
|
|
|
|
| 255 |
metadata={
|
| 256 |
"false_positive": is_fp,
|
| 257 |
"generated_at_step": step,
|
| 258 |
+
"is_outlier": True, # mark for audit
|
| 259 |
},
|
| 260 |
)
|
| 261 |
|
| 262 |
|
| 263 |
+
|
| 264 |
# ---------------------------------------------------------------------------
|
| 265 |
# Correlated-alert chain generation
|
| 266 |
# ---------------------------------------------------------------------------
|
tasks/easy.py
CHANGED
|
@@ -60,7 +60,7 @@ _MEDIUM_ESCALATE_MIN: float = 0.60 # ESCALATE acceptable above this
|
|
| 60 |
_MEDIUM_IGNORE_MAX: float = 0.50 # IGNORE acceptable below this
|
| 61 |
|
| 62 |
# Pass threshold
|
| 63 |
-
SUCCESS_THRESHOLD: float = 0.
|
| 64 |
|
| 65 |
|
| 66 |
# ---------------------------------------------------------------------------
|
|
@@ -161,14 +161,20 @@ class EasyTaskGrader:
|
|
| 161 |
|
| 162 |
def get_episode_score(self) -> float:
|
| 163 |
"""
|
| 164 |
-
Return final normalised score in
|
| 165 |
|
| 166 |
-
Formula: correct_actions / total_actions
|
| 167 |
-
|
|
|
|
| 168 |
"""
|
| 169 |
if self.total_actions == 0:
|
| 170 |
-
return 0.
|
| 171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
|
| 173 |
def passed(self) -> bool:
|
| 174 |
"""Return True if the agent meets the easy-task success threshold."""
|
|
|
|
| 60 |
_MEDIUM_IGNORE_MAX: float = 0.50 # IGNORE acceptable below this
|
| 61 |
|
| 62 |
# Pass threshold
|
| 63 |
+
SUCCESS_THRESHOLD: float = 0.696
|
| 64 |
|
| 65 |
|
| 66 |
# ---------------------------------------------------------------------------
|
|
|
|
| 161 |
|
| 162 |
def get_episode_score(self) -> float:
|
| 163 |
"""
|
| 164 |
+
Return final normalised score in (0, 1).
|
| 165 |
|
| 166 |
+
Formula: 0.01 + 0.98 * (correct_actions / total_actions)
|
| 167 |
+
This ensures the score is always strictly between 0 and 1 as
|
| 168 |
+
required by the grading system.
|
| 169 |
"""
|
| 170 |
if self.total_actions == 0:
|
| 171 |
+
return 0.01
|
| 172 |
+
|
| 173 |
+
raw = self.correct_actions / self.total_actions
|
| 174 |
+
# Enforce strict (0, 1) range
|
| 175 |
+
clamped = 0.01 + 0.98 * raw
|
| 176 |
+
return round(float(clamped), 6)
|
| 177 |
+
|
| 178 |
|
| 179 |
def passed(self) -> bool:
|
| 180 |
"""Return True if the agent meets the easy-task success threshold."""
|
tasks/hard.py
CHANGED
|
@@ -372,15 +372,13 @@ class HardTaskGrader:
|
|
| 372 |
|
| 373 |
def get_episode_score(self) -> float:
|
| 374 |
"""
|
| 375 |
-
Return final normalised score in
|
| 376 |
|
| 377 |
Formula:
|
| 378 |
-
chain_score = Σ chain.outcome_score()
|
| 379 |
-
max_chain = Σ chain.max_possible() for all chains
|
| 380 |
-
isolation = min(isolation_correct * _ISOLATION_BONUS, cap)
|
| 381 |
-
raw = (chain_score + isolation) / max(max_chain, 1.0)
|
| 382 |
stability = _stability_score(system_failures)
|
| 383 |
-
|
|
|
|
| 384 |
"""
|
| 385 |
# Chain component
|
| 386 |
chain_score = sum(c.outcome_score() for c in self._chains.values())
|
|
@@ -396,8 +394,12 @@ class HardTaskGrader:
|
|
| 396 |
raw = min((chain_score + isolation) / denominator, 1.0)
|
| 397 |
|
| 398 |
stability = self._stability_score(self._system_failures)
|
| 399 |
-
|
| 400 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 401 |
|
| 402 |
def passed(self) -> bool:
|
| 403 |
"""Return True if the agent meets the hard-task success threshold."""
|
|
|
|
| 372 |
|
| 373 |
def get_episode_score(self) -> float:
|
| 374 |
"""
|
| 375 |
+
Return final normalised score in (0, 1).
|
| 376 |
|
| 377 |
Formula:
|
| 378 |
+
chain_score = Σ chain.outcome_score()
|
|
|
|
|
|
|
|
|
|
| 379 |
stability = _stability_score(system_failures)
|
| 380 |
+
base = (raw * stability)
|
| 381 |
+
clamped = 0.01 + 0.98 * base
|
| 382 |
"""
|
| 383 |
# Chain component
|
| 384 |
chain_score = sum(c.outcome_score() for c in self._chains.values())
|
|
|
|
| 394 |
raw = min((chain_score + isolation) / denominator, 1.0)
|
| 395 |
|
| 396 |
stability = self._stability_score(self._system_failures)
|
| 397 |
+
final_base = max(0.0, min(raw * stability, 1.0))
|
| 398 |
+
|
| 399 |
+
# Enforce strict (0, 1) range
|
| 400 |
+
clamped = 0.01 + 0.98 * final_base
|
| 401 |
+
return round(float(clamped), 6)
|
| 402 |
+
|
| 403 |
|
| 404 |
def passed(self) -> bool:
|
| 405 |
"""Return True if the agent meets the hard-task success threshold."""
|
tasks/medium.py
CHANGED
|
@@ -76,7 +76,7 @@ _CRITICAL_MISS_PENALTY_WEIGHT: float = 0.20
|
|
| 76 |
# Filtering-bonus cap so ignoring FPs never inflates score above 1.0
|
| 77 |
_FP_BONUS_CAP_PER_ALERT: float = 0.15
|
| 78 |
|
| 79 |
-
SUCCESS_THRESHOLD: float = 0.
|
| 80 |
|
| 81 |
|
| 82 |
# ---------------------------------------------------------------------------
|
|
@@ -192,14 +192,15 @@ class MediumTaskGrader:
|
|
| 192 |
|
| 193 |
def get_episode_score(self) -> float:
|
| 194 |
"""
|
| 195 |
-
Return final normalised score in
|
| 196 |
|
| 197 |
Formula:
|
| 198 |
raw = resolved_score / max_possible_score
|
| 199 |
-
|
|
|
|
| 200 |
"""
|
| 201 |
if self._max_possible_score <= 0.0:
|
| 202 |
-
return 0.
|
| 203 |
|
| 204 |
# Normalised resolved quality
|
| 205 |
raw = min(self._resolved_score / self._max_possible_score, 1.0)
|
|
@@ -218,8 +219,11 @@ class MediumTaskGrader:
|
|
| 218 |
miss_rate = 0.0
|
| 219 |
miss_penalty = _CRITICAL_MISS_PENALTY_WEIGHT * miss_rate
|
| 220 |
|
| 221 |
-
|
| 222 |
-
|
|
|
|
|
|
|
|
|
|
| 223 |
|
| 224 |
def passed(self) -> bool:
|
| 225 |
"""Return True if the agent meets the medium-task success threshold."""
|
|
|
|
| 76 |
# Filtering-bonus cap so ignoring FPs never inflates score above 1.0
|
| 77 |
_FP_BONUS_CAP_PER_ALERT: float = 0.15
|
| 78 |
|
| 79 |
+
SUCCESS_THRESHOLD: float = 0.549
|
| 80 |
|
| 81 |
|
| 82 |
# ---------------------------------------------------------------------------
|
|
|
|
| 192 |
|
| 193 |
def get_episode_score(self) -> float:
|
| 194 |
"""
|
| 195 |
+
Return final normalised score in (0, 1).
|
| 196 |
|
| 197 |
Formula:
|
| 198 |
raw = resolved_score / max_possible_score
|
| 199 |
+
base = max(0.0, raw − fp_penalty − miss_penalty)
|
| 200 |
+
clamped = 0.01 + 0.98 * base
|
| 201 |
"""
|
| 202 |
if self._max_possible_score <= 0.0:
|
| 203 |
+
return 0.01
|
| 204 |
|
| 205 |
# Normalised resolved quality
|
| 206 |
raw = min(self._resolved_score / self._max_possible_score, 1.0)
|
|
|
|
| 219 |
miss_rate = 0.0
|
| 220 |
miss_penalty = _CRITICAL_MISS_PENALTY_WEIGHT * miss_rate
|
| 221 |
|
| 222 |
+
base_score = max(0.0, raw - fp_penalty - miss_penalty)
|
| 223 |
+
# Enforce strict (0, 1) range
|
| 224 |
+
clamped = 0.01 + 0.98 * base_score
|
| 225 |
+
return round(float(clamped), 6)
|
| 226 |
+
|
| 227 |
|
| 228 |
def passed(self) -> bool:
|
| 229 |
"""Return True if the agent meets the medium-task success threshold."""
|