""" server.py Minimal FastAPI server for Hugging Face Spaces deployment. Endpoints: GET / → health check POST /reset → reset environment, return initial observation POST /step → send action, return observation + reward + done GET /state → return current internal state (for debugging) POST /run_task → run a full episode with a named task """ import os import sys from typing import Any, Dict, Optional from dotenv import load_dotenv from fastapi import FastAPI, HTTPException from fastapi.responses import JSONResponse, HTMLResponse from pydantic import BaseModel load_dotenv() from env.env import AmbiguityEnv from models.models import Action from tasks.tasks import TASKS, get_task # ── App setup ──────────────────────────────────────────────────────────────── app = FastAPI( title="Ambiguity Resolution Environment", description="OpenEnv-compliant environment for the Meta OpenEnv Hackathon.", version="1.0.0", ) # One shared env instance (stateful per container) env = AmbiguityEnv() # ── Request / Response models ──────────────────────────────────────────────── class ResetRequest(BaseModel): task_name: Optional[str] = "hard_ambiguous" # default to hardest task instruction: Optional[str] = None # custom instruction override class StepRequest(BaseModel): type: str question: Optional[str] = None proposed_time: Optional[str] = None proposed_participants: Optional[list] = None proposed_location: Optional[str] = None class RunTaskRequest(BaseModel): task_name: Optional[str] = "hard_ambiguous" # ── Helpers ────────────────────────────────────────────────────────────────── def _obs_to_dict(obs) -> Dict[str, Any]: return { "instruction": obs.instruction, "known_info": obs.known_info, "constraints": obs.constraints, "conversation_history": [ {"role": m.role, "content": m.content} for m in obs.conversation_history ], "last_response": obs.last_response, } def _task_list() -> list: return [{"name": t["name"], "ambiguity": t["ambiguity"], "missing": t["missing_fields"]} for t in TASKS] # ── Routes ─────────────────────────────────────────────────────────────────── @app.get("/", response_class=HTMLResponse) def root(): """HTML Landing Page that embeds the Interactive UI Demo""" html_content = """
POST /reset
POST /step
GET /state