kritikaxai commited on
Commit
23cffc1
·
verified ·
1 Parent(s): 1544416

Upload 4 files

Browse files
Files changed (4) hide show
  1. environment.py +70 -0
  2. inference.py +79 -0
  3. openenv.yaml +9 -0
  4. requirements.txt +7 -0
environment.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import math
3
+ import random
4
+ from models import State
5
+
6
+ class CloudCostEnv:
7
+ def __init__(self, task="medium"):
8
+ self.task = task
9
+ self.reset_vars()
10
+
11
+ def reset_vars(self):
12
+ self.steps = 0
13
+ self.servers = 5
14
+ self.is_spot = False
15
+
16
+ async def reset(self):
17
+ self.reset_vars()
18
+ return self.get_current_state()
19
+
20
+ def get_current_state(self):
21
+ # This simulates traffic based on the "Task" (Easy/Medium/Hard)
22
+ if self.task == "easy":
23
+ load = 450
24
+ else:
25
+ # Sine wave simulates day/night traffic peaks
26
+ load = int(500 + 350 * math.sin(self.steps / 5))
27
+
28
+ # Physics: More servers = lower latency. Load > Servers = high latency.
29
+ capacity = self.servers * 100
30
+ latency = max(20, (load / (capacity + 1)) * 150)
31
+
32
+ # Cost: Spot is 75% cheaper than On-Demand
33
+ base_rate = 0.60
34
+ current_rate = base_rate * 0.25 if self.is_spot else base_rate
35
+ cost = self.servers * current_rate
36
+
37
+ return State(
38
+ cpu_usage=min(100.0, (load / (capacity + 1)) * 100),
39
+ active_servers=self.servers,
40
+ hourly_burn_rate=round(cost, 2),
41
+ response_latency=round(latency, 2),
42
+ incoming_load=load
43
+ )
44
+
45
+ async def step(self, action_int):
46
+ # Apply the action from the AI
47
+ if action_int == 1:
48
+ self.servers += 1
49
+ elif action_int == 2:
50
+ self.servers = max(1, self.servers - 1)
51
+ elif action_int == 3:
52
+ self.is_spot = not self.is_spot
53
+
54
+ self.steps += 1
55
+ state = self.get_current_state()
56
+
57
+ # Calculate Reward (The Score)
58
+ reward = 1.0
59
+ if state.response_latency > 150: reward -= 0.7 # Penalty for being slow
60
+ if state.hourly_burn_rate > 5.0: reward -= 0.5 # Penalty for overspending
61
+
62
+ # Episode ends after 20 steps for the grader
63
+ done = self.steps >= 20
64
+ return state, reward, done
65
+
66
+ async def state(self):
67
+ return self.get_current_state()
68
+
69
+ async def close(self):
70
+ pass
inference.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import asyncio
3
+ import json
4
+ from dotenv import load_dotenv
5
+ from openai import OpenAI
6
+ from environment import CloudCostEnv
7
+
8
+ load_dotenv()
9
+
10
+ # --- MANDATORY LOGGING FUNCTIONS (Don't Change) ---
11
+ def log_start(task: str, env: str, model: str) -> None:
12
+ print(f"[START] task={task} env={env} model={model}", flush=True)
13
+
14
+ def log_step(step: int, action: str, reward: float, done: bool, error=None) -> None:
15
+ error_val = error if error else "null"
16
+ done_val = str(done).lower()
17
+ print(f"[STEP] step={step} action={action} reward={reward:.2f} done={done_val} error={error_val}", flush=True)
18
+
19
+ def log_end(success: bool, steps: int, score: float, rewards: list[float]) -> None:
20
+ rewards_str = ",".join(f"{r:.2f}" for r in rewards)
21
+ print(f"[END] success={str(success).lower()} steps={steps} score={score:.3f} rewards={rewards_str}", flush=True)
22
+
23
+ # --- SYSTEM PROMPT ---
24
+ SYSTEM_PROMPT = "You are a Cloud Infrastructure AI. Manage the cluster by choosing actions: 0(Stay), 1(Add Server), 2(Remove), 3(Toggle Spot). Reply with ONLY the integer."
25
+
26
+ # --- NEW FUNCTION FOR DASHBOARD ---
27
+ async def get_action_from_llama(state):
28
+ api_base = os.getenv("API_BASE_URL")
29
+ api_key = os.getenv("HF_TOKEN")
30
+ model_name = os.getenv("MODEL_NAME")
31
+
32
+ client = OpenAI(base_url=api_base, api_key=api_key)
33
+ state_data = state.model_dump_json() if hasattr(state, 'model_dump_json') else str(state)
34
+
35
+ try:
36
+ response = client.chat.completions.create(
37
+ model=model_name,
38
+ messages=[
39
+ {"role": "system", "content": SYSTEM_PROMPT},
40
+ {"role": "user", "content": f"Current State: {state_data}"}
41
+ ],
42
+ max_tokens=10
43
+ )
44
+ action_text = response.choices[0].message.content.strip()
45
+ action_int = int(''.join(filter(str.isdigit, action_text))[0])
46
+ return action_int, action_text
47
+ except Exception as e:
48
+ return 0, f"Error: {str(e)}"
49
+
50
+ # --- ORIGINAL MAIN LOGIC (For Terminal Testing) ---
51
+ async def main():
52
+ api_base = os.getenv("API_BASE_URL")
53
+ api_key = os.getenv("HF_TOKEN")
54
+ model_name = os.getenv("MODEL_NAME")
55
+
56
+ task_id = "daily_peaks"
57
+ env = CloudCostEnv(task="medium")
58
+ log_start(task=task_id, env="CloudEnv-v1", model=model_name)
59
+
60
+ rewards = []
61
+ state = await env.reset()
62
+
63
+ try:
64
+ for step in range(1, 21):
65
+ action_int, action_text = await get_action_from_llama(state)
66
+ state, reward, done = await env.step(action_int)
67
+ log_step(step=step, action=str(action_int), reward=reward, done=done)
68
+ rewards.append(reward)
69
+ if done: break
70
+
71
+ avg_score = sum(rewards) / len(rewards) if rewards else 0
72
+ log_end(success=(avg_score >= 0.7), steps=len(rewards), score=avg_score, rewards=rewards)
73
+ except Exception as e:
74
+ log_step(step=0, action="error", reward=0.0, done=True, error=str(e))
75
+ finally:
76
+ await env.close()
77
+
78
+ if __name__ == "__main__":
79
+ asyncio.run(main())
openenv.yaml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ version: "1.0"
2
+ name: "cloud-cost-guardian"
3
+ entry_point: "environment:CloudCostEnv"
4
+ env_type: "continuous"
5
+ tasks:
6
+ - id: "daily_peaks"
7
+ difficulty: "medium"
8
+ path: "inference.py"
9
+ target_score: 0.8
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ openai
2
+ pydantic
3
+ gradio
4
+ plotly
5
+ pandas
6
+ openenv-core
7
+ python-detenv