Spaces:
Runtime error
Runtime error
prashasti commited on
Commit ·
13558c9
1
Parent(s): c016180
Revert "Improvements"
Browse filesThis reverts commit c01618015e2b8718ddbf6598bcf881c16c9d7778.
- inference.py +3 -49
- tasks/task_critical.py +1 -16
- tasks/task_multi_service.py +1 -15
- tasks/task_simple.py +4 -33
inference.py
CHANGED
|
@@ -40,31 +40,6 @@ if _OPENAI_AVAILABLE and API_KEY:
|
|
| 40 |
_client = OpenAI(api_key=API_KEY, base_url=API_BASE_URL)
|
| 41 |
|
| 42 |
|
| 43 |
-
def infer_root_cause(state: Dict[str, Any]) -> str:
|
| 44 |
-
logs = " ".join(state.get("logs", [])).lower()
|
| 45 |
-
metrics = state.get("metrics", {})
|
| 46 |
-
|
| 47 |
-
if "timeout" in logs or metrics.get("latency", 0) > 1000:
|
| 48 |
-
return "traffic_overload"
|
| 49 |
-
|
| 50 |
-
if "connection" in logs or "db" in logs:
|
| 51 |
-
return "database_issue"
|
| 52 |
-
|
| 53 |
-
if "cache" in logs:
|
| 54 |
-
return "cache_issue"
|
| 55 |
-
|
| 56 |
-
if metrics.get("cpu", 0) > 85:
|
| 57 |
-
return "resource_exhaustion"
|
| 58 |
-
|
| 59 |
-
return "unknown"
|
| 60 |
-
|
| 61 |
-
PLANS = {
|
| 62 |
-
"traffic_overload": ["scale_up", "restart_api"],
|
| 63 |
-
"database_issue": ["restart_db", "scale_up"],
|
| 64 |
-
"cache_issue": ["restart_cache", "scale_up"],
|
| 65 |
-
"resource_exhaustion": ["scale_up"],
|
| 66 |
-
}
|
| 67 |
-
|
| 68 |
# Heuristic fallback agent (used when no LLM key or on API error)
|
| 69 |
def _fallback_agent(state: Dict[str, Any], action_history: List[str]) -> str:
|
| 70 |
"""
|
|
@@ -131,9 +106,8 @@ def _call_llm(
|
|
| 131 |
|
| 132 |
services_degraded = [s for s, h in state["services"].items() if h == "degraded"]
|
| 133 |
metrics = state["metrics"]
|
| 134 |
-
root_cause = infer_root_cause(state)
|
| 135 |
|
| 136 |
-
prompt = f"""You are an expert SRE triaging a production incident. Your goal is to resolve it in as few steps as possible.
|
| 137 |
|
| 138 |
SYSTEM STATE (step {state['time_step']})
|
| 139 |
Degraded services : {services_degraded if services_degraded else 'none'}
|
|
@@ -202,28 +176,12 @@ def run_episode(task_name: str = "simple") -> None:
|
|
| 202 |
|
| 203 |
action_history: List[str] = []
|
| 204 |
reward_history: List[float] = []
|
| 205 |
-
bad_actions = set()
|
| 206 |
-
plan: List[str] = []
|
| 207 |
episode_logs: List[Dict[str, Any]] = []
|
| 208 |
done = False
|
| 209 |
step = 0
|
| 210 |
|
| 211 |
while not done and step < max_steps:
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
# generate plan if empty
|
| 215 |
-
if not plan:
|
| 216 |
-
plan = PLANS.get(root_cause, []).copy()
|
| 217 |
-
|
| 218 |
-
# choose from plan first
|
| 219 |
-
if plan:
|
| 220 |
-
action = plan.pop(0)
|
| 221 |
-
else:
|
| 222 |
-
action = _call_llm(state, action_history, reward_history)
|
| 223 |
-
|
| 224 |
-
# avoid bad actions
|
| 225 |
-
if action in bad_actions:
|
| 226 |
-
action = _fallback_agent(state, action_history)
|
| 227 |
|
| 228 |
try:
|
| 229 |
next_state, reward, done, info = env.step(action)
|
|
@@ -234,15 +192,11 @@ def run_episode(task_name: str = "simple") -> None:
|
|
| 234 |
|
| 235 |
action_history.append(action)
|
| 236 |
reward_history.append(reward)
|
| 237 |
-
|
| 238 |
-
if reward < -5:
|
| 239 |
-
bad_actions.add(action)
|
| 240 |
episode_logs.append({"reward": reward, "info": info})
|
| 241 |
|
| 242 |
print(
|
| 243 |
f"[STEP] step={step} action={action} reward={round(reward, 3)} "
|
| 244 |
-
f"done={str(done).lower()} error={error}
|
| 245 |
-
f"root_cause={root_cause} plan_remaining={len(plan)}",
|
| 246 |
flush=True,
|
| 247 |
)
|
| 248 |
|
|
|
|
| 40 |
_client = OpenAI(api_key=API_KEY, base_url=API_BASE_URL)
|
| 41 |
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
# Heuristic fallback agent (used when no LLM key or on API error)
|
| 44 |
def _fallback_agent(state: Dict[str, Any], action_history: List[str]) -> str:
|
| 45 |
"""
|
|
|
|
| 106 |
|
| 107 |
services_degraded = [s for s, h in state["services"].items() if h == "degraded"]
|
| 108 |
metrics = state["metrics"]
|
|
|
|
| 109 |
|
| 110 |
+
prompt = f"""You are an expert SRE triaging a production incident. Your goal is to resolve it in as few steps as possible.
|
| 111 |
|
| 112 |
SYSTEM STATE (step {state['time_step']})
|
| 113 |
Degraded services : {services_degraded if services_degraded else 'none'}
|
|
|
|
| 176 |
|
| 177 |
action_history: List[str] = []
|
| 178 |
reward_history: List[float] = []
|
|
|
|
|
|
|
| 179 |
episode_logs: List[Dict[str, Any]] = []
|
| 180 |
done = False
|
| 181 |
step = 0
|
| 182 |
|
| 183 |
while not done and step < max_steps:
|
| 184 |
+
action = _call_llm(state, action_history, reward_history)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
|
| 186 |
try:
|
| 187 |
next_state, reward, done, info = env.step(action)
|
|
|
|
| 192 |
|
| 193 |
action_history.append(action)
|
| 194 |
reward_history.append(reward)
|
|
|
|
|
|
|
|
|
|
| 195 |
episode_logs.append({"reward": reward, "info": info})
|
| 196 |
|
| 197 |
print(
|
| 198 |
f"[STEP] step={step} action={action} reward={round(reward, 3)} "
|
| 199 |
+
f"done={str(done).lower()} error={error}",
|
|
|
|
| 200 |
flush=True,
|
| 201 |
)
|
| 202 |
|
tasks/task_critical.py
CHANGED
|
@@ -25,7 +25,7 @@ class CriticalEnv(DebugEnv):
|
|
| 25 |
|
| 26 |
def reset(self) -> Dict[str, Any]:
|
| 27 |
state = super().reset()
|
| 28 |
-
|
| 29 |
self.state_data["root_cause"] = "memory_leak"
|
| 30 |
self.state_data["fix_sequence"] = ["restart_api", "restart_db"]
|
| 31 |
|
|
@@ -64,30 +64,15 @@ class CriticalEnv(DebugEnv):
|
|
| 64 |
|
| 65 |
def step(self, action: str) -> Tuple[Dict[str, Any], float, bool, Dict[str, Any]]:
|
| 66 |
obs, reward, done, info = super().step(action)
|
| 67 |
-
if action == getattr(self, "last_action", None):
|
| 68 |
-
reward -= 5.0
|
| 69 |
-
|
| 70 |
-
self.last_action = action
|
| 71 |
|
| 72 |
if info["latency"] > self.SLA_LATENCY_THRESHOLD:
|
| 73 |
reward -= self.SLA_PENALTY
|
| 74 |
|
| 75 |
if self.t > self.TIME_PRESSURE_START and not info["resolved"]:
|
| 76 |
reward -= self.TIME_PRESSURE_PENALTY
|
| 77 |
-
if action == "scale_up":
|
| 78 |
-
reward -= 2.0 # cost penalty
|
| 79 |
-
if action == getattr(self, "last_action", None):
|
| 80 |
-
reward -= 5.0
|
| 81 |
-
|
| 82 |
|
| 83 |
reward += random.uniform(-3, 3)
|
| 84 |
|
| 85 |
-
if info.get("resolved"):
|
| 86 |
-
info["explanation"] = "Incident resolved successfully"
|
| 87 |
-
elif reward > 0:
|
| 88 |
-
info["explanation"] = "Correct step towards resolution"
|
| 89 |
-
else:
|
| 90 |
-
info["explanation"] = "Ineffective or incorrect action"
|
| 91 |
return obs, reward, done, info
|
| 92 |
|
| 93 |
|
|
|
|
| 25 |
|
| 26 |
def reset(self) -> Dict[str, Any]:
|
| 27 |
state = super().reset()
|
| 28 |
+
|
| 29 |
self.state_data["root_cause"] = "memory_leak"
|
| 30 |
self.state_data["fix_sequence"] = ["restart_api", "restart_db"]
|
| 31 |
|
|
|
|
| 64 |
|
| 65 |
def step(self, action: str) -> Tuple[Dict[str, Any], float, bool, Dict[str, Any]]:
|
| 66 |
obs, reward, done, info = super().step(action)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
if info["latency"] > self.SLA_LATENCY_THRESHOLD:
|
| 69 |
reward -= self.SLA_PENALTY
|
| 70 |
|
| 71 |
if self.t > self.TIME_PRESSURE_START and not info["resolved"]:
|
| 72 |
reward -= self.TIME_PRESSURE_PENALTY
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
reward += random.uniform(-3, 3)
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
return obs, reward, done, info
|
| 77 |
|
| 78 |
|
tasks/task_multi_service.py
CHANGED
|
@@ -12,7 +12,6 @@ class MultiServiceEnv(DebugEnv):
|
|
| 12 |
|
| 13 |
def reset(self) -> Dict[str, Any]:
|
| 14 |
state = super().reset()
|
| 15 |
-
self.last_action = None
|
| 16 |
self.state_data["services"]["api"] = "degraded"
|
| 17 |
self.state_data["services"]["db"] = "degraded"
|
| 18 |
# Increase starting metric pressure
|
|
@@ -22,28 +21,15 @@ class MultiServiceEnv(DebugEnv):
|
|
| 22 |
self.state_data["metrics"]["error_rate"] = min(
|
| 23 |
self.state_data["metrics"]["error_rate"] * 1.2, 0.95
|
| 24 |
)
|
| 25 |
-
self.dependencies = {
|
| 26 |
-
"api": ["db"], # API depends on DB
|
| 27 |
-
}
|
| 28 |
return self._obs()
|
| 29 |
|
| 30 |
def step(self, action: str) -> Tuple[Dict[str, Any], float, bool, Dict[str, Any]]:
|
| 31 |
obs, reward, done, info = super().step(action)
|
| 32 |
-
if action == getattr(self, "last_action", None):
|
| 33 |
-
reward -= 5.0
|
| 34 |
-
|
| 35 |
-
self.last_action = action
|
| 36 |
-
# Dependency impact
|
| 37 |
-
if self.state_data["services"]["db"] == "down":
|
| 38 |
-
self.state_data["services"]["api"] = "degraded"
|
| 39 |
|
| 40 |
# Additional latency penalty for multi-service SLA
|
| 41 |
if info["latency"] > 300:
|
| 42 |
reward -= 10.0
|
| 43 |
-
|
| 44 |
-
reward -= 2.0 # cost penalty
|
| 45 |
-
|
| 46 |
-
info["explanation"] = f"Action {action} applied to fix issue"
|
| 47 |
return obs, reward, done, info
|
| 48 |
|
| 49 |
|
|
|
|
| 12 |
|
| 13 |
def reset(self) -> Dict[str, Any]:
|
| 14 |
state = super().reset()
|
|
|
|
| 15 |
self.state_data["services"]["api"] = "degraded"
|
| 16 |
self.state_data["services"]["db"] = "degraded"
|
| 17 |
# Increase starting metric pressure
|
|
|
|
| 21 |
self.state_data["metrics"]["error_rate"] = min(
|
| 22 |
self.state_data["metrics"]["error_rate"] * 1.2, 0.95
|
| 23 |
)
|
|
|
|
|
|
|
|
|
|
| 24 |
return self._obs()
|
| 25 |
|
| 26 |
def step(self, action: str) -> Tuple[Dict[str, Any], float, bool, Dict[str, Any]]:
|
| 27 |
obs, reward, done, info = super().step(action)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
# Additional latency penalty for multi-service SLA
|
| 30 |
if info["latency"] > 300:
|
| 31 |
reward -= 10.0
|
| 32 |
+
|
|
|
|
|
|
|
|
|
|
| 33 |
return obs, reward, done, info
|
| 34 |
|
| 35 |
|
tasks/task_simple.py
CHANGED
|
@@ -1,35 +1,6 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
import random
|
| 4 |
-
|
| 5 |
from env.environment import DebugEnv
|
| 6 |
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
def reset(self) -> Dict[str, Any]:
|
| 11 |
-
state = super().reset()
|
| 12 |
-
self.last_action = None
|
| 13 |
-
# Add slight noise to logs
|
| 14 |
-
if random.random() < 0.2:
|
| 15 |
-
self.state_data["logs"].append("intermittent network glitch detected")
|
| 16 |
-
|
| 17 |
-
return self._obs()
|
| 18 |
-
|
| 19 |
-
def step(self, action: str) -> Tuple[Dict[str, Any], float, bool, Dict[str, Any]]:
|
| 20 |
-
obs, reward, done, info = super().step(action)
|
| 21 |
-
if action == getattr(self, "last_action", None):
|
| 22 |
-
reward -= 5.0
|
| 23 |
-
|
| 24 |
-
self.last_action = action
|
| 25 |
-
|
| 26 |
-
# Slight metric fluctuation
|
| 27 |
-
self.state_data["metrics"]["latency"] += random.randint(-20, 20)
|
| 28 |
-
self.state_data["metrics"]["cpu"] += random.randint(-3, 3)
|
| 29 |
-
|
| 30 |
-
info["explanation"] = f"Action {action} applied to fix issue"
|
| 31 |
-
return obs, reward, done, info
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
def create_env() -> SimpleEnv:
|
| 35 |
-
return SimpleEnv(max_steps=15)
|
|
|
|
| 1 |
+
#Task: Simple: A single-service failure with a 2-step fix sequence.
|
| 2 |
+
#Entry-level task - low penalty, generous step budget.
|
|
|
|
|
|
|
| 3 |
from env.environment import DebugEnv
|
| 4 |
|
| 5 |
+
def create_env() -> DebugEnv:
|
| 6 |
+
return DebugEnv(max_steps=15)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|