Ramachandra Dayal K commited on
Commit
e2284e6
·
1 Parent(s): e88fa8b

fix: resolve openEnv reset response inconsistency and port mismatch

Browse files
Files changed (4) hide show
  1. README.md +5 -5
  2. app.py +15 -6
  3. index.html +16 -11
  4. test_env.py +40 -19
README.md CHANGED
@@ -39,8 +39,8 @@ pip install -r requirements.txt
39
  ### Try it out
40
 
41
  ```bash
42
- openenv validate
43
- docker build -t llm-control .
44
  ```
45
 
46
  Quick Local Test Snippet:
@@ -48,12 +48,12 @@ Quick Local Test Snippet:
48
  import requests
49
 
50
  # Reset environment
51
- resp = requests.post("http://localhost:8000/reset", json={"task": "easy"})
52
- obs = resp.json()
53
  print("Reset observation:", obs)
54
 
55
  # Take step
56
- resp = requests.post("http://localhost:8000/step", json={"action": {"action_type": "follow_prompt"}})
57
  print("Step result:", resp.json())
58
  ```
59
 
 
39
  ### Try it out
40
 
41
  ```bash
42
+ # Run the FastAPI server
43
+ python app.py
44
  ```
45
 
46
  Quick Local Test Snippet:
 
48
  import requests
49
 
50
  # Reset environment
51
+ resp = requests.post("http://localhost:7860/reset", json={"task": "easy"})
52
+ obs = resp.json()["observation"]
53
  print("Reset observation:", obs)
54
 
55
  # Take step
56
+ resp = requests.post("http://localhost:7860/step", json={"action": {"action_type": "follow_prompt"}})
57
  print("Step result:", resp.json())
58
  ```
59
 
app.py CHANGED
@@ -2,6 +2,7 @@ from fastapi import FastAPI, HTTPException
2
  from fastapi.responses import HTMLResponse
3
  from fastapi.staticfiles import StaticFiles
4
  from pydantic import BaseModel
 
5
  import sys
6
  import os
7
 
@@ -12,9 +13,13 @@ from server.llm_env import LLMEnv
12
 
13
  app = FastAPI(title="LLM Control OpenEnv")
14
 
15
- # In-memory store for environments per episode id and overall states
16
- envs = {}
17
- completed_episodes = {}
 
 
 
 
18
 
19
  class ResetRequest(BaseModel):
20
  task: str = "easy"
@@ -38,20 +43,24 @@ async def serve_gui():
38
  except FileNotFoundError:
39
  return "GUI index.html not found. Check the root directory."
40
 
41
- @app.post("/reset", response_model=Observation)
42
  async def reset(req: ResetRequest):
43
  if req.task not in ["easy", "medium", "hard"]:
44
  raise HTTPException(status_code=400, detail="Invalid task")
45
 
46
  env = LLMEnv(task=req.task)
47
  obs = env.reset()
48
- envs[env.state.episode_id] = env
 
49
 
50
  # Also set default env to the latest reset for easy single-agent testing
51
  global default_env
52
  default_env = env
53
 
54
- return obs
 
 
 
55
 
56
  @app.post("/step")
57
  async def step(req: StepRequest):
 
2
  from fastapi.responses import HTMLResponse
3
  from fastapi.staticfiles import StaticFiles
4
  from pydantic import BaseModel
5
+ from typing import Dict, Any
6
  import sys
7
  import os
8
 
 
13
 
14
  app = FastAPI(title="LLM Control OpenEnv")
15
 
16
+ # Global in-memory store for environments and session state
17
+ envs: Dict[str, LLMEnv] = {}
18
+ completed_episodes: Dict[str, Dict[str, Any]] = {}
19
+
20
+ # Default global environment initialized with a reset state
21
+ default_env = LLMEnv()
22
+ default_env.reset()
23
 
24
  class ResetRequest(BaseModel):
25
  task: str = "easy"
 
43
  except FileNotFoundError:
44
  return "GUI index.html not found. Check the root directory."
45
 
46
+ @app.post("/reset")
47
  async def reset(req: ResetRequest):
48
  if req.task not in ["easy", "medium", "hard"]:
49
  raise HTTPException(status_code=400, detail="Invalid task")
50
 
51
  env = LLMEnv(task=req.task)
52
  obs = env.reset()
53
+ state = env.state
54
+ envs[state.episode_id] = env
55
 
56
  # Also set default env to the latest reset for easy single-agent testing
57
  global default_env
58
  default_env = env
59
 
60
+ return {
61
+ "observation": obs.model_dump(),
62
+ "state": state.model_dump()
63
+ }
64
 
65
  @app.post("/step")
