Krishna1107 commited on
Commit
eb895b1
·
1 Parent(s): 2794920

inference fixed, port changed to 7860

Browse files
Dockerfile CHANGED
@@ -12,11 +12,11 @@ COPY baseline_runner.py .
12
  COPY inference.py .
13
  COPY openenv.yaml .
14
 
15
- # HuggingFace Spaces expects port 8000
16
- EXPOSE 8000
17
 
18
  # Health check
19
  HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
20
- CMD python -c "import requests; requests.get('http://localhost:8000/')" || exit 1
21
 
22
- CMD ["python", "-m", "uvicorn", "server.app:app", "--host", "0.0.0.0", "--port", "8000"]
 
12
  COPY inference.py .
13
  COPY openenv.yaml .
14
 
15
+ # HuggingFace Spaces expects port 7860
16
+ EXPOSE 7860
17
 
18
  # Health check
19
  HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
20
+ CMD python -c "import requests; requests.get('http://localhost:7860/')" || exit 1
21
 
22
+ CMD ["python", "-m", "uvicorn", "server.app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 🔧
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: docker
7
- app_port: 8000
8
  pinned: false
9
  ---
10
 
@@ -296,12 +296,12 @@ This ensures:
296
 
297
  ```bash
298
  # 1. Start an episode
299
- curl -X POST http://localhost:8000/reset \
300
  -H "Content-Type: application/json" \
301
  -d '{"task_id": "k8s_pod_failures", "scenario_id": "oom_killed"}'
302
 
303
  # 2. Fix the memory limit (any reasonable value works — simulator validates structurally)
304
- curl -X POST http://localhost:8000/step \
305
  -H "Content-Type: application/json" \
306
  -d '{
307
  "action": {
@@ -325,7 +325,7 @@ curl -X POST http://localhost:8000/step \
325
 
326
  ```bash
327
  pip install -r requirements.txt
328
- python -m uvicorn server.app:app --host 0.0.0.0 --port 8000
329
  ```
330
 
331
  ### Run Tests
@@ -338,7 +338,7 @@ pytest tests/ -v
338
 
339
  ```bash
340
  docker build -t cloud-native-devops-env .
341
- docker run -p 8000:8000 cloud-native-devops-env
342
  ```
343
 
344
  ### Baseline Inference (with LLM)
 
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: docker
7
+ app_port: 7860
8
  pinned: false
9
  ---
10
 
 
296
 
297
  ```bash
298
  # 1. Start an episode
299
+ curl -X POST http://localhost:7860/reset \
300
  -H "Content-Type: application/json" \
301
  -d '{"task_id": "k8s_pod_failures", "scenario_id": "oom_killed"}'
302
 
303
  # 2. Fix the memory limit (any reasonable value works — simulator validates structurally)
304
+ curl -X POST http://localhost:7860/step \
305
  -H "Content-Type: application/json" \
306
  -d '{
307
  "action": {
 
325
 
326
  ```bash
327
  pip install -r requirements.txt
328
+ python -m uvicorn server.app:app --host 0.0.0.0 --port 7860
329
  ```
330
 
331
  ### Run Tests
 
338
 
339
  ```bash
340
  docker build -t cloud-native-devops-env .
341
+ docker run -p 7860:7860 cloud-native-devops-env
342
  ```
343
 
344
  ### Baseline Inference (with LLM)
inference.py CHANGED
@@ -56,7 +56,7 @@ from openai import OpenAI
56
  API_BASE_URL = os.getenv("API_BASE_URL") or "https://router.huggingface.co/v1"
57
  MODEL_NAME = os.getenv("MODEL_NAME") or "meta-llama/Llama-3.1-70B-Instruct"
58
  API_KEY = os.getenv("HF_TOKEN") or os.getenv("API_KEY")
59
- ENV_URL = os.getenv("ENV_URL", "http://localhost:8000")
60
  LOCAL_IMAGE_NAME = os.getenv("LOCAL_IMAGE_NAME")
61
  BENCHMARK = "cloud_native_devops"
62
  MAX_STEPS = 8 # leave 2 steps buffer before env hard-limit of 10
@@ -72,18 +72,29 @@ Your job is to:
72
 
73
  When you identify a fix, respond with a JSON object in this exact format:
74
  {
 
75
  "reasoning": "Brief explanation of the bug and fix",
76
  "edits": [
77
  {
78
  "file_path": "path/to/file",
79
- "old_content": "exact broken line or block",
80
- "new_content": "corrected line or block"
 
81
  }
82
  ]
83
  }
84
 
85
- To create a new file (e.g. a missing ConfigMap), use an empty old_content:
 
 
 
 
 
 
 
 
86
  {
 
87
  "reasoning": "Create missing ConfigMap manifest",
88
  "edits": [
89
  {
@@ -95,10 +106,10 @@ To create a new file (e.g. a missing ConfigMap), use an empty old_content:
95
  }
96
 
97
  If you believe all issues are fixed and want to submit, respond with:
98
- {"action": "submit"}
99
 
100
  If you need a hint, respond with:
101
- {"action": "hint"}
102
 
103
  Rules:
104
  - Match old_content EXACTLY as it appears in the file (whitespace matters)
@@ -217,20 +228,26 @@ def parse_llm_response(text: str) -> Dict[str, Any]:
217
 
218
  def build_action(parsed: Dict[str, Any]) -> Dict[str, Any]:
219
  """Convert parsed LLM response to environment action format."""
220
- if parsed.get("action") == "submit":
 
 
 
221
  return {"action_type": "submit"}
222
- if parsed.get("action") == "hint":
223
  return {"action_type": "request_hint"}
224
 
225
  edits = parsed.get("edits", [])
226
- if not edits:
227
  return {"action_type": "submit"}
228
 
 
 
229
  return {
230
- "action_type": "edit_file",
231
  "edits": [
232
  {
233
  "file_path": e.get("file_path", ""),
 
234
  "old_content": e.get("old_content", ""),
235
  "new_content": e.get("new_content", ""),
236
  }
@@ -384,7 +401,7 @@ def main():
384
  print(f"[DEBUG] Environment status: {health.get('status', 'unknown')}", flush=True)
385
  except Exception as e:
386
  print(f"[DEBUG] Cannot connect to environment at {ENV_URL}: {e}", flush=True)
387
- print("[DEBUG] Start the server first: python -m uvicorn server.app:app --host 0.0.0.0 --port 8000", flush=True)
388
  sys.exit(1)
389
 
390
  client = create_client()
 
56
  API_BASE_URL = os.getenv("API_BASE_URL") or "https://router.huggingface.co/v1"
57
  MODEL_NAME = os.getenv("MODEL_NAME") or "meta-llama/Llama-3.1-70B-Instruct"
58
  API_KEY = os.getenv("HF_TOKEN") or os.getenv("API_KEY")
59
+ ENV_URL = os.getenv("ENV_URL", "http://localhost:7860")
60
  LOCAL_IMAGE_NAME = os.getenv("LOCAL_IMAGE_NAME")
61
  BENCHMARK = "cloud_native_devops"
62
  MAX_STEPS = 8 # leave 2 steps buffer before env hard-limit of 10
 
72
 
73
  When you identify a fix, respond with a JSON object in this exact format:
74
  {
75
+ "action_type": "YOUR_CHOSEN_ACTION_TYPE",
76
  "reasoning": "Brief explanation of the bug and fix",
77
  "edits": [
78
  {
79
  "file_path": "path/to/file",
80
+ "line_number": 5, // Only needed for replace_line, add_line, delete_line, add_block
81
+ "old_content": "exactly broken", // Only needed for edit_file, delete_block
82
+ "new_content": "corrected block" // Not needed for delete_line, delete_block
83
  }
84
  ]
85
  }
86
 
87
+ Available action_type values for edits:
88
+ - "edit_file" (requires old_content and new_content)
89
+ - "replace_line" (requires line_number and new_content)
90
+ - "add_line" (requires line_number and new_content)
91
+ - "delete_line" (requires line_number)
92
+ - "add_block" (requires line_number and new_content)
93
+ - "delete_block" (requires old_content)
94
+
95
+ To create a new file (e.g. a missing ConfigMap), use "edit_file" with empty old_content:
96
  {
97
+ "action_type": "edit_file",
98
  "reasoning": "Create missing ConfigMap manifest",
99
  "edits": [
100
  {
 
106
  }
107
 
108
  If you believe all issues are fixed and want to submit, respond with:
109
+ {"action_type": "submit"}
110
 
111
  If you need a hint, respond with:
112
+ {"action_type": "request_hint"}
113
 
114
  Rules:
115
  - Match old_content EXACTLY as it appears in the file (whitespace matters)
 
228
 
229
  def build_action(parsed: Dict[str, Any]) -> Dict[str, Any]:
230
  """Convert parsed LLM response to environment action format."""
231
+ action_type = parsed.get("action_type")
232
+
233
+ # Backwards compatibility and standard aliases
234
+ if parsed.get("action") == "submit" or action_type == "submit":
235
  return {"action_type": "submit"}
236
+ if parsed.get("action") == "hint" or action_type == "request_hint":
237
  return {"action_type": "request_hint"}
238
 
239
  edits = parsed.get("edits", [])
240
+ if not edits and not action_type:
241
  return {"action_type": "submit"}
242
 
243
+ action_str = action_type if action_type else "edit_file"
244
+
245
  return {
246
+ "action_type": action_str,
247
  "edits": [
248
  {
249
  "file_path": e.get("file_path", ""),
250
+ "line_number": e.get("line_number"),
251
  "old_content": e.get("old_content", ""),
252
  "new_content": e.get("new_content", ""),
253
  }
 
401
  print(f"[DEBUG] Environment status: {health.get('status', 'unknown')}", flush=True)
402
  except Exception as e:
403
  print(f"[DEBUG] Cannot connect to environment at {ENV_URL}: {e}", flush=True)
404
+ print("[DEBUG] Start the server first: python -m uvicorn server.app:app --host 0.0.0.0 --port 7860", flush=True)
405
  sys.exit(1)
406
 
407
  client = create_client()
server/app.py CHANGED
@@ -234,7 +234,7 @@ async def run_baseline(request: Optional[BaselineRequest] = None):
234
 
235
 
236
  def main():
237
- uvicorn.run(app, host="0.0.0.0", port=8000)
238
 
239
 
240
  if __name__ == "__main__":
 
234
 
235
 
236
  def main():
237
+ uvicorn.run(app, host="0.0.0.0", port=7860)
238
 
239
 
240
  if __name__ == "__main__":
server/static/index.html CHANGED
@@ -428,12 +428,12 @@
428
  </div>
429
  <div class="code-block">
430
  <span class="comment"># 1. Get a broken K8s deployment with OOMKilled pods</span>
431
- <span class="cmd">curl</span> -X POST <span class="url">http://localhost:8000/reset</span> \
432
  -H <span class="flag">"Content-Type: application/json"</span> \
433
  -d '{"task_id": "k8s_pod_failures", "scenario_id": "oom_killed"}'
434
 
435
  <span class="comment"># 2. Bump the memory limit from 64Mi to 256Mi</span>
436
- <span class="cmd">curl</span> -X POST <span class="url">http://localhost:8000/step</span> \
437
  -H <span class="flag">"Content-Type: application/json"</span> \
438
  -d '{"action": {"action_type": "edit_file", "edits": [{"file_path": "k8s/deployment.yaml", "old_content": "memory: \"64Mi\"", "new_content": "memory: \"256Mi\""}]}}'
439
 
 
428
  </div>
429
  <div class="code-block">
430
  <span class="comment"># 1. Get a broken K8s deployment with OOMKilled pods</span>
431
+ <span class="cmd">curl</span> -X POST <span class="url">http://localhost:7860/reset</span> \
432
  -H <span class="flag">"Content-Type: application/json"</span> \
433
  -d '{"task_id": "k8s_pod_failures", "scenario_id": "oom_killed"}'
434
 
435
  <span class="comment"># 2. Bump the memory limit from 64Mi to 256Mi</span>
436
+ <span class="cmd">curl</span> -X POST <span class="url">http://localhost:7860/step</span> \
437
  -H <span class="flag">"Content-Type: application/json"</span> \
438
  -d '{"action": {"action_type": "edit_file", "edits": [{"file_path": "k8s/deployment.yaml", "old_content": "memory: \"64Mi\"", "new_content": "memory: \"256Mi\""}]}}'
439
 
server/tasks/pipeline_build_deploy.py CHANGED
@@ -128,7 +128,7 @@ class PipelineBuildDeployTask(BaseTask):
128
  "COPY requirements.txt .\n"
129
  "RUN pip install -r requirements.txt\n"
130
  "COPY . .\n"
131
- "EXPOSE 8000\n"
132
  'CMD ["python", "app.py"]\n'
133
  ),
134
  },
@@ -275,7 +275,7 @@ class PipelineBuildDeployTask(BaseTask):
275
  "WORKDIR /app\n"
276
  "COPY . .\n"
277
  "RUN echo $APP_VERSION > /app/version.txt\n"
278
- "EXPOSE 8000\n"
279
  'CMD ["python", "app.py"]\n'
280
  ),
281
  },
@@ -341,7 +341,7 @@ class PipelineBuildDeployTask(BaseTask):
341
  "COPY requirements.txt .\n"
342
  "RUN pip install -r requirements.txt\n"
343
  "COPY . .\n"
344
- "EXPOSE 8000\n"
345
  'CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]\n'
346
  ),
347
  },
 
128
  "COPY requirements.txt .\n"
129
  "RUN pip install -r requirements.txt\n"
130
  "COPY . .\n"
131
+ "EXPOSE 7860\n"
132
  'CMD ["python", "app.py"]\n'
133
  ),
134
  },
 
275
  "WORKDIR /app\n"
276
  "COPY . .\n"
277
  "RUN echo $APP_VERSION > /app/version.txt\n"
278
+ "EXPOSE 7860\n"
279
  'CMD ["python", "app.py"]\n'
280
  ),
281
  },
 
