shivam2k3 commited on
Commit
ef1fd72
·
1 Parent(s): e75ae7b

hugging face runtime error fix

Browse files
Files changed (5) hide show
  1. Dockerfile +2 -0
  2. app_runtime.py +141 -0
  3. pyproject.toml +1 -1
  4. server.py +2 -2
  5. server/app.py +2 -143
Dockerfile CHANGED
@@ -12,8 +12,10 @@ COPY requirements.txt .
12
  RUN pip install --no-cache-dir -r requirements.txt
13
 
14
  # Copy source
 
15
  COPY env.py .
16
  COPY server.py .
 
17
  COPY tasks/ tasks/
18
  COPY openenv.yaml .
19
 
 
12
  RUN pip install --no-cache-dir -r requirements.txt
13
 
14
  # Copy source
15
+ COPY app_runtime.py .
16
  COPY env.py .
17
  COPY server.py .
18
+ COPY server/ server/
19
  COPY tasks/ tasks/
20
  COPY openenv.yaml .
21
 
app_runtime.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Shared FastAPI application module for source and packaged entry points."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from typing import Any, Dict, Optional
7
+
8
+ from fastapi import FastAPI, HTTPException, Query
9
+ from fastapi.middleware.cors import CORSMiddleware
10
+ from pydantic import BaseModel
11
+
12
+ from env import Action, CodeReviewEnv, Observation
13
+
14
+ app = FastAPI(
15
+ title="CodeReviewEnv",
16
+ description="OpenEnv environment for AI-driven code review and bug triage",
17
+ version="1.0.0",
18
+ )
19
+
20
+ app.add_middleware(
21
+ CORSMiddleware,
22
+ allow_origins=["*"],
23
+ allow_methods=["*"],
24
+ allow_headers=["*"],
25
+ )
26
+
27
+ _envs: Dict[str, CodeReviewEnv] = {}
28
+
29
+
30
+ def _get_env(task: str) -> CodeReviewEnv:
31
+ if task not in _envs:
32
+ _envs[task] = CodeReviewEnv(task_id=task)
33
+ return _envs[task]
34
+
35
+
36
+ class StepResult(BaseModel):
37
+ observation: Observation
38
+ reward: float
39
+ done: bool
40
+ info: Dict[str, Any]
41
+
42
+
43
+ class GradeResult(BaseModel):
44
+ task: str
45
+ score: float
46
+ found_issues: list
47
+ false_positives: int
48
+ final_decision: Optional[str]
49
+ steps_taken: int
50
+
51
+
52
+ @app.post("/reset", response_model=Observation)
53
+ def reset(task: str = Query("easy", description="Task difficulty: easy | medium | hard")):
54
+ """Reset the environment and return the initial observation."""
55
+ env = _get_env(task)
56
+ try:
57
+ obs = env.reset()
58
+ except ValueError as exc:
59
+ raise HTTPException(status_code=400, detail=str(exc)) from exc
60
+ return obs
61
+
62
+
63
+ @app.post("/step", response_model=StepResult)
64
+ def step(
65
+ action: Action,
66
+ task: str = Query("easy", description="Task difficulty: easy | medium | hard"),
67
+ ):
68
+ """Execute one action and return observation, reward, done, info."""
69
+ env = _get_env(task)
70
+ if env._state is None:
71
+ raise HTTPException(status_code=400, detail="Call /reset first.")
72
+ try:
73
+ obs, reward, done, info = env.step(action)
74
+ except RuntimeError as exc:
75
+ raise HTTPException(status_code=400, detail=str(exc)) from exc
76
+ return StepResult(observation=obs, reward=reward, done=done, info=info)
77
+
78
+
79
+ @app.get("/state")
80
+ def state(task: str = Query("easy")):
81
+ """Return the full internal episode state."""
82
+ env = _get_env(task)
83
+ return env.state()
84
+
85
+
86
+ @app.get("/tasks")
87
+ def list_tasks():
88
+ """List available task IDs with descriptions."""
89
+ return {
90
+ "tasks": [
91
+ {
92
+ "id": "easy",
93
+ "difficulty": "easy",
94
+ "description": "Find one obvious null-dereference bug in a user service.",
95
+ "num_issues": 1,
96
+ },
97
+ {
98
+ "id": "medium",
99
+ "difficulty": "medium",
100
+ "description": "Find an off-by-one boundary bug AND a missing thread-safety lock in a rate limiter.",
101
+ "num_issues": 2,
102
+ },
103
+ {
104
+ "id": "hard",
105
+ "difficulty": "hard",
106
+ "description": "Find a SQL injection vulnerability AND an unbounded memory leak in a report service.",
107
+ "num_issues": 2,
108
+ },
109
+ ]
110
+ }
111
+
112
+
113
+ @app.post("/grade", response_model=GradeResult)
114
+ def grade(task: str = Query("easy")):
115
+ """Compute normalised 0-1 score for the current (or just-finished) episode."""
116
+ env = _get_env(task)
117
+ if env._state is None:
118
+ raise HTTPException(status_code=400, detail="No episode to grade. Call /reset first.")
119
+ score = env.grade()
120
+ state_obj = env._state
121
+ return GradeResult(
122
+ task=task,
123
+ score=score,
124
+ found_issues=state_obj.found_issue_ids,
125
+ false_positives=state_obj.false_positives,
126
+ final_decision=state_obj.final_decision,
127
+ steps_taken=state_obj.step,
128
+ )
129
+
130
+
131
+ @app.get("/health")
132
+ def health():
133
+ return {"status": "ok", "env": "CodeReviewEnv", "version": "1.0.0"}
134
+
135
+
136
+ def main() -> None:
137
+ import uvicorn
138
+
139
+ port = int(os.getenv("PORT", 7860))
140
+ uvicorn.run(app, host="0.0.0.0", port=port)
141
+
pyproject.toml CHANGED
@@ -31,7 +31,7 @@ test = [
31
  ]
