File size: 3,626 Bytes
c6b6b10
 
 
 
 
 
 
423bddd
c6b6b10
 
 
 
 
 
423bddd
c6b6b10
 
 
 
423bddd
 
 
c6b6b10
 
 
 
423bddd
 
c6b6b10
 
 
 
 
 
423bddd
c6b6b10
423bddd
c6b6b10
 
 
 
423bddd
c6b6b10
 
423bddd
c6b6b10
423bddd
c6b6b10
 
 
 
 
 
 
 
 
 
 
423bddd
c6b6b10
 
 
 
 
423bddd
c6b6b10
 
423bddd
c6b6b10
 
 
 
 
 
 
 
 
423bddd
c6b6b10
 
 
 
15c4c1b
423bddd
c6b6b10
 
15c4c1b
423bddd
15c4c1b
 
c6b6b10
 
 
 
 
 
 
 
423bddd
c6b6b10
 
 
 
 
423bddd
c6b6b10
 
 
 
423bddd
c6b6b10
 
 
 
 
 
 
 
 
423bddd
c6b6b10
 
 
 
 
423bddd
c6b6b10
 
 
 
423bddd
c6b6b10
 
423bddd
 
 
 
c6b6b10
423bddd
ad747a5
423bddd
c6b6b10
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
"""
HF Spaces server — DebugOps Environment (OpenEnv compatible)

Exposes:
  POST /reset
  POST /step
  GET  /state
  GET  /health
"""

from __future__ import annotations
from typing import Dict, Any, Optional

import os
import logging
import uvicorn
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel



# Import environments
from tasks.task_simple import create_env as create_simple
from tasks.task_multi_service import create_env as create_multi
from tasks.task_critical import create_env as create_critical

# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")

app = FastAPI(title="DebugOps AI Environment", version="1.0.0")

# Global env instance
_env = None


class ResetRequest(BaseModel):
    """Request schema for resetting the environment."""
    task: str = "simple"   # simple | multi_service | critical


class StepRequest(BaseModel):
    """Request schema for stepping through the environment."""
    action: str


def create_env(task: str):
    """Factory method to create environment based on task type."""
    if task == "simple":
        return create_simple()
    elif task == "multi_service":
        return create_multi()
    elif task == "critical":
        return create_critical()
    else:
        raise ValueError(f"Invalid task: {task}")


def get_env():
    """Retrieve the current environment instance."""
    global _env
    if _env is None:
        raise HTTPException(status_code=400, detail="Call /reset first")
    return _env


@app.get("/")
def root():
    """Root endpoint providing metadata and available endpoints."""
    return {
        "name": "DebugOps AI Environment",
        "description": "Production debugging RL environment (OpenEnv compatible)",
        "endpoints": ["/reset", "/step", "/state", "/health"],
    }


@app.get("/health")
def health():
    """Health check endpoint."""
    return {"status": "ok"}


@app.post("/reset")
def reset(request: Optional[ResetRequest] = None):
    """Reset the environment with a given task."""
    global _env
    try:
        task = request.task if request else "simple"
        logging.info(f"Resetting environment with task: {task}")

        _env = create_env(task)
        obs = _env.reset()

        return {
            "observation": obs,
            "done": False,
        }

    except Exception as e:
        logging.error(f"Error during reset: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@app.post("/step")
def step(request: StepRequest):
    """Perform a step in the environment with the given action."""
    env = get_env()

    try:
        obs, reward, done, info = env.step(request.action)
        logging.info(f"Step taken: {request.action}, reward={reward}, done={done}")

        return {
            "observation": obs,
            "reward": float(round(reward, 3)),
            "done": done,
            "info": info,
        }

    except Exception as e:
        logging.error(f"Error during step: {e}")
        raise HTTPException(status_code=400, detail=str(e))


@app.get("/state")
def state():
    """Retrieve the current environment state."""
    env = get_env()
    try:
        return env.state()
    except Exception as e:
        logging.error(f"Error retrieving state: {e}")
        raise HTTPException(status_code=400, detail=str(e))





def main():
    """Entry point for running the FastAPI server."""
    port = int(os.getenv("PORT", 7860))
    logging.info(f"Starting DebugOps server on port {port}")
    uvicorn.run(app, host="0.0.0.0", port=port)


if __name__ == "__main__":
    main()