div18 commited on
Commit
b84be63
·
1 Parent(s): 92019fc

fix(inference): add debugging and error handling for env.step action calls

Browse files

- Log each action step with compacted action string for better traceability
- Catch and log RuntimeError exceptions during env.step to identify failures
- Re-raise exceptions after logging to maintain original error flow
- Ensure printed debug information flushes stdout immediately for real-time monitoring

feat(reward): add comprehensive AntiAtropos reward function specification

- Provide detailed Markdown documentation explaining reward function design
- Describe multi-scale control signal architecture for Autonomous SRE
- Explain Lyapunov graph energy, reward composition, sigmoid normalization
- Outline layered action-efficiency penalties and episode grading system
- Highlight theoretical guarantees and practical innovation in reward design

fix(environment): correct idle capacity calculation to prevent negative values

- Adjust idle capacity formula to use max(0, ...) to avoid negative idle counts
- Clarify commented explanation to reflect correction for idle capacity calculation
- Maintain tiered cost computation consistent with three-tier infrastructure model

REWARD_FUNCTION.md ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # The AntiAtropos Reward Function
2
+
3
+ A physics-grounded, multi-scale control signal for Autonomous SRE — built on Lyapunov stability theory, graph-aware energy, three-tier cost economics, and smooth preventive SLA gradients.
4
+
5
+ ---
6
+
7
+ ## Architecture at a Glance
8
+
9
+ The reward operates at three temporal scales:
10
+
11
+ | Scale | Purpose | Consumer |
12
+ |-------|---------|----------|
13
+ | **Per-step** | Immediate feedback on stability, cost, SLA, action quality | LLM agent |
14
+ | **Per-episode** | Holistic grading across uptime, cost, stability | Leaderboard |
15
+ | **Cross-episode** | Sustained-excellence bonuses | Leaderboard |
16
+
17
+ No single term dominates — a healthy cluster with wasted capacity scores poorly, as does a cheap cluster with burning queues.
18
+
19
+ ---
20
+
21
+ ## Layer 1: Lyapunov Graph Energy
22
+
23
+ ```
24
+ V_graph(s) = Σ w_i · Q_i² + edge_weight · Σ_{(i,j)∈E} |Q_i − Q_j|
25
+ ```
26
+
27
+ **Node energy** — Squared queue depths weighted by business importance (node-0 VIP = 2×). Squaring penalizes load concentration: one node at Q=100 is far worse than five at Q=20.
28
+
29
+ **Edge imbalance** — Penalizes flow mismatch across DAG edges. If a parent has deep queues but its child is idle, the edge term fires even though the child's individual energy is zero. This gives the agent gradient signal to **balance load across topology**, not just minimize individual queues.
30
+
31
+ ---
32
+
33
+ ## Layer 2: Reward Composition
34
+
35
+ ```
36
+ R_t = −(α·ΔV + β·Cost + γ·SLA + δ·Barrier)
37
+ ```
38
+
39
+ ### ΔV — Lyapunov Drift (α = 0.002)
40
+
41
+ One-step change in cluster energy. Negative = stabilizing. Positive = destabilizing. The small weight makes it a **directional nudge**, not a sledgehammer. Grounded in Neely's Drift-Plus-Penalty framework, which guarantees queue stability with bounded average cost.
42
+
43
+ ### Cost — Three-Tier Infrastructure Model (β = 1.5)
44
+
45
+ ```
46
+ needed = ⌈incoming_rate / 15⌉
47
+ ```
48
+
49
+ | Tier | Range | Rate | Rationale |
50
+ |------|-------|------|-----------|
51
+ | **Baseline** | ≤ DEFAULT_CAPACITY (3) | $0.05/u/hr | Already provisioned — sunk cost, no penalty |
52
+ | **Justified** | >3, ≤ needed | $0.20/u/hr (4×) | Extra capacity serving traffic — defensible spend |
53
+ | **Idle waste** | > needed | $1.00/u/hr (20×) | Capacity sitting idle — pure waste |
54
+
55
+ A naive two-tier model (cheap ≤ needed, expensive > needed) penalizes baseline capacity as "overprovisioned" because `needed` can be 1 while DEFAULT_CAPACITY is 3. The three-tier model recognizes that **baseline infrastructure is already paid for** — only agent-added capacity triggers premium pricing.
56
+
57
+ Baseline cost: 5 nodes × 3 units × $0.05 = **$0.75/hr**. Scaling one node to capacity=6 (3 justified + 0 idle) costs $0.75 + $0.60 = $1.35/hr.
58
+
59
+ ### SLA — Smooth Preventive Penalty (γ = 4.0)
60
+
61
+ ```
62
+ sla = max(σ(latency, threshold=0.20, temp=0.03), σ(errors, threshold=0.05, temp=0.01))
63
+ ```
64
+
65
+ Dual sigmoids with **max** operator — worst dimension dominates. Unlike binary penalties (0 or 1), the sigmoid provides **gradient before the violation**, enabling the agent to learn preventive scaling. Asymmetric temperatures reflect operational reality: latency degrades gradually (wide band), error rates spike sharply (narrow band).
66
+
67
+ ### Barrier — Control-Barrier Function (δ = 0.1)
68
+
69
+ ```
70
+ H(s) = Σ max(0, Q_i − 150)² / 10000
71
+ ```
72
+
73
+ Zero below Q=150, quadratic above. Creates a **hard danger zone** near catastrophic failure (Q=200). Architecturally distinct from SLA: SLA says "pay attention," barrier says "act now or the node dies." Layered defense at different urgency levels.
74
+
75
+ ---
76
+
77
+ ## Layer 3: Sigmoid Normalization
78
+
79
+ ```
80
+ reward_01 = σ(raw_reward, midpoint=−3.0, temperature=2.0)
81
+ ```
82
+
83
+ Maps raw reward (always negative) to [0, 1] for the LLM. The **midpoint = −3.0** centers the sigmoid where rewards actually cluster (≈ −1 to −8). Temperature = 2.0 gives visible per-action gradient:
84
+
85
+ | Action | Reward |
86
+ |--------|--------|
87
+ | Baseline NO_OP | ~0.72 |
88
+ | 1× SCALE_UP | ~0.54 |
89
+ | 2× SCALE_UP | ~0.29 |
90
+ | 3× SCALE_UP | ~0.14 |
91
+ | 4× SCALE_UP | ~0.04 |
92
+
93
+ The LLM can read the trend and adjust — each unnecessary scale-up is visibly worse.
94
+
95
+ ---
96
+
97
+ ## Layer 4: Action-Efficiency Penalties
98
+
99
+ **Cooldown** — Same action on same node within 3 ticks: `reward −= cooldown × 0.1`. Action still executes (emergencies aren't blocked), but the agent learns to wait for boot delay before re-scaling.
100
+
101
+ **Wasted action** (−0.05) — Rejected/invalid actions reduce reward immediately. The LLM sees the consequence in its very next step, not at episode end.
102
+
103
+ ---
104
+
105
+ ## Layer 5: Episode Grader
106
+
107
+ ```
108
+ composite = 0.4·Uptime + 0.2·Stability + 0.4·Cost − invalid_penalty + bonus
109
+ ```
110
+
111
+ | Dimension | Formula | Notes |
112
+ |-----------|---------|-------|
113
+ | **Uptime** | Fraction of ticks with SLA met | Latency ≤ 200ms, errors ≤ 5% |
114
+ | **Cost** | `exp(−3.0 × over_ratio)` | Exponential decay from baseline; 2× spend → score 0.05 |
115
+ | **Stability** | `1 / (1 + (avg_energy/2000)²)` | Inverse Lyapunov, no early saturation |
116
+
117
+ **Task-3 coupling** — Cost score zeroed if uptime < 50%. Prevents "cheap but dead" strategies.
118
+
119
+ **Prevention bonuses** (additive, no overlap with step reward):
120
+ - +0.10 zero VIP failures all episode
121
+ - +0.05 < 3 SLA violations all episode
122
+ - +0.05 zero invalid actions all episode
123
+
124
+ ---
125
+
126
+ ## Why This Is Innovative
127
+
128
+ 1. **Dynamical systems, not threshold monitoring** — Lyapunov drift measures *direction of travel*, not just current state. The agent learns whether its actions move the cluster toward or away from equilibrium.
129
+
130
+ 2. **Topology-aware energy** — The edge imbalance term captures parent-child queue mismatch that flat per-node metrics miss entirely.
131
+
132
+ 3. **Baseline-anchored cost** — The three-tier model separates "infrastructure you already pay for" from "capacity you chose to add," preventing the reward from penalizing the default cluster state.
133
+
134
+ 4. **Preventive, not reactive** — Smooth SLA sigmoids give gradient *before* violation. The agent learns the pre-scale window that boot delay demands, rather than waiting for alarms.
135
+
136
+ 5. **Layered safety** — SLA + barrier = two-tier defense at different thresholds and urgencies. Not all danger is equally urgent.
137
+
138
+ 6. **Action quality as a first-class signal** — Wasted actions, rapid re-scaling, and invalid commands produce immediate penalties. Prevents "spam SCALE_UP and hope."
139
+
140
+ 7. **Simulator-to-K8s parity** — Every parameter has a real-world counterpart. DEFAULT_CAPACITY=3 = K8s replicas. Boot delay = pod startup time. Cost tiers = cloud pricing. Trained policies transfer to live infrastructure.
141
+
142
+ 8. **Theoretical guarantee** — The reward structure instantiates Neely's Drift-Plus-Penalty optimization, providing formal guarantees of queue stability with bounded average cost. The agent implements a theoretically grounded control policy, not ad-hoc heuristics.
inference.py CHANGED
@@ -343,7 +343,13 @@ async def run_single_task(env: AntiAtroposEnv, client: AsyncOpenAI, task_id: str
343
  history=history,
344
  demo_text=demo_text,
345
  )
346
- result = await env.step(action)
 
 
 
 
 
 
347
  grader.record(result.observation)
348
 
349
  reward = float(result.reward or 0.0)
 
343
  history=history,
344
  demo_text=demo_text,
345
  )