32
 
33
  [tool.setuptools]
34
- py-modules = ["env", "inference"]
35
 
36
  [tool.setuptools.packages.find]
37
  include = ["server*", "tasks*"]
 
31
  ]
32
 
33
  [tool.setuptools]
34
+ py-modules = ["app_runtime", "env", "inference"]
35
 
36
  [tool.setuptools.packages.find]
37
  include = ["server*", "tasks*"]
server.py CHANGED
@@ -1,6 +1,6 @@
1
- """Compatibility wrapper for the packaged server entry point."""
2
 
3
- from server.app import app, main
4
 
5
 
6
  if __name__ == "__main__":
 
1
+ """Source entry point used by Docker and local `python server.py` runs."""
2
 
3
+ from app_runtime import app, main
4
 
5
 
6
  if __name__ == "__main__":
server/app.py CHANGED
@@ -1,144 +1,3 @@
1
- """FastAPI server for CodeReviewEnv."""
2
 
3
- from __future__ import annotations
4
-
5
- import os
6
- from typing import Any, Dict, Optional
7
-
8
- from fastapi import FastAPI, HTTPException, Query
9
- from fastapi.middleware.cors import CORSMiddleware
10
- from pydantic import BaseModel
11
-
12
- from env import Action, CodeReviewEnv, Observation
13
-
14
- app = FastAPI(
15
- title="CodeReviewEnv",
16
- description="OpenEnv environment for AI-driven code review and bug triage",
17
- version="1.0.0",
18
- )
19
-
20
- app.add_middleware(
21
- CORSMiddleware,
22
- allow_origins=["*"],
23
- allow_methods=["*"],
24
- allow_headers=["*"],
25
- )
26
-
27
- _envs: Dict[str, CodeReviewEnv] = {}
28
-
29
-
30
- def _get_env(task: str) -> CodeReviewEnv:
31
- if task not in _envs:
32
- _envs[task] = CodeReviewEnv(task_id=task)
33
- return _envs[task]
34
-
35
-
36
- class StepResult(BaseModel):
37
- observation: Observation
38
- reward: float
39
- done: bool
40
- info: Dict[str, Any]
41
-
42
-
43
- class GradeResult(BaseModel):
44
- task: str
45
- score: float
46
- found_issues: list
47
- false_positives: int
48
- final_decision: Optional[str]
49
- steps_taken: int
50
-
51
-
52
- @app.post("/reset", response_model=Observation)
53
- def reset(task: str = Query("easy", description="Task difficulty: easy | medium | hard")):
54
- """Reset the environment and return the initial observation."""
55
- env = _get_env(task)
56
- try:
57
- obs = env.reset()
58
- except ValueError as exc:
59
- raise HTTPException(status_code=400, detail=str(exc)) from exc
60
- return obs
61
-
62
-
63
- @app.post("/step", response_model=StepResult)
64
- def step(
65
- action: Action,
66
- task: str = Query("easy", description="Task difficulty: easy | medium | hard"),
67
- ):
68
- """Execute one action and return observation, reward, done, info."""
69
- env = _get_env(task)
70
- if env._state is None:
71
- raise HTTPException(status_code=400, detail="Call /reset first.")
72
- try:
73
- obs, reward, done, info = env.step(action)
74
- except RuntimeError as exc:
75
- raise HTTPException(status_code=400, detail=str(exc)) from exc
76
- return StepResult(observation=obs, reward=reward, done=done, info=info)
77
-
78
-
79
- @app.get("/state")
80
- def state(task: str = Query("easy")):
81
- """Return the full internal episode state."""
82
- env = _get_env(task)
83
- return env.state()
84
-
85
-
86
- @app.get("/tasks")
87
- def list_tasks():
88
- """List available task IDs with descriptions."""
89
- return {
90
- "tasks": [
91
- {
92
- "id": "easy",
93
- "difficulty": "easy",
94
- "description": "Find one obvious null-dereference bug in a user service.",
95
- "num_issues": 1,
96
- },
97
- {
98
- "id": "medium",
99
- "difficulty": "medium",
100
- "description": "Find an off-by-one boundary bug AND a missing thread-safety lock in a rate limiter.",
101
- "num_issues": 2,
102
- },
103
- {
104
- "id": "hard",
105
- "difficulty": "hard",
106
- "description": "Find a SQL injection vulnerability AND an unbounded memory leak in a report service.",
107
- "num_issues": 2,
108
- },
109
- ]
110
- }
111
-
112
-
113
- @app.post("/grade", response_model=GradeResult)
114
- def grade(task: str = Query("easy")):
115
- """Compute normalised 0-1 score for the current (or just-finished) episode."""
116
- env = _get_env(task)
117
- if env._state is None:
118
- raise HTTPException(status_code=400, detail="No episode to grade. Call /reset first.")
119
- score = env.grade()
120
- state_obj = env._state
121
- return GradeResult(
122
- task=task,
123
- score=score,
124
- found_issues=state_obj.found_issue_ids,
125
- false_positives=state_obj.false_positives,
126
- final_decision=state_obj.final_decision,
127
- steps_taken=state_obj.step,
128
- )
129
-
130
-
131
- @app.get("/health")
132
- def health():
133
- return {"status": "ok", "env": "CodeReviewEnv", "version": "1.0.0"}
134
-
135
-
136
- def main() -> None:
137
- import uvicorn
138
-
139
- port = int(os.getenv("PORT", 7860))
140
- uvicorn.run(app, host="0.0.0.0", port=port)
141
-
142
-
143
- if __name__ == "__main__":
144
- main()
 
1
+ """Packaged server entry point required for multi-mode deployment."""
2
 
3
+ from app_runtime import app, main