Simon Sassi commited on
Commit
0c8e9bd
·
1 Parent(s): 4524124

chore: format code

Browse files
Files changed (3) hide show
  1. agent.py +29 -27
  2. app.py +1 -2
  3. mcp_server.py +26 -24
agent.py CHANGED
@@ -23,9 +23,7 @@ Tips:
23
  - The seed parameter should be used to set your LLM's seed for reproducibility
24
  """
25
 
26
- import json
27
  import os
28
- import re
29
  from dataclasses import dataclass, field
30
  from typing import Optional
31
 
@@ -70,16 +68,16 @@ else:
70
  def call_llm(prompt: str, system_prompt: str, seed: int, max_tokens: int = 300) -> str:
71
  """
72
  Call the LLM with the given prompt. Use this function in your agent.
73
-
74
  Args:
75
  prompt: The user prompt (current game state, history, etc.)
76
  system_prompt: The system prompt (instructions for the agent)
77
  seed: Random seed for reproducibility
78
  max_tokens: Maximum tokens in response (default: 300)
79
-
80
  Returns:
81
  The LLM's response text
82
-
83
  Example:
84
  response = call_llm(
85
  prompt="You are in a forest. What do you do?",
@@ -115,6 +113,7 @@ def call_llm(prompt: str, system_prompt: str, seed: int, max_tokens: int = 300)
115
  @dataclass
116
  class RunResult:
117
  """Result of running the agent. Do not modify this class."""
 
118
  final_score: int
119
  max_score: int
120
  moves: int
@@ -158,25 +157,26 @@ ARGS: {"action": "look"}
158
  # Student Agent - IMPLEMENT THIS CLASS
159
  # =============================================================================
160
 
 
161
  class StudentAgent:
162
  """
163
  Your ReAct agent implementation.
164
-
165
  TODO:
166
  1. Implement the run() method with the ReAct loop
167
  2. Parse LLM responses to extract tool calls
168
  3. Track state and avoid loops
169
-
170
  Use the provided call_llm() function to interact with the LLM.
171
  """
172
-
173
  def __init__(self):
174
  """Initialize your agent here."""
175
  # TODO: Initialize any state tracking you need
176
  # self.history = []
177
  # self.visited_locations = set()
178
  pass
179
-
180
  async def run(
181
  self,
182
  client, # FastMCP Client connected to your MCP server
@@ -187,14 +187,14 @@ class StudentAgent:
187
  ) -> RunResult:
188
  """
189
  Run the agent for a game session.
190
-
191
  Args:
192
  client: FastMCP Client connected to your MCP server
193
  game: Name of the game being played (e.g., "zork1")
194
  max_steps: Maximum number of steps to take
195
  seed: Random seed for reproducibility (use for LLM calls)
196
  verbose: Whether to print detailed output
197
-
198
  Returns:
199
  RunResult with final score and statistics
200
  """
@@ -210,27 +210,27 @@ class StudentAgent:
210
  # e. Update history and state
211
  # f. Check for game over
212
  # 3. Return RunResult with final statistics
213
-
214
  # Example of calling a tool:
215
  # result = await client.call_tool("play_action", {"action": "look"})
216
  # observation = result[0].text if result else "No response"
217
-
218
  # Example of calling the LLM:
219
  # response = call_llm(
220
  # prompt="Current observation: " + observation,
221
  # system_prompt=SYSTEM_PROMPT,
222
  # seed=seed,
223
  # )
224
-
225
  # Placeholder implementation - replace with your code
226
  locations_visited = set()
227
  history = []
228
  final_score = 0
229
  moves = 0
230
-
231
  # TODO: Your implementation here
232
  # ...
233
-
234
  return RunResult(
235
  final_score=final_score,
236
  max_score=350, # Zork1 max score, adjust if needed
@@ -239,22 +239,22 @@ class StudentAgent:
239
  game_completed=False,
240
  history=history,
241
  )
242
-
243
  def _build_prompt(self, observation: str, history: list) -> str:
244
  """
245
  Build the prompt for the LLM.
246
-
247
  TODO: Implement this to create effective prompts
248
  """
249
  # TODO: Combine system prompt, history, and current observation
250
  pass
251
-
252
  def _parse_response(self, response: str) -> tuple[str, str, dict]:
253
  """
254
  Parse LLM response to extract thought, tool name, and arguments.
255
-
256
  TODO: Implement robust parsing
257
-
258
  Returns:
259
  Tuple of (thought, tool_name, args_dict)
260
  """
@@ -263,11 +263,11 @@ class StudentAgent:
263
  # TOOL: ...
264
  # ARGS: {...}
265
  pass
266
-
267
  def _call_llm(self, prompt: str, system_prompt: str, seed: int) -> str:
268
  """
269
  Call the LLM with the given prompt.
270
-
271
  This is a convenience wrapper - you can also use call_llm() directly.
272
  """
273
  return call_llm(prompt, system_prompt, seed)
@@ -277,15 +277,16 @@ class StudentAgent:
277
  # For local testing
278
  # =============================================================================
279
 
 
280
  async def test_agent():
281
  """Test the agent locally."""
282
  from fastmcp import Client
283
-
284
  # Path to your MCP server
285
  server_path = "mcp_server.py"
286
-
287
  agent = StudentAgent()
288
-
289
  async with Client(server_path) as client:
290
  result = await agent.run(
291
  client=client,
@@ -294,7 +295,7 @@ async def test_agent():
294
  seed=42,
295
  verbose=True,
296
  )
297
-
298
  print(f"\nFinal Score: {result.final_score}")
299
  print(f"Moves: {result.moves}")
300
  print(f"Locations: {result.locations_visited}")
@@ -302,4 +303,5 @@ async def test_agent():
302
 
303
  if __name__ == "__main__":
304
  import asyncio
 
305
  asyncio.run(test_agent())
 
23
  - The seed parameter should be used to set your LLM's seed for reproducibility
24
  """
25
 
 
26
  import os
 
27
  from dataclasses import dataclass, field
28
  from typing import Optional
29
 
 
68
  def call_llm(prompt: str, system_prompt: str, seed: int, max_tokens: int = 300) -> str:
69
  """
70
  Call the LLM with the given prompt. Use this function in your agent.
71
+
72
  Args:
73
  prompt: The user prompt (current game state, history, etc.)
74
  system_prompt: The system prompt (instructions for the agent)
75
  seed: Random seed for reproducibility
76
  max_tokens: Maximum tokens in response (default: 300)
77
+
78
  Returns:
79
  The LLM's response text
80
+
81
  Example:
82
  response = call_llm(
83
  prompt="You are in a forest. What do you do?",
 
113
  @dataclass
114
  class RunResult:
115
  """Result of running the agent. Do not modify this class."""
116
+
117
  final_score: int
118
  max_score: int
119
  moves: int
 
157
  # Student Agent - IMPLEMENT THIS CLASS
158
  # =============================================================================
159
 
160
+
161
  class StudentAgent:
162
  """
163
  Your ReAct agent implementation.
164
+
165
  TODO:
166
  1. Implement the run() method with the ReAct loop
167
  2. Parse LLM responses to extract tool calls
168
  3. Track state and avoid loops
169
+
170
  Use the provided call_llm() function to interact with the LLM.
171
  """
172
+
173
  def __init__(self):
174
  """Initialize your agent here."""
175
  # TODO: Initialize any state tracking you need
176
  # self.history = []
177
  # self.visited_locations = set()
178
  pass
179
+
180
  async def run(
181
  self,
182
  client, # FastMCP Client connected to your MCP server
 
187
  ) -> RunResult:
188
  """
189
  Run the agent for a game session.
190
+
191
  Args:
192
  client: FastMCP Client connected to your MCP server
193
  game: Name of the game being played (e.g., "zork1")
194
  max_steps: Maximum number of steps to take
195
  seed: Random seed for reproducibility (use for LLM calls)
196
  verbose: Whether to print detailed output
197
+
198
  Returns:
199
  RunResult with final score and statistics
200
  """
 
210
  # e. Update history and state
211
  # f. Check for game over
212
  # 3. Return RunResult with final statistics
213
+
214
  # Example of calling a tool:
215
  # result = await client.call_tool("play_action", {"action": "look"})
216
  # observation = result[0].text if result else "No response"
217
+
218
  # Example of calling the LLM:
219
  # response = call_llm(
220
  # prompt="Current observation: " + observation,
221
  # system_prompt=SYSTEM_PROMPT,
222
  # seed=seed,
223
  # )
224
+
225
  # Placeholder implementation - replace with your code
226
  locations_visited = set()
227
  history = []
228
  final_score = 0
229
  moves = 0
230
+
231
  # TODO: Your implementation here
232
  # ...
233
+
234
  return RunResult(
235
  final_score=final_score,
236
  max_score=350, # Zork1 max score, adjust if needed
 
239
  game_completed=False,
240
  history=history,
241
  )
242
+
243
  def _build_prompt(self, observation: str, history: list) -> str:
244
  """
245
  Build the prompt for the LLM.
246
+
247
  TODO: Implement this to create effective prompts
248
  """
249
  # TODO: Combine system prompt, history, and current observation
250
  pass
251
+
252
  def _parse_response(self, response: str) -> tuple[str, str, dict]:
253
  """
254
  Parse LLM response to extract thought, tool name, and arguments.
255
+
256
  TODO: Implement robust parsing
257
+
258
  Returns:
259
  Tuple of (thought, tool_name, args_dict)
260
  """
 
263
  # TOOL: ...
264
  # ARGS: {...}
265
  pass
266
+
267
  def _call_llm(self, prompt: str, system_prompt: str, seed: int) -> str:
268
  """
269
  Call the LLM with the given prompt.
270
+
271
  This is a convenience wrapper - you can also use call_llm() directly.
272
  """
273
  return call_llm(prompt, system_prompt, seed)
 
277
  # For local testing
278
  # =============================================================================
279
 
280
+
281
  async def test_agent():
282
  """Test the agent locally."""
283
  from fastmcp import Client
284
+
285
  # Path to your MCP server
286
  server_path = "mcp_server.py"
287
+
288
  agent = StudentAgent()
289
+
290
  async with Client(server_path) as client:
291
  result = await agent.run(
292
  client=client,
 
295
  seed=42,
296
  verbose=True,
297
  )
298
+
299
  print(f"\nFinal Score: {result.final_score}")
300
  print(f"Moves: {result.moves}")
301
  print(f"Locations: {result.locations_visited}")
 
303
 
304
  if __name__ == "__main__":
305
  import asyncio
306
+
307
  asyncio.run(test_agent())
app.py CHANGED
@@ -15,7 +15,6 @@ To test locally:
15
  """
16
 
17
  import gradio as gr
18
- from pathlib import Path
19
 
20
  # Create the Gradio interface
21
  with gr.Blocks(title="Text Adventure Agent Submission") as demo:
@@ -23,7 +22,7 @@ with gr.Blocks(title="Text Adventure Agent Submission") as demo:
23
  gr.Markdown(
24
  "This Space contains a template submission for the Text Adventure Agent assignment. "
25
  )
26
-
27
  gr.Markdown(
28
  "---\n"
29
  "**Note:** This is a code submission Space. "
 
15
  """
16
 
17
  import gradio as gr
 
18
 
19
  # Create the Gradio interface
20
  with gr.Blocks(title="Text Adventure Agent Submission") as demo:
 
22
  gr.Markdown(
23
  "This Space contains a template submission for the Text Adventure Agent assignment. "
24
  )
25
+
26
  gr.Markdown(
27
  "---\n"
28
  "**Note:** This is a code submission Space. "
mcp_server.py CHANGED
@@ -11,10 +11,10 @@ Required tool:
11
  Recommended tools:
12
  memory() -> str
13
  Return current game state, score, and recent history.
14
-
15
- inventory() -> str
16
  Return the player's current inventory.
17
-
18
  get_map() -> str
19
  Return a map of explored locations.
20
 
@@ -45,16 +45,17 @@ mcp = FastMCP("Student Text Adventure Server")
45
  # Game State Management
46
  # =============================================================================
47
 
 
48
  class GameManager:
49
  """
50
  Manages the text adventure game state.
51
-
52
  TODO: Extend this class to track:
53
  - Action history (for memory tool)
54
  - Explored locations (for mapping)
55
  - Current score and moves
56
  """
57
-
58
  def __init__(self):
59
  self.env: TextAdventureEnv = None
60
  self.state = None
@@ -63,7 +64,7 @@ class GameManager:
63
  # self.history: list[tuple[str, str]] = []
64
  # self.explored_locations: dict[str, set[str]] = {}
65
  # self.current_location: str = ""
66
-
67
  def initialize(self, game: str = "zork1"):
68
  """Initialize or reset the game."""
69
  self.game_name = game
@@ -71,24 +72,24 @@ class GameManager:
71
  self.state = self.env.reset()
72
  # TODO: Reset your state tracking here
73
  return self.state.observation
74
-
75
  def step(self, action: str) -> str:
76
  """Execute an action and return the result."""
77
  if self.env is None:
78
  self.initialize()
79
-
80
  self.state = self.env.step(action)
81
-
82
  # TODO: Update your state tracking here
83
  # self.history.append((action, self.state.observation))
84
  # Update location tracking, etc.
85
-
86
  return self.state.observation
87
-
88
  def get_score(self) -> int:
89
  """Get current score."""
90
  return self.state.score if self.state else 0
91
-
92
  def get_moves(self) -> int:
93
  """Get number of moves taken."""
94
  return self.state.moves if self.state else 0
@@ -112,34 +113,35 @@ def get_game() -> GameManager:
112
  # MCP Tools - IMPLEMENT THESE
113
  # =============================================================================
114
 
 
115
  @mcp.tool()
116
  def play_action(action: str) -> str:
117
  """
118
  Execute a game command and return the result.
119
-
120
  This is the main tool for interacting with the game.
121
-
122
  Args:
123
  action: The command to execute (e.g., "north", "take lamp", "open mailbox")
124
-
125
  Returns:
126
  The game's response to the action
127
-
128
  Valid commands include:
129
  - Movement: north, south, east, west, up, down, enter, exit
130
  - Objects: take <item>, drop <item>, open <thing>, examine <thing>
131
  - Other: look, inventory, read <thing>, turn on lamp
132
  """
133
  game = get_game()
134
-
135
  # TODO: You might want to add action validation here
136
  # TODO: You might want to include score changes in the response
137
-
138
  result = game.step(action)
139
-
140
  # Optional: Append score info
141
  # result += f"\n[Score: {game.get_score()} | Moves: {game.get_moves()}]"
142
-
143
  return result
144
 
145
 
@@ -149,7 +151,7 @@ def play_action(action: str) -> str:
149
  # def memory() -> str:
150
  # """
151
  # Get the current game state summary.
152
- #
153
  # Returns:
154
  # A summary including current location, score, moves, and recent history
155
  # """
@@ -162,7 +164,7 @@ def play_action(action: str) -> str:
162
  # def inventory() -> str:
163
  # """
164
  # Check what the player is carrying.
165
- #
166
  # Returns:
167
  # List of items in the player's inventory
168
  # """
@@ -175,7 +177,7 @@ def play_action(action: str) -> str:
175
  # def get_map() -> str:
176
  # """
177
  # Get a map of explored locations.
178
- #
179
  # Returns:
180
  # A text representation of explored locations and connections
181
  # """
@@ -188,7 +190,7 @@ def play_action(action: str) -> str:
188
  # def get_valid_actions() -> str:
189
  # """
190
  # Get a list of likely valid actions from the current location.
191
- #
192
  # Returns:
193
  # List of actions that might work here
194
  # """
 
11
  Recommended tools:
12
  memory() -> str
13
  Return current game state, score, and recent history.
14
+
15
+ inventory() -> str
16
  Return the player's current inventory.
17
+
18
  get_map() -> str
19
  Return a map of explored locations.
20
 
 
45
  # Game State Management
46
  # =============================================================================
47
 
48
+
49
  class GameManager:
50
  """
51
  Manages the text adventure game state.
52
+
53
  TODO: Extend this class to track:
54
  - Action history (for memory tool)
55
  - Explored locations (for mapping)
56
  - Current score and moves
57
  """
58
+
59
  def __init__(self):
60
  self.env: TextAdventureEnv = None
61
  self.state = None
 
64
  # self.history: list[tuple[str, str]] = []
65
  # self.explored_locations: dict[str, set[str]] = {}
66
  # self.current_location: str = ""
67
+
68
  def initialize(self, game: str = "zork1"):
69
  """Initialize or reset the game."""
70
  self.game_name = game
 
72
  self.state = self.env.reset()
73
  # TODO: Reset your state tracking here
74
  return self.state.observation
75
+
76
  def step(self, action: str) -> str:
77
  """Execute an action and return the result."""
78
  if self.env is None:
79
  self.initialize()
80
+
81
  self.state = self.env.step(action)
82
+
83
  # TODO: Update your state tracking here
84
  # self.history.append((action, self.state.observation))
85
  # Update location tracking, etc.
86
+
87
  return self.state.observation
88
+
89
  def get_score(self) -> int:
90
  """Get current score."""
91
  return self.state.score if self.state else 0
92
+
93
  def get_moves(self) -> int:
94
  """Get number of moves taken."""
95
  return self.state.moves if self.state else 0
 
113
  # MCP Tools - IMPLEMENT THESE
114
  # =============================================================================
115
 
116
+
117
  @mcp.tool()
118
  def play_action(action: str) -> str:
119
  """
120
  Execute a game command and return the result.
121
+
122
  This is the main tool for interacting with the game.
123
+
124
  Args:
125
  action: The command to execute (e.g., "north", "take lamp", "open mailbox")
126
+
127
  Returns:
128
  The game's response to the action
129
+
130
  Valid commands include:
131
  - Movement: north, south, east, west, up, down, enter, exit
132
  - Objects: take <item>, drop <item>, open <thing>, examine <thing>
133
  - Other: look, inventory, read <thing>, turn on lamp
134
  """
135
  game = get_game()
136
+
137
  # TODO: You might want to add action validation here
138
  # TODO: You might want to include score changes in the response
139
+
140
  result = game.step(action)
141
+
142
  # Optional: Append score info
143
  # result += f"\n[Score: {game.get_score()} | Moves: {game.get_moves()}]"
144
+
145
  return result
146
 
147
 
 
151
  # def memory() -> str:
152
  # """
153
  # Get the current game state summary.
154
+ #
155
  # Returns:
156
  # A summary including current location, score, moves, and recent history
157
  # """
 
164
  # def inventory() -> str:
165
  # """
166
  # Check what the player is carrying.
167
+ #
168
  # Returns:
169
  # List of items in the player's inventory
170
  # """
 
177
  # def get_map() -> str:
178
  # """
179
  # Get a map of explored locations.
180
+ #
181
  # Returns:
182
  # A text representation of explored locations and connections
183
  # """
 
190
  # def get_valid_actions() -> str:
191
  # """
192
  # Get a list of likely valid actions from the current location.
193
+ #
194
  # Returns:
195
  # List of actions that might work here
196
  # """