Spaces:
Sleeping
Sleeping
Create inference.py
Browse files- inference.py +91 -0
inference.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
from openai import OpenAI
|
| 4 |
+
from src.disaster_grid.environment import CityGrid
|
| 5 |
+
from src.disaster_grid.models import AgentAction, ActionType
|
| 6 |
+
|
| 7 |
+
def run_inference():
|
| 8 |
+
print("Initializing Disaster Grid Environment...")
|
| 9 |
+
env = CityGrid()
|
| 10 |
+
|
| 11 |
+
# Initialize the API client
|
| 12 |
+
# NOTE: If the hackathon requires a specific API (like Grok or TogetherAI),
|
| 13 |
+
# just change the base_url and model name below!
|
| 14 |
+
client = OpenAI(
|
| 15 |
+
api_key=os.environ.get("API_KEY", "your-api-key-here"),
|
| 16 |
+
base_url="https://api.openai.com/v1"
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
print("\n--- Starting Disaster Scenario ---")
|
| 20 |
+
# Our environment returns a tuple: (observation, info) on reset
|
| 21 |
+
obs, _ = env.reset()
|
| 22 |
+
|
| 23 |
+
done = False
|
| 24 |
+
|
| 25 |
+
while not done:
|
| 26 |
+
print(f"\nTime Step: {env.step_count}/50 | Energy: {env.agent_energy}")
|
| 27 |
+
|
| 28 |
+
# 1. Package the environment state into a prompt for the LLM
|
| 29 |
+
prompt = f"""
|
| 30 |
+
You are an Autonomous AI Emergency Manager.
|
| 31 |
+
|
| 32 |
+
Current Environment State:
|
| 33 |
+
{json.dumps(obs, indent=2)}
|
| 34 |
+
|
| 35 |
+
Rules:
|
| 36 |
+
- You are on a 5x5 grid (indices 0 to 24). You start at index 0.
|
| 37 |
+
- Moving (MOVE_N, MOVE_S, MOVE_E, MOVE_W) costs 2 energy.
|
| 38 |
+
- REPAIR costs 15 energy and adds 25 health to your current sector.
|
| 39 |
+
- RECHARGE adds 20 energy, but ONLY works if you are at index 0 (Base).
|
| 40 |
+
- Do not let your energy hit 0. Navigate to critical sectors and repair them.
|
| 41 |
+
|
| 42 |
+
Determine the best action. You MUST respond with a perfectly formatted JSON object matching this schema:
|
| 43 |
+
{{"action": "MOVE_N" | "MOVE_S" | "MOVE_E" | "MOVE_W" | "REPAIR" | "RECHARGE" | "WAIT", "reasoning": "<string explaining your strategy>"}}
|
| 44 |
+
"""
|
| 45 |
+
|
| 46 |
+
try:
|
| 47 |
+
# 2. Call the LLM
|
| 48 |
+
response = client.chat.completions.create(
|
| 49 |
+
model="gpt-4o", # Replace with "grok-beta" or your required model
|
| 50 |
+
messages=[
|
| 51 |
+
{"role": "system", "content": "You are a JSON-only API. You only output raw, valid JSON."},
|
| 52 |
+
{"role": "user", "content": prompt}
|
| 53 |
+
],
|
| 54 |
+
response_format={"type": "json_object"}
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
# 3. Parse the JSON response
|
| 58 |
+
raw_response = response.choices[0].message.content
|
| 59 |
+
action_data = json.loads(raw_response)
|
| 60 |
+
|
| 61 |
+
# Validate it through our Pydantic model just to be safe
|
| 62 |
+
action_parsed = AgentAction(**action_data)
|
| 63 |
+
|
| 64 |
+
print(f"๐ค AI decided: {action_parsed.action.value}")
|
| 65 |
+
print(f" Reasoning: {action_parsed.reasoning}")
|
| 66 |
+
|
| 67 |
+
# 4. Execute the action in the environment
|
| 68 |
+
# Our env.step returns a 5-item tuple and handles the dict parsing internally
|
| 69 |
+
obs, reward, done, truncated, info = env.step(action_data)
|
| 70 |
+
|
| 71 |
+
# Print any errors from the environment engine (like wall bumps)
|
| 72 |
+
step_result = info.get("step_result", {})
|
| 73 |
+
if step_result.get("is_error"):
|
| 74 |
+
print(f"โ ๏ธ Engine Warning: {step_result.get('error_message')}")
|
| 75 |
+
|
| 76 |
+
except Exception as e:
|
| 77 |
+
print(f"โ Error during LLM processing: {e}")
|
| 78 |
+
print("Forcing a WAIT action to prevent the loop from crashing...")
|
| 79 |
+
fallback_action = {"action": ActionType.WAIT.value, "reasoning": "Fallback due to error"}
|
| 80 |
+
obs, reward, done, truncated, info = env.step(fallback_action)
|
| 81 |
+
|
| 82 |
+
# 5. The episode is finished. Print the final summary!
|
| 83 |
+
print("\n" + "="*40)
|
| 84 |
+
print("๐ EPISODE COMPLETE ๐")
|
| 85 |
+
print(f"Final City Health: {sum(env.grid_health)/25:.1f}/100")
|
| 86 |
+
print(f"Final Energy: {env.agent_energy}")
|
| 87 |
+
print(f"Steps Taken: {env.step_count}")
|
| 88 |
+
print("="*40)
|
| 89 |
+
|
| 90 |
+
if __name__ == "__main__":
|
| 91 |
+
run_inference()
|