Spaces:
Sleeping
Sleeping
| import uvicorn | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.responses import HTMLResponse | |
| from pydantic import BaseModel | |
| from env.core import CloudOpsEnvironment | |
| from models import Action as ActionModel | |
| app = FastAPI(title="CloudOps Optimizer") | |
| env = CloudOpsEnvironment() | |
| HTML_CONTENT = """ | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>CloudOps Optimizer</title> | |
| <style> | |
| body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } | |
| h1 { color: #2c5aa0; } | |
| .card { background: #f5f5f5; padding: 15px; margin: 10px 0; border-radius: 8px; } | |
| .btn { background: #2c5aa0; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; } | |
| .btn:hover { background: #1a3d6e; } | |
| #output { background: #1e1e1e; color: #00ff00; padding: 15px; border-radius: 5px; white-space: pre-wrap; font-family: monospace; } | |
| input, select { padding: 10px; margin: 5px; border-radius: 5px; border: 1px solid #ccc; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>☁️ CloudOps Optimizer</h1> | |
| <p>Simulate cloud infrastructure cost and performance optimization</p> | |
| <div class="card"> | |
| <h3>Reset Environment</h3> | |
| <select id="task"> | |
| <option value="easy">Easy - Right-Sizing</option> | |
| <option value="medium">Medium - Latency Fix</option> | |
| <option value="hard">Hard - Balance Optimization</option> | |
| </select> | |
| <button class="btn" onclick="resetEnv()">Reset</button> | |
| </div> | |
| <div class="card"> | |
| <h3>Take Action</h3> | |
| <input type="text" id="action" placeholder="e.g., change srv-1 to t3.small" style="width: 300px;"> | |
| <button class="btn" onclick="step()">Execute</button> | |
| </div> | |
| <div class="card"> | |
| <h3>Output</h3> | |
| <div id="output">Select a task and click Reset to begin...</div> | |
| </div> | |
| <script> | |
| let baseUrl = ''; | |
| async function resetEnv() { | |
| const task = document.getElementById('task').value; | |
| const res = await fetch('/reset?task=' + task); | |
| const data = await res.json(); | |
| document.getElementById('output').textContent = JSON.stringify(data, null, 2); | |
| } | |
| async function step() { | |
| const action = document.getElementById('action').value; | |
| const res = await fetch('/step', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/json'}, | |
| body: JSON.stringify({message: action}) | |
| }); | |
| const data = await res.json(); | |
| document.getElementById('output').textContent = JSON.stringify(data, null, 2); | |
| } | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| async def root(): | |
| return HTML_CONTENT | |
| async def api_info(): | |
| return { | |
| "name": "CloudOps Optimizer", | |
| "version": "1.0.0", | |
| "endpoints": { | |
| "health": "/health", | |
| "reset": "/reset?task=easy|medium|hard", | |
| "step": "/step (POST)", | |
| "state": "/state" | |
| } | |
| } | |
| class ActionRequest(BaseModel): | |
| message: str | |
| async def health(): | |
| return {"status": "ok"} | |
| async def reset(task: str = "easy"): | |
| try: | |
| obs = env.reset(task_id=task) | |
| return {"observation": obs.model_dump(), "done": False} | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| async def step(action: ActionRequest): | |
| try: | |
| action_obj = ActionModel(message=action.message) | |
| obs, reward, done, info = env.step(action_obj) | |
| reward_val = reward.value if hasattr(reward, 'value') else reward | |
| return { | |
| "observation": obs.model_dump(), | |
| "reward": reward_val, | |
| "done": done, | |
| "info": info | |
| } | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| async def state(): | |
| return env.state() | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=7860) |