66
  async def step(req: StepRequest):
index.html CHANGED
@@ -241,17 +241,22 @@
241
 
242
  async function resetEnv() {
243
  log("Sending reset sequence...");
244
- const res = await fetch('/reset', {
245
- method: 'POST',
246
- headers: { 'Content-Type': 'application/json' },
247
- body: JSON.stringify({ task: "medium" })
248
- });
249
- const data = await res.json();
250
- updateUI(data);
251
- document.getElementById('reward-val').innerText = "0.00";
252
- document.getElementById('reward-val').style.color = "var(--cyber-green)";
253
- isDead = false;
254
- log("System Reset Complete.");
 
 
 
 
 
255
  }
256
 
257
  async function takeAction(actionType) {
 
241
 
242
  async function resetEnv() {
243
  log("Sending reset sequence...");
244
+ try {
245
+ const res = await fetch('/reset', {
246
+ method: 'POST',
247
+ headers: { 'Content-Type': 'application/json' },
248
+ body: JSON.stringify({ task: "medium" })
249
+ });
250
+ const data = await res.json();
251
+ updateUI(data.observation);
252
+ document.getElementById('reward-val').innerText = "0.00";
253
+ document.getElementById('reward-val').style.color = "var(--cyber-green)";
254
+ isDead = false;
255
+ log(`System Reset Complete. Episode ID: <span style="color:var(--cyber-blue); font-size: 0.7rem;">${data.state.episode_id}</span>`);
256
+ } catch (err) {
257
+ log("<span class='log-mi'>Error during reset. Check server console.</span>");
258
+ console.error(err);
259
+ }
260
  }
261
 
262
  async function takeAction(actionType) {
test_env.py CHANGED
@@ -2,26 +2,47 @@ import requests
2
  import json
3
 
4
  def test():
5
- print("Resetting the environment (easy task)...")
6
- resp = requests.post("http://localhost:8000/reset", json={"task": "easy"})
7
- obs = resp.json()
8
- print("Initial Observation:")
9
- print(json.dumps(obs, indent=2))
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  print("\nTaking an action: 'follow_prompt'...")
12
- resp = requests.post("http://localhost:8000/step", json={"action": {"action_type": "follow_prompt"}})
13
- result = resp.json()
14
- print("Step Result:")
15
- print(json.dumps(result, indent=2))
16
-
17
- print("\nTaking an action: 'minor_hallucination'...")
18
- resp = requests.post("http://localhost:8000/step", json={"action": {"action_type": "minor_hallucination"}})
19
- result = resp.json()
20
- print("Step Result:")
21
- print(json.dumps(result, indent=2))
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  if __name__ == "__main__":
24
- try:
25
- test()
26
- except requests.exceptions.ConnectionError:
27
- print("Error: Could not connect to the API. Is the server running on http://localhost:8000?")
 
2
  import json
3
 
4
  def test():
5
+ # Use the correct port 7860 as defined in app.py
6
+ base_url = "http://localhost:7860"
7
+
8
+ print(f"Resetting the environment (easy task) via {base_url}/reset...")
9
+ try:
10
+ resp = requests.post(f"{base_url}/reset", json={"task": "easy"})
11
+ resp.raise_for_status()
12
+ data = resp.json()
13
+
14
+ # New API returns a wrapped object: {"observation": ..., "state": ...}
15
+ obs = data["observation"]
16
+ episode_id = data["state"]["episode_id"]
17
+
18
+ print(f"Initial Observation (Episode: {episode_id}):")
19
+ print(json.dumps(obs, indent=2))
20
+ except (requests.exceptions.RequestException, KeyError) as e:
21
+ print(f"Error during reset: {e}")
22
+ return
23
 
24
  print("\nTaking an action: 'follow_prompt'...")
25
+ try:
26
+ resp = requests.post(f"{base_url}/step", json={
27
+ "action": {"action_type": "follow_prompt"},
28
+ "episode_id": episode_id
29
+ })
30
+ resp.raise_for_status()
31
+ result = resp.json()
32
+ print("Step Result:")
33
+ print(json.dumps(result, indent=2))
34
+
35
+ print("\nTaking an action: 'minor_hallucination'...")
36
+ resp = requests.post(f"{base_url}/step", json={
37
+ "action": {"action_type": "minor_hallucination"},
38
+ "episode_id": episode_id
39
+ })
40
+ resp.raise_for_status()
41
+ result = resp.json()
42
+ print("Step Result:")
43
+ print(json.dumps(result, indent=2))
44
+ except Exception as e:
45
+ print(f"Error during steps: {e}")
46
 
47
  if __name__ == "__main__":
48
+ test()