341
  "COPY requirements.txt .\n"
342
  "RUN pip install -r requirements.txt\n"
343
  "COPY . .\n"
344
+ "EXPOSE 7860\n"
345
  'CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]\n'
346
  ),
347
  },
server/tasks/pipeline_full.py CHANGED
@@ -299,8 +299,8 @@ class PipelineFullTask(BaseTask):
299
  "COPY requirements.txt .\n"
300
  "RUN pip install -r requirements.txt\n"
301
  "COPY . .\n"
302
- "EXPOSE 8000\n"
303
- 'CMD ["gunicorn", "app:app", "-b", "0.0.0.0:8000"]\n'
304
  ),
305
  },
306
  {
@@ -330,7 +330,7 @@ class PipelineFullTask(BaseTask):
330
  " - name: api\n"
331
  " image: ghcr.io/myorg/myapp:latest\n"
332
  " ports:\n"
333
- " - containerPort: 8000\n"
334
  " resources:\n"
335
  " limits:\n"
336
  ' memory: "64Mi"\n'
 
299
  "COPY requirements.txt .\n"
300
  "RUN pip install -r requirements.txt\n"
301
  "COPY . .\n"
302
+ "EXPOSE 7860\n"
303
+ 'CMD ["gunicorn", "app:app", "-b", "0.0.0.0:7860"]\n'
304
  ),
