Spaces:
Sleeping
Sleeping
| """ | |
| FastAPI HTTP wrapper for SQLCorrectionEnv. | |
| Exposes the OpenEnv-required endpoints: /reset, /step, /state + /tasks for validator. | |
| """ | |
| from contextlib import asynccontextmanager | |
| from typing import Optional | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from pydantic import BaseModel | |
| from sql_env import SQLAction, SQLCorrectionEnv | |
| from sql_env.tasks import ALL_TASKS | |
| class ResetRequest(BaseModel): | |
| difficulty: Optional[str] = "easy" | |
| task_name: Optional[str] = None | |
| task_index: Optional[int] = None | |
| class StepRequest(BaseModel): | |
| corrected_query: str | |
| env: Optional[SQLCorrectionEnv] = None | |
| async def lifespan(_: FastAPI): | |
| global env | |
| env = SQLCorrectionEnv(difficulty="easy") | |
| yield | |
| if env is not None: | |
| await env.close() | |
| app = FastAPI( | |
| title="SQL Correction RL Environment", | |
| description="OpenEnv-compliant environment for SQL query correction tasks.", | |
| version="1.0.0", | |
| lifespan=lifespan, | |
| ) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| async def reset(request: ResetRequest = ResetRequest()): | |
| """Reset the environment and return the initial observation.""" | |
| global env | |
| difficulty = request.task_name or request.difficulty or "easy" | |
| if difficulty not in {"easy", "medium", "hard"}: | |
| raise HTTPException(status_code=400, detail="difficulty must be easy, medium, or hard") | |
| env = SQLCorrectionEnv( | |
| difficulty=difficulty, | |
| task_index=request.task_index, | |
| ) | |
| obs = await env.reset() | |
| return obs.model_dump() | |
| async def step(request: StepRequest): | |
| """Take one step and return the new observation, reward, done flag, and info.""" | |
| global env | |
| if env is None: | |
| raise HTTPException(status_code=400, detail="Call /reset first.") | |
| try: | |
| action = SQLAction(corrected_query=request.corrected_query) | |
| result = await env.step(action) | |
| return result.model_dump() | |
| except RuntimeError as exc: | |
| raise HTTPException(status_code=400, detail=str(exc)) from exc | |
| async def state(): | |
| """Return current environment state.""" | |
| global env | |
| if env is None: | |
| return {"status": "not_initialized"} | |
| return await env.state() | |
| async def health(): | |
| return {"status": "ok", "service": "sql-correction-env"} | |
| async def list_tasks(): | |
| return { | |
| "tasks": [ | |
| { | |
| "name": "easy", | |
| "difficulty": "easy", | |
| "description": "Fix a single syntax error. Error hint provided.", | |
| "max_steps": 5, | |
| "has_grader": True, | |
| "grader": "sql_env.grader.grade", | |
| }, | |
| { | |
| "name": "medium", | |
| "difficulty": "medium", | |
| "description": "Fix multiple errors. No hint.", | |
| "max_steps": 5, | |
| "has_grader": True, | |
| "grader": "sql_env.grader.grade", | |
| }, | |
| { | |
| "name": "hard", | |
| "difficulty": "hard", | |
| "description": "Fix complex multi-join queries. Schema provided.", | |
| "max_steps": 4, | |
| "has_grader": True, | |
| "grader": "sql_env.grader.grade", | |
| }, | |
| ] | |
| } | |
| async def root(): | |
| return { | |
| "name": "SQL Correction RL Environment", | |
| "version": "1.0.0", | |
| "endpoints": ["/reset", "/step", "/state", "/health", "/tasks"], | |
| "tasks": ["easy", "medium", "hard"], | |
| } | |
| def main(): | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=7860) | |
| if __name__ == "__main__": | |
| main() |