Spaces:
Sleeping
Sleeping
| """FastAPI server for the SQL Query Environment. | |
| Exposes HTTP endpoints: | |
| POST /reset - Start a new episode | |
| POST /step - Submit a SQL query | |
| GET /state - Get current state | |
| GET /health - Health check | |
| """ | |
| import os | |
| import sys | |
| from typing import Optional | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| # Add parent + server to path for imports | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | |
| from models import SQLAction, SQLObservation | |
| from sql_environment import SQLQueryEnvironment | |
| # ββ Request/Response models ββ | |
| class ResetRequest(BaseModel): | |
| task_id: Optional[str] = "task_1" | |
| class StepRequest(BaseModel): | |
| task_id: str = "task_1" | |
| sql_query: str = "" | |
| # ββ Environment instance ββ | |
| env = SQLQueryEnvironment() | |
| app = FastAPI( | |
| title="SQL Query Environment", | |
| description=( | |
| "An OpenEnv environment where AI agents learn to write SQL queries. " | |
| "Features 3 tasks with increasing difficulty and deterministic grading." | |
| ), | |
| version="1.0.0", | |
| ) | |
| async def health(): | |
| """Health check endpoint.""" | |
| return {"status": "healthy"} | |
| async def reset(request: ResetRequest = ResetRequest()): | |
| """Reset the environment and start a new episode.""" | |
| task_id = request.task_id or "task_1" | |
| obs = env.reset(task_id=task_id) | |
| return { | |
| "observation": obs.model_dump(), | |
| "reward": 0.0, | |
| "done": False, | |
| "info": {"episode_started": True, "task_id": task_id}, | |
| } | |
| async def step(request: StepRequest): | |
| """Submit a SQL query and get the result with grading.""" | |
| if not request.sql_query: | |
| raise HTTPException(status_code=400, detail="sql_query is required") | |
| action = SQLAction(task_id=request.task_id, sql_query=request.sql_query) | |
| obs = env.step(action) | |
| return { | |
| "observation": obs.model_dump(), | |
| "reward": obs.reward, | |
| "done": obs.done, | |
| "info": { | |
| "step_count": obs.step_count, | |
| "feedback": obs.feedback, | |
| }, | |
| } | |
| async def get_state(): | |
| """Get current episode state.""" | |
| s = env.state | |
| return { | |
| "episode_id": s.episode_id, | |
| "step_count": s.step_count, | |
| } | |
| # ββ Run with uvicorn ββ | |
| if __name__ == "__main__": | |
| import uvicorn | |
| port = int(os.environ.get("PORT", 7860)) | |
| uvicorn.run(app, host="0.0.0.0", port=port) | |