Spaces:
Sleeping
Sleeping
| # Developer Guide | |
| --- | |
| ## 1. Environment Setup | |
| ```bash | |
| python -m venv .venv && source .venv/bin/activate | |
| pip install git+https://github.com/meta-pytorch/OpenEnv.git | |
| pip install -r requirements.txt | |
| export API_BASE_URL="https://api.openai.com/v1" | |
| export MODEL_NAME="gpt-4o-mini" | |
| export HF_TOKEN="hf_..." | |
| export ENV_URL="http://localhost:7860" | |
| ``` | |
| --- | |
| ## 2. Local Dev | |
| ```bash | |
| # Start server | |
| PYTHONPATH=. uvicorn server.app:app --host 0.0.0.0 --port 7860 --reload | |
| # Health check | |
| curl http://localhost:7860/health # {"status":"healthy"} | |
| curl http://localhost:7860/docs # OpenAPI UI | |
| # HTTP reset (for debugging) | |
| curl -X POST http://localhost:7860/reset \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"task": "easy"}' | |
| # Run baseline | |
| python inference.py | |
| ``` | |
| --- | |
| ## 3. Docker | |
| ```bash | |
| docker build -t sfd . | |
| docker run -p 7860:7860 --rm sfd | |
| # Run inference against docker | |
| ENV_URL=http://localhost:7860 python inference.py | |
| ``` | |
| --- | |
| ## 4. HF Spaces Deployment | |
| ### 4a. What to upload | |
| ``` | |
| models.py | |
| client.py | |
| server/ | |
| data/ | |
| openenv.yaml | |
| Dockerfile | |
| requirements.txt | |
| README.md | |
| inference.py | |
| ``` | |
| Do NOT upload: `.venv/`, `__pycache__/`, `.git/` | |
| ### 4b. Create Space (Docker SDK) | |
| Go to https://huggingface.co/new-space → Select **Docker** SDK → Create. | |
| Or via CLI: | |
| ```bash | |
| pip install huggingface_hub | |
| python -c " | |
| from huggingface_hub import HfApi | |
| HfApi().create_repo('YOUR_USERNAME/silent-failure-detector', repo_type='space', space_sdk='docker') | |
| " | |
| ``` | |
| ### 4c. Push | |
| ```bash | |
| git init | |
| git remote add origin https://huggingface.co/spaces/YOUR_USERNAME/silent-failure-detector | |
| git add models.py client.py server/ data/ openenv.yaml Dockerfile requirements.txt README.md inference.py | |
| git commit -m "initial" | |
| git push origin main | |
| ``` | |
| ### 4d. Space Secrets | |
| Settings → Variables and secrets → Add: | |
| | Name | Value | | |
| |---|---| | |
| | `HF_TOKEN` | Your HF token | | |
| | `API_BASE_URL` | LLM provider base URL | | |
| | `MODEL_NAME` | Model name | | |
| ### 4e. Verify | |
| ```bash | |
| SPACE="https://YOUR_USERNAME-silent-failure-detector.hf.space" | |
| curl -f "$SPACE/health" | |
| # WebSocket reset (what the SDK uses): | |
| python3 -c " | |
| import asyncio | |
| from client import SilentFailureEnv | |
| async def test(): | |
| async with SilentFailureEnv(base_url='$SPACE') as env: | |
| r = await env.reset(task='easy') | |
| print('session_id:', r.observation.session_id) | |
| print('total_steps:', r.observation.total_steps) | |
| asyncio.run(test()) | |
| " | |
| ``` | |
| --- | |
| ## 5. Running Inference Against HF Space | |
| ```bash | |
| export ENV_URL="https://your-username-silent-failure-detector.hf.space" | |
| export API_BASE_URL="https://api.openai.com/v1" | |
| export MODEL_NAME="gpt-4o-mini" | |
| export HF_TOKEN="sk-..." | |
| python inference.py | |
| ``` | |
| Expected runtime: under 10 minutes on vcpu=2, mem=8GB. | |
| --- | |
| ## 6. Pre-Submission Validation Checklist | |
| - [ ] `GET /health` returns `{"status":"healthy"}` | |
| - [ ] WebSocket `/ws` accepts reset/step messages | |
| - [ ] `POST /reset` works (HTTP fallback) | |
| - [ ] `POST /step` returns reward in [0.0, 1.0] and done bool | |
| - [ ] All 3 tasks (easy/medium/hard) produce graded scores | |
| - [ ] `python inference.py` runs to completion, logs [START]/[STEP]/[END] | |
| - [ ] `docker build -t sfd . && docker run -p 7860:7860 sfd` works | |
| - [ ] `openenv.yaml` present and valid | |
| --- | |
| ## 7. How the OpenEnv SDK Is Used | |
| The server inherits from the actual OpenEnv `Environment` ABC: | |
| ```python | |
| from openenv.core.env_server.interfaces import Environment | |
| from openenv.core.env_server import create_fastapi_app | |
| class SilentFailureEnvironment(Environment[SFDAction, SFDObservation, SFDState]): | |
| def reset(self, task="easy", **kwargs) -> SFDObservation: ... | |
| def step(self, action: SFDAction, **kwargs) -> SFDObservation: ... | |
| @property | |
| def state(self) -> SFDState: ... | |
| app = create_fastapi_app(SilentFailureEnvironment, SFDAction, SFDObservation) | |
| ``` | |
| `create_fastapi_app` automatically provides: | |
| - `GET /health` | |
| - `POST /reset`, `POST /step`, `GET /state` (HTTP) | |
| - `WS /ws` (WebSocket — primary transport used by the client) | |
| - `GET /docs` (OpenAPI UI) | |
| - `GET /web` (interactive web UI) | |
| The client inherits from `EnvClient` and uses WebSocket: | |
| ```python | |
| from openenv.core.env_client import EnvClient | |
| class SilentFailureEnv(EnvClient[SFDAction, SFDObservation, SFDState]): | |
| def _step_payload(self, action): return {"message": action.message} | |
| def _parse_result(self, payload): return StepResult(...) | |
| def _parse_state(self, payload): return SFDState(...) | |
| ``` | |
| Usage is always async: | |
| ```python | |
| async with SilentFailureEnv(base_url="http://localhost:7860") as env: | |
| result = await env.reset(task="medium") | |
| result = await env.step(SFDAction(message='{"flag":true,"confidence":0.9}')) | |
| ``` | |
| --- | |
| ## 8. Extending the Dataset | |
| Edit `scripts/generate_dataset.py`, add items to `ITEMS`: | |
| ```python | |
| { | |
| "id": "h_wc_013", # unique: {difficulty}_{label_abbrev}_{num} | |
| "domain": "finance", # medicine|law|finance|coding|science|geography|history | |
| "difficulty": "hard", # easy|medium|hard | |
| "label": "wrong_confident", # wrong_confident|correct|wrong_uncertain|correct_misleading | |
| "question": "...", | |
| "ai_response": "...", | |
| } | |
| ``` | |
| Minimum pool sizes needed: easy ≥10, medium ≥20, hard ≥30. | |
| Target label balance per tier: ~40% wrong_confident, ~35% correct, ~15% wrong_uncertain, ~10% correct_misleading. | |
| Then: `python scripts/generate_dataset.py` | |
| --- | |
| ## 9. Training an RL Agent with GRPO (TRL) | |
| Install TRL: | |
| ```bash | |
| pip install git+https://github.com/huggingface/trl.git | |
| ``` | |
| The environment is stateless per `session_id` and supports concurrent sessions (`SUPPORTS_CONCURRENT_SESSIONS = True`). | |
| Recommended curriculum: | |
| 1. Warm up on `easy` until recall > 0.7 | |
| 2. Train primarily on `medium` | |
| 3. Use `hard` as evaluation benchmark only | |
| Reward is sparse (terminal only). For faster GRPO convergence, consider shaping: give +0.1 for each correctly classified item using the known labels as a secondary signal during training rollouts. | |
| --- | |
| ## 10. Grader Verification | |
| ```python | |
| from server.grader import compute_reward | |
| labels = ["wrong_confident", "correct", "wrong_confident", "wrong_uncertain"] | |
| flags = [True, False, False, False] | |
| confs = [0.9, 0.1, 0.3, 0.2] | |
| reward = compute_reward(labels, flags, confs) | |
| print(reward) | |
| # TP=1, FN=1, TN=2, FP=0 | |
| # recall=0.5, specificity=1.0, base=0.5 | |
| # calibration_bonus~0.1, reward~0.55 | |
| assert 0.0 <= reward <= 1.0 | |
| ``` |