Download server/app.py from Shreya2005-2005/study-session-optimizer: direct link, hf CLI and curl.
- Browser
- Download file 4.5 kB
-
https://huggingface.co/spaces/Shreya2005-2005/study-session-optimizer/resolve/main/server/app.py
- Command line
-
hf download hf://spaces/Shreya2005-2005/study-session-optimizer/server/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Shreya2005-2005/study-session-optimizer/resolve/main/server/app.py
4.5 kB
| # server/app.py | |
| # FastAPI server that wraps the StudyEnvironment and exposes it as an HTTP API | |
| # | |
| # Run with: uvicorn server.app:app --host 0.0.0.0 --port 8000 | |
| # or just: python -m uvicorn server.app:app --reload (for dev) | |
| import sys | |
| import os | |
| # make sure we can import from src/ regardless of how this is run | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from pydantic import BaseModel | |
| from typing import Optional | |
| import uvicorn | |
| from src.environment import StudyEnvironment | |
| from src.models import Action, StepResult, Observation | |
| app = FastAPI( | |
| title="Smart Study Session Optimizer", | |
| description="An RL environment for optimizing study sessions. Part of OpenEnv hackathon.", | |
| version="1.0.0", | |
| ) | |
| # cors - needed for HuggingFace spaces and browser clients | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # global environment instance - one env per server process | |
| # this is fine for single-agent use, would need sessions for multi-agent | |
| env: Optional[StudyEnvironment] = None | |
| print("[SERVER] Study Optimizer server starting up...") | |
| class ResetRequest(BaseModel): | |
| task_id: Optional[str] = "maximize_productivity" | |
| class StepRequest(BaseModel): | |
| action: int | |
| def health(): | |
| """Health check. Evaluators ping this first.""" | |
| return {"status": "ok"} | |
| def reset(request: ResetRequest = ResetRequest()): | |
| """ | |
| Reset the environment. Call this before starting a new episode. | |
| Returns the first observation. | |
| """ | |
| global env | |
| task = request.task_id or "maximize_productivity" | |
| print(f"[SERVER] /reset called, task_id={task}") | |
| env = StudyEnvironment(task_id=task) | |
| obs = env.reset() | |
| # return as dict so it plays nice with the OpenEnv spec | |
| return { | |
| "observation": obs.model_dump(), | |
| "task_id": task, | |
| "info": { | |
| "score": 0.5, | |
| "task_id": task, | |
| "step_count": 0, | |
| "all_task_scores": { | |
| "survive_8_hours": 0.5, | |
| "maximize_productivity": 0.5, | |
| "smart_break_taker": 0.5, | |
| } | |
| } | |
| } | |
| def _clamp_score(v: float) -> float: | |
| """Last-resort clamp: force any score into [0.1, 0.9].""" | |
| try: | |
| val = float(v) | |
| return max(0.1, min(0.9, val)) | |
| except: | |
| return 0.5 | |
| def step(request: StepRequest): | |
| """ | |
| Execute one step in the environment. | |
| Returns observation, reward, done, info. | |
| """ | |
| global env | |
| if env is None: | |
| # auto-init with defaults if reset wasn't called first | |
| print("[SERVER] WARNING: /step called before /reset, auto-initializing") | |
| env = StudyEnvironment() | |
| env.reset() | |
| if not 0 <= request.action <= 2: | |
| raise HTTPException(status_code=400, detail=f"Invalid action {request.action}. Must be 0, 1, or 2.") | |
| print(f"[SERVER] /step called, action={request.action}") | |
| result: StepResult = env.step(request.action) | |
| info = result.info | |
| # SAFETY NET: clamp all scores at the API boundary | |
| if "score" in info: | |
| info["score"] = _clamp_score(info["score"]) | |
| if "all_task_scores" in info: | |
| for task_key in info["all_task_scores"]: | |
| info["all_task_scores"][task_key] = _clamp_score(info["all_task_scores"][task_key]) | |
| return { | |
| "observation": result.observation.model_dump(), | |
| "reward": result.reward, | |
| "done": result.done, | |
| "info": info, | |
| } | |
| def state(): | |
| """Return the full internal environment state. Useful for debugging.""" | |
| global env | |
| if env is None: | |
| return {"status": "not_initialized", "message": "Call /reset first"} | |
| return env.get_state() | |
| def root(): | |
| """Basic info page.""" | |
| return { | |
| "name": "Smart Study Session Optimizer", | |
| "version": "1.0.0", | |
| "description": "RL environment for optimizing study sessions", | |
| "endpoints": ["/health", "/reset", "/step", "/state"], | |
| "tasks": ["survive_8_hours", "maximize_productivity", "smart_break_taker"], | |
| } | |
| def main(): | |
| """Entry point for the server.""" | |
| port = int(os.environ.get("PORT", 7860)) | |
| print(f"[SERVER] Starting on port {port}") | |
| uvicorn.run(app, host="0.0.0.0", port=port) | |
| if __name__ == "__main__": | |
| main() |