Eshit commited on
Commit
75ffb61
·
verified ·
1 Parent(s): 2b174f4

Upload 6 files

Browse files
Files changed (6) hide show
  1. __init__.py +0 -0
  2. app.py +17 -0
  3. dockerfile +21 -0
  4. environment.py +46 -0
  5. requirements.txt +4 -0
  6. schemas.py +33 -0
__init__.py ADDED
File without changes
app.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from openenv.core.env_server import create_app
2
+ from .environment import AccountantEng
3
+ from .schemas import Action, AccountantState
4
+
5
+ # This creates the API server
6
+ # It automatically handles the WebSocket connections for you!
7
+ app = create_app(
8
+ env=AccountantEng,
9
+ action_cls=Action,
10
+ observation_cls=AccountantState,
11
+ env_name="mini-accountant",
12
+ )
13
+
14
+ if __name__ == "__main__":
15
+ import uvicorn
16
+ # This runs the server locally on port 8000
17
+ uvicorn.run(app, host="0.0.0.0", port=8000)
dockerfile ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 1. Use an official Python runtime as a parent image
2
+ FROM python:3.10-slim
3
+
4
+ # 2. Set the working directory in the container
5
+ WORKDIR /app
6
+
7
+ # 3. Copy the requirements file first (better for Docker caching)
8
+ COPY requirements.txt .
9
+
10
+ # 4. Install dependencies
11
+ RUN pip install --no-cache-dir -r requirements.txt
12
+
13
+ # 5. Copy the rest of your application code
14
+ COPY . .
15
+
16
+ # 6. Expose the port the app runs on
17
+ EXPOSE 8000
18
+
19
+ # 7. Run the application
20
+ # We use the same command you used locally!
21
+ CMD ["python", "-m", "mini_accountant_env.app"]
environment.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from openenv.core.env_server import Environment as BaseEnv
2
+ from .schemas import CalculateAction, SubmitAction, AccountantState, Action
3
+
4
+ class AccountantEng(BaseEnv):
5
+ def __init__(self):
6
+ self.target_answer = 3000
7
+ self.max_steps = 5
8
+ self.messy_text = "Revenue was 5000, costs were 2000. What is the net profit?"
9
+ self.current_step = 0
10
+
11
+ def reset(self) -> AccountantState:
12
+ self.current_state = 0
13
+ return AccountantState(
14
+ observation=self.messy_text,
15
+ is_done=False
16
+ )
17
+
18
+ def step(self, action:Action)->tuple[AccountantState, float, bool, dict]:
19
+ self.current_step+=1
20
+ reward=-0.1
21
+ done=False
22
+ observation=""
23
+
24
+ if self.current_step==self.max_steps:
25
+ observation="Max steps reached."
26
+
27
+ if action.action_type=="calculate":
28
+ try:
29
+ result=eval(action.expression)
30
+ observation = f"Calculation result: {result}"
31
+ except Exception as e:
32
+ reward-=0.5
33
+
34
+ elif action.action_type=="submit":
35
+ done=True
36
+ if action.net_profit==self.target_answer:
37
+ reward+=1.0
38
+ observation = "Correct! Task complete."
39
+ else:
40
+ reward-=0.5
41
+ observation = f"Incorrect. The target was not {action.net_profit}."
42
+ if self.current_step==self.max_steps:
43
+ observation="Max steps reached."
44
+
45
+ state = AccountantState(observation=observation, is_done=done)
46
+ return state, float(reward), done, {}
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ openenv
2
+ pydantic>=2.0.0
3
+ fastapi
4
+ uvicorn
schemas.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel, Field
2
+ from typing import Union, Literal
3
+
4
+ # ==========================================
5
+ # 1. TOOL ARGUMENTS (What the agent can do)
6
+ # ==========================================
7
+
8
+ class CalculateAction(BaseModel):
9
+ """Tool to calculate mathematical expressions."""
10
+ action_type: Literal["calculate"] = "calculate"
11
+ expression: str = Field(
12
+ ...,
13
+ description="A strict mathematical expression to evaluate. ONLY use numbers and operators (+, -, *, /). Example: '5000 - 1200 - 800'"
14
+ )
15
+
16
+ class SubmitAction(BaseModel):
17
+ """Submits the final answer"""
18
+ action_type : Literal["submit"]="submit"
19
+ net_profit: float = Field(
20
+ ...,
21
+ description="The final calculated net profit as a floating point number."
22
+ )
23
+
24
+ # The agent's action must be exactly one of these two
25
+ Action = Union[CalculateAction, SubmitAction]
26
+ # ==========================================
27
+ # 2. STATE (What the agent sees)
28
+ # ==========================================
29
+
30
+ class AccountantState(BaseModel):
31
+ """The observation space returned to the agent after every step."""
32
+ observation: str = Field(..., description="The current text prompt, system message, or calculator result.")
33
+ is_done: bool = Field(default=False, description="True if the episode has finished.")