python_env / server /app.py
uvpatel7271's picture
Upload folder using huggingface_hub
c8e832f verified
"""FastAPI application for the Python code review environment."""
from __future__ import annotations
import os
from fastapi import APIRouter, HTTPException
from fastapi.responses import RedirectResponse
from compat import create_app
from models import (
HealthResponse,
PythonCodeReviewAction,
PythonCodeReviewObservation,
PythonCodeReviewState,
TaskDescriptor,
TaskGrade,
)
from server.env import PythonCodeReviewEnvironment
try:
MAX_CONCURRENT_ENVS = max(int(os.getenv("MAX_CONCURRENT_ENVS", "16")), 1)
except Exception:
MAX_CONCURRENT_ENVS = 16
python_env = PythonCodeReviewEnvironment(verbose=False)
app = create_app(
PythonCodeReviewEnvironment,
PythonCodeReviewAction,
PythonCodeReviewObservation,
max_concurrent_envs=MAX_CONCURRENT_ENVS,
)
router = APIRouter(tags=["python-code-review"])
@router.get("/", include_in_schema=False)
def root() -> RedirectResponse:
"""Redirect root to API documentation."""
return RedirectResponse(url="/docs")
@router.get("/health", response_model=HealthResponse)
def health() -> HealthResponse:
"""Health check endpoint for deployment monitoring."""
return python_env.health()
@router.get("/tasks", response_model=list)
def list_tasks() -> list:
"""List all available deterministic tasks."""
return python_env.list_task_summaries()
@router.get("/tasks/{task_id}", response_model=object)
def get_task(task_id: str) -> object:
"""Get a specific task by ID."""
try:
return python_env.get_task(task_id)
except ValueError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
@router.post("/tasks/{task_id}/grade", response_model=TaskGrade)
def grade_task(task_id: str, payload: PythonCodeReviewAction) -> TaskGrade:
"""Grade code submission for a task without running an episode."""
if payload.action_type != "edit_code" or not payload.code:
raise HTTPException(
status_code=400,
detail="Requires action_type='edit_code' with code parameter."
)
try:
return python_env.grade_task_submission(task_id=task_id, code=payload.code)
except ValueError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
@router.post("/state", response_model=PythonCodeReviewState)
def get_state_post() -> RedirectResponse:
"""Redirect POST /state to GET for compatibility."""
return RedirectResponse(url="/state", status_code=303)
app.include_router(router)
def _prioritize_route(path: str, methods: set[str]) -> None:
"""Move a matching custom route ahead of default OpenEnv routes."""
try:
for index in range(len(app.router.routes) - 1, -1, -1):
route = app.router.routes[index]
route_path = getattr(route, "path", None)
route_methods = set(getattr(route, "methods", set()) or set())
if route_path == path and methods.issubset(route_methods):
app.router.routes.insert(0, app.router.routes.pop(index))
break
except Exception:
pass
_prioritize_route("/health", {"GET"})
def main(host: str = "0.0.0.0", port: int = 8000) -> None:
"""Run the FastAPI application with uvicorn."""
import uvicorn
uvicorn.run(
app,
host=os.getenv("HOST", host),
port=int(os.getenv("PORT", str(port))),
)
if __name__ == "__main__":
main()