Dev176 commited on
Commit
18db941
·
0 Parent(s):

Initial project structure for Meta PyTorch OpenEnv Hackathon

Browse files
.gitignore ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.pyo
4
+ .env
5
+ .venv/
6
+ venv/
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ .pytest_cache/
11
+ .mypy_cache/
12
+ *.log
13
+ .DS_Store
Dockerfile ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY . .
9
+
10
+ EXPOSE 8000
11
+
12
+ CMD ["uvicorn", "src.environment.server:app", "--host", "0.0.0.0", "--port", "8000"]
README.md ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Meta × PyTorch OpenEnv Hackathon 2026
2
+
3
+ > Built for the **Meta PyTorch OpenEnv Hackathon x SST** — India's Biggest MEGA AI Hackathon.
4
+
5
+ ## Overview
6
+
7
+ This repository contains a complete [OpenEnv](https://github.com/huggingface/openenv)-compliant environment that an AI agent can learn from through the standard `step()` / `reset()` / `state()` API.
8
+
9
+ ## Environment Description
10
+
11
+ <!-- TODO: Describe your chosen environment here -->
12
+
13
+ ## Action & Observation Spaces
14
+
15
+ <!-- TODO: Fill in after choosing your problem statement -->
16
+
17
+ ### Action Space
18
+ ```
19
+ {
20
+ "action_type": str,
21
+ ...
22
+ }
23
+ ```
24
+
25
+ ### Observation Space
26
+ ```
27
+ {
28
+ "state": ...,
29
+ "reward": float,
30
+ "done": bool
31
+ }
32
+ ```
33
+
34
+ ## Tasks
35
+
36
+ | Task | Difficulty | Score Range |
37
+ |------|-----------|-------------|
38
+ | Task 1 | Easy | 0.0 – 1.0 |
39
+ | Task 2 | Medium | 0.0 – 1.0 |
40
+ | Task 3 | Hard | 0.0 – 1.0 |
41
+
42
+ ## Setup & Installation
43
+
44
+ ```bash
45
+ # Clone the repo
46
+ git clone https://github.com/YOUR_USERNAME/meta-pytorch-openenv-hackathon.git
47
+ cd meta-pytorch-openenv-hackathon
48
+
49
+ # Install dependencies
50
+ pip install -r requirements.txt
51
+
52
+ # Run the environment
53
+ python scripts/run_baseline.py
54
+ ```
55
+
56
+ ## Running with Docker
57
+
58
+ ```bash
59
+ docker build -t openenv-hackathon .
60
+ docker run -p 8000:8000 openenv-hackathon
61
+ ```
62
+
63
+ ## API Endpoints
64
+
65
+ | Endpoint | Description |
66
+ |----------|-------------|
67
+ | `POST /reset` | Reset environment, returns initial state |
68
+ | `POST /step` | Execute an action, returns next state + reward |
69
+ | `GET /state` | Get current environment state |
70
+ | `GET /tasks` | List all tasks and action schemas |
71
+ | `GET /grader` | Get grader score after an episode |
72
+ | `GET /baseline` | Run baseline inference and return scores |
73
+
74
+ ## Evaluation Criteria
75
+
76
+ - ✅ HF Space deploys and responds to `reset()`
77
+ - ✅ OpenEnv spec compliance (`openenv.yaml`, typed models)
78
+ - ✅ Dockerfile builds
79
+ - ✅ Baseline script runs without error
80
+ - ✅ 3+ tasks with graders (scores in 0.0–1.0 range)
81
+
82
+ ## Submission Deadline
83
+
84
+ **7th April 2026, 11:59 PM**
85
+
86
+ ## License
87
+
88
+ MIT
openenv.yaml ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: openenv-hackathon
2
+ version: "1.0.0"
3
+ description: "OpenEnv environment for Meta PyTorch Hackathon 2026"
4
+ author: "Devesh B"
5
+
6
+ # TODO: Fill in after choosing your problem statement
7
+ environment:
8
+ type: custom
9
+ entry_point: src/environment/env.py
10
+ class: HackathonEnv
11
+
12
+ tasks:
13
+ - id: task_easy
14
+ name: "Task 1 - Easy"
15
+ difficulty: easy
16
+ grader: src/graders/task_easy_grader.py
17
+
18
+ - id: task_medium
19
+ name: "Task 2 - Medium"
20
+ difficulty: medium
21
+ grader: src/graders/task_medium_grader.py
22
+
23
+ - id: task_hard
24
+ name: "Task 3 - Hard"
25
+ difficulty: hard
26
+ grader: src/graders/task_hard_grader.py
27
+
28
+ api:
29
+ host: 0.0.0.0
30
+ port: 8000
31
+ endpoints:
32
+ - /reset
33
+ - /step
34
+ - /state
35
+ - /tasks
36
+ - /grader
37
+ - /baseline
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ fastapi>=0.110.0
2
+ uvicorn>=0.29.0
3
+ pydantic>=2.0.0
4
+ numpy>=1.26.0
5
+ torch>=2.2.0
6
+ gymnasium>=0.29.0
7
+ httpx>=0.27.0
8
+ pytest>=8.0.0
9
+ python-dotenv>=1.0.0
scripts/run_baseline.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Baseline inference script.
3
+ Run this to produce reproducible scores before submission.
4
+ Usage: python scripts/run_baseline.py
5
+ """
6
+ import httpx
7
+ import json
8
+
9
+ BASE_URL = "http://localhost:8000"
10
+ TASKS = ["task_easy", "task_medium", "task_hard"]
11
+
12
+
13
+ def run_episode(task_id: str) -> float:
14
+ """Run a single episode for the given task and return score."""
15
+ httpx.post(f"{BASE_URL}/reset")
16
+ # TODO: Implement actual baseline agent logic here
17
+ score = httpx.get(f"{BASE_URL}/grader", params={"task_id": task_id}).json()["score"]
18
+ return score
19
+
20
+
21
+ def main():
22
+ print("Running baseline inference...\n")
23
+ scores = {}
24
+ for task in TASKS:
25
+ score = run_episode(task)
26
+ scores[task] = score
27
+ print(f" {task}: {score:.4f}")
28
+
29
+ print(f"\nBaseline scores: {json.dumps(scores, indent=2)}")
30
+ return scores
31
+
32
+
33
+ if __name__ == "__main__":
34
+ main()
scripts/validate.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Pre-submission validation script.
3
+ Run this before submitting to check all automated judge requirements.
4
+ Usage: python scripts/validate.py
5
+ """
6
+ import httpx
7
+ import yaml
8
+ import sys
9
+
10
+ BASE_URL = "http://localhost:8000"
11
+ PASS = "✅"
12
+ FAIL = "❌"
13
+ results = []
14
+
15
+
16
+ def check(label: str, passed: bool, detail: str = ""):
17
+ icon = PASS if passed else FAIL
18
+ print(f" {icon} {label}" + (f" — {detail}" if detail else ""))
19
+ results.append(passed)
20
+
21
+
22
+ def main():
23
+ print("\n🔍 Pre-submission validation\n")
24
+
25
+ # 1. openenv.yaml exists and is valid
26
+ try:
27
+ with open("openenv.yaml") as f:
28
+ config = yaml.safe_load(f)
29
+ check("openenv.yaml valid", True)
30
+ tasks = config.get("tasks", [])
31
+ check("3+ tasks defined", len(tasks) >= 3, f"{len(tasks)} tasks found")
32
+ except Exception as e:
33
+ check("openenv.yaml valid", False, str(e))
34
+
35
+ # 2. Server reachable
36
+ try:
37
+ r = httpx.get(f"{BASE_URL}/tasks", timeout=5)
38
+ check("Server reachable", r.status_code == 200)
39
+ except Exception as e:
40
+ check("Server reachable", False, str(e))
41
+ print("\n⚠️ Start the server first: uvicorn src.environment.server:app --host 0.0.0.0 --port 8000")
42
+ sys.exit(1)
43
+
44
+ # 3. /reset responds
45
+ try:
46
+ r = httpx.post(f"{BASE_URL}/reset", timeout=5)
47
+ check("/reset returns 200", r.status_code == 200)
48
+ except Exception as e:
49
+ check("/reset returns 200", False, str(e))
50
+
51
+ # 4. /tasks lists 3+ tasks
52
+ try:
53
+ r = httpx.get(f"{BASE_URL}/tasks", timeout=5)
54
+ task_list = r.json().get("tasks", [])
55
+ check("/tasks returns 3+ tasks", len(task_list) >= 3, f"{len(task_list)} returned")
56
+ except Exception as e:
57
+ check("/tasks returns 3+ tasks", False, str(e))
58
+
59
+ # 5. /grader scores in 0.0–1.0 range
60
+ try:
61
+ r = httpx.get(f"{BASE_URL}/grader", params={"task_id": "task_easy"}, timeout=5)
62
+ score = r.json().get("score", -1)
63
+ check("Grader score in 0.0–1.0", 0.0 <= score <= 1.0, f"score={score}")
64
+ except Exception as e:
65
+ check("Grader score in 0.0–1.0", False, str(e))
66
+
67
+ # 6. /baseline runs
68
+ try:
69
+ r = httpx.get(f"{BASE_URL}/baseline", timeout=30)
70
+ check("/baseline returns 200", r.status_code == 200)
71
+ except Exception as e:
72
+ check("/baseline returns 200", False, str(e))
73
+
74
+ passed = sum(results)
75
+ total = len(results)
76
+ print(f"\n{'='*40}")
77
+ print(f"Result: {passed}/{total} checks passed")
78
+ if passed == total:
79
+ print("🎉 Ready to submit!")
80
+ else:
81
+ print("⚠️ Fix the failing checks before submitting.")
82
+ print("="*40 + "\n")
83
+
84
+ sys.exit(0 if passed == total else 1)
85
+
86
+
87
+ if __name__ == "__main__":
88
+ main()
src/__init__.py ADDED
File without changes
src/environment/__init__.py ADDED
File without changes
src/environment/env.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Base OpenEnv environment implementation.
3
+ Implements the standard step() / reset() / state() API.
4
+ """
5
+ from abc import ABC, abstractmethod
6
+ from typing import Any
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class StepResult(BaseModel):
11
+ observation: dict[str, Any]
12
+ reward: float
13
+ done: bool
14
+ info: dict[str, Any] = {}
15
+
16
+
17
+ class HackathonEnv(ABC):
18
+ """
19
+ Base class for the hackathon OpenEnv environment.
20
+ TODO: Implement this with your chosen problem statement.
21
+ """
22
+
23
+ def __init__(self):
24
+ self._state: dict[str, Any] = {}
25
+
26
+ @abstractmethod
27
+ def reset(self) -> dict[str, Any]:
28
+ """Reset environment to initial state. Returns initial observation."""
29
+ ...
30
+
31
+ @abstractmethod
32
+ def step(self, action: dict[str, Any]) -> StepResult:
33
+ """Execute action. Returns observation, reward, done flag, info."""
34
+ ...
35
+
36
+ def state(self) -> dict[str, Any]:
37
+ """Return current environment state."""
38
+ return self._state
src/environment/server.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ OpenEnv-compliant FastAPI server.
3
+ Exposes all required endpoints: /reset, /step, /state, /tasks, /grader, /baseline
4
+ """
5
+ from fastapi import FastAPI
6
+ from pydantic import BaseModel
7
+ from typing import Any
8
+
9
+ app = FastAPI(title="OpenEnv Hackathon", version="1.0.0")
10
+
11
+ # TODO: Import and instantiate your environment
12
+ # from src.environment.env import YourEnv
13
+ # env = YourEnv()
14
+
15
+
16
+ class Action(BaseModel):
17
+ action_type: str
18
+ payload: dict[str, Any] = {}
19
+
20
+
21
+ @app.post("/reset")
22
+ def reset():
23
+ """Reset environment and return initial observation."""
24
+ # return env.reset()
25
+ return {"status": "ok", "observation": {}}
26
+
27
+
28
+ @app.post("/step")
29
+ def step(action: Action):
30
+ """Execute an action and return next state, reward, done."""
31
+ # return env.step(action.dict())
32
+ return {"observation": {}, "reward": 0.0, "done": False, "info": {}}
33
+
34
+
35
+ @app.get("/state")
36
+ def state():
37
+ """Get current environment state."""
38
+ # return env.state()
39
+ return {}
40
+
41
+
42
+ @app.get("/tasks")
43
+ def tasks():
44
+ """List all tasks and their action schemas."""
45
+ return {
46
+ "tasks": [
47
+ {"id": "task_easy", "difficulty": "easy", "action_schema": {}},
48
+ {"id": "task_medium", "difficulty": "medium", "action_schema": {}},
49
+ {"id": "task_hard", "difficulty": "hard", "action_schema": {}},
50
+ ]
51
+ }
52
+
53
+
54
+ @app.get("/grader")
55
+ def grader(task_id: str = "task_easy"):
56
+ """Return grader score for a completed episode."""
57
+ # TODO: Implement grader logic
58
+ return {"task_id": task_id, "score": 0.0}
59
+
60
+
61
+ @app.get("/baseline")
62
+ def baseline():
63
+ """Run baseline inference and return scores for all tasks."""
64
+ # TODO: Run actual baseline
65
+ return {
66
+ "scores": {
67
+ "task_easy": 0.0,
68
+ "task_medium": 0.0,
69
+ "task_hard": 0.0,
70
+ }
71
+ }
src/graders/__init__.py ADDED
File without changes
src/tasks/__init__.py ADDED
File without changes
tests/__init__.py ADDED
File without changes