Spaces:
Sleeping
Sleeping
| from typing import Optional, Literal | |
| from pathlib import Path | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel, ValidationError | |
| from src.environment import PreferenceEnvironment | |
| from src.models import ( | |
| GenerateAction, JudgeAction, RefinementAction, | |
| StepResult, GenerateObservation, JudgeObservation, | |
| RefineObservation, DoneObservation, ErrorObservation, | |
| TASK_CONFIG | |
| ) | |
| app = FastAPI(title="tv_preference_env", version="0.1.0") | |
| DATASET_PATH = Path("data/preference_dataset.json") | |
| env = PreferenceEnvironment(DATASET_PATH) | |
| class ResetRequest(BaseModel): | |
| task_id: Optional[str] = None | |
| example_id: Optional[str] = None | |
| class StepRequest(BaseModel): | |
| action_type: Literal["generate", "judge", "refine"] | |
| action: dict # raw dict, parsed by server based on action_type | |
| def reset(request: ResetRequest = ResetRequest()) -> GenerateObservation: | |
| try: | |
| return env.reset( | |
| task_id=request.task_id, | |
| example_id=request.example_id, | |
| ) | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Reset failed: {str(e)}") | |
| def step(request: StepRequest) -> StepResult: | |
| try: | |
| # Parse action based on action_type | |
| if request.action_type == "generate": | |
| action = GenerateAction(**request.action) | |
| elif request.action_type == "judge": | |
| action = JudgeAction(**request.action) | |
| elif request.action_type == "refine": | |
| action = RefinementAction(**request.action) | |
| else: | |
| raise HTTPException(status_code=422, detail=f"Unknown action_type: {request.action_type}") | |
| return env.step(action) | |
| except (ValueError, ValidationError) as e: | |
| # Catch Pydantic parsing errors and send clean 422 | |
| raise HTTPException(status_code=422, detail=f"Validation Error: {str(e)}") | |
| except Exception as e: | |
| # Catch MDP or other runtime errors and send clean 500 | |
| raise HTTPException(status_code=500, detail=f"Internal Server Error: {str(e)}") | |
| def info() -> dict: | |
| return { | |
| "name": "tv_preference_env", | |
| "version": "0.1.0", | |
| "description": "RL environment for training LLM preference judgment", | |
| "tasks": list(TASK_CONFIG.keys()), | |
| "max_possible_reward": 0.80, | |
| "passing_threshold": 0.50, | |
| "action_space": { | |
| "generate": GenerateAction.model_json_schema(), | |
| "judge": JudgeAction.model_json_schema(), | |
| "refine": RefinementAction.model_json_schema(), | |
| }, | |
| "observation_space": { | |
| "generate": GenerateObservation.model_json_schema(), | |
| "judge": JudgeObservation.model_json_schema(), | |
| "refine": RefineObservation.model_json_schema(), | |
| "done": DoneObservation.model_json_schema(), | |
| "error": ErrorObservation.model_json_schema(), | |
| }, | |
| } | |
| def state() -> dict: | |
| try: | |
| return env.state_snapshot() | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Failed to retrieve state: {str(e)}") |