305
  },
306
  {
 
330
  " - name: api\n"
331
  " image: ghcr.io/myorg/myapp:latest\n"
332
  " ports:\n"
333
+ " - containerPort: 7860\n"
334
  " resources:\n"
335
  " limits:\n"
336
  ' memory: "64Mi"\n'
server/tasks/task_1_build_errors.py CHANGED
@@ -70,7 +70,7 @@ class DockerfileSyntaxTask(BaseTask):
70
  "COPY requirements.txt .\n"
71
  "RUN pip install -r requirements.txt\n"
72
  "COPY . .\n"
73
- "EXPOSE 8000\n"
74
  'CMD ["python", "app.py"]'
75
  ),
76
  },
 
70
  "COPY requirements.txt .\n"
71
  "RUN pip install -r requirements.txt\n"
72
  "COPY . .\n"
73
+ "EXPOSE 7860\n"
74
  'CMD ["python", "app.py"]'
75
  ),
76
  },
smoke_test.py CHANGED
@@ -2,7 +2,7 @@
2
 
3
  Usage:
4
  .\\.venv\\Scripts\\python.exe smoke_test.py
5
- .\\.venv\\Scripts\\python.exe smoke_test.py --mode live --base-url http://127.0.0.1:8000
6
 
7
  Modes:
