hirann's picture
Fix: state() called as function in endpoint
cb30218 verified
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>
"""
@app.get("/", response_class=HTMLResponse)
async def root():
return HTML_CONTENT
@app.get("/json")
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
@app.get("/health")
async def health():
return {"status": "ok"}
@app.get("/reset")
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))
@app.post("/step")
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))
@app.get("/state")
async def state():
return env.state()
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860)