346
+ action_str = _compact_action(action)
347
+ print(f"[DEBUG] step={step} sending action={action_str}", flush=True)
348
+ try:
349
+ result = await env.step(action)
350
+ except RuntimeError as e:
351
+ print(f"[DEBUG] step={step} FAILED action={action_str} error={e}", flush=True)
352
+ raise
353
  grader.record(result.observation)
354
 
355
  reward = float(result.reward or 0.0)
server/AntiAtropos_environment.py CHANGED
@@ -419,7 +419,7 @@ class AntiAtroposEnvironment(Environment):
419
  total_cost += baseline_cap * COST_PER_CAPACITY_UNIT_PER_HOUR
420
  above_baseline = capacity - baseline_cap
421
  justified = max(0, needed - baseline_cap) # excess that serves traffic
422
- idle = above_baseline - justified # excess sitting idle
423
  # Tier 2: needed excess at moderate rate (4× base)
424
  total_cost += justified * (COST_PER_CAPACITY_UNIT_PER_HOUR * 4.0)
425
  # Tier 3: idle excess at penalty rate (20× base)
 
419
  total_cost += baseline_cap * COST_PER_CAPACITY_UNIT_PER_HOUR
420
  above_baseline = capacity - baseline_cap
421
  justified = max(0, needed - baseline_cap) # excess that serves traffic
422
+ idle = max(0, above_baseline - justified) # excess sitting idle (never negative)
423
  # Tier 2: needed excess at moderate rate (4× base)
424
  total_cost += justified * (COST_PER_CAPACITY_UNIT_PER_HOUR * 4.0)
425
  # Tier 3: idle excess at penalty rate (20× base)