8
  - inprocess (default): uses FastAPI TestClient, no running server needed.
@@ -227,7 +227,7 @@ def run_smoke(client: EndpointClient) -> int:
227
  def main() -> int:
228
  parser = argparse.ArgumentParser(description="Smoke test Cloud-Native DevOps Debug FastAPI server")
229
  parser.add_argument("--mode", choices=["inprocess", "live"], default="inprocess")
230
- parser.add_argument("--base-url", default="http://127.0.0.1:8000")
231
  args = parser.parse_args()
232
 
233
  if args.mode == "inprocess":
 
2
 
3
  Usage:
4
  .\\.venv\\Scripts\\python.exe smoke_test.py
5
+ .\\.venv\\Scripts\\python.exe smoke_test.py --mode live --base-url http://127.0.0.1:7860
6
 
7
  Modes:
8
  - inprocess (default): uses FastAPI TestClient, no running server needed.
 
227
  def main() -> int:
228
  parser = argparse.ArgumentParser(description="Smoke test Cloud-Native DevOps Debug FastAPI server")
229
  parser.add_argument("--mode", choices=["inprocess", "live"], default="inprocess")
230
+ parser.add_argument("--base-url", default="http://127.0.0.1:7860")
231
  args = parser.parse_args()
232
 
233
  if args.mode == "inprocess":