Spaces:
Running
Running
Update agents.py
Browse files
agents.py
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
|
|
| 1 |
import os
|
| 2 |
import json
|
| 3 |
import asyncio
|
| 4 |
import random
|
| 5 |
from openai import AsyncOpenAI # Use AsyncOpenAI for async compatibility with poke-env
|
| 6 |
|
|
|
|
| 7 |
from poke_env.player import Player
|
| 8 |
from poke_env.environment.battle import Battle
|
| 9 |
from poke_env.environment.move import Move
|
| 10 |
from poke_env.environment.pokemon import Pokemon
|
| 11 |
-
from poke_env.player import
|
| 12 |
-
|
| 13 |
|
| 14 |
|
| 15 |
class OpenAIAgent(Player):
|
| 16 |
"""
|
| 17 |
An AI agent for Pokemon Showdown that uses OpenAI's API
|
| 18 |
with function calling to decide its moves.
|
|
|
|
| 19 |
"""
|
| 20 |
def __init__(self, *args, **kwargs):
|
|
|
|
| 21 |
super().__init__(*args, **kwargs)
|
| 22 |
|
| 23 |
# Initialize OpenAI client
|
|
|
|
| 24 |
api_key = os.environ["OPENAI_API_KEY"]
|
| 25 |
if not api_key:
|
| 26 |
-
raise ValueError("OPENAI_API_KEY environment variable not set.")
|
|
|
|
| 27 |
# Use AsyncOpenAI for compatibility with poke-env's async nature
|
| 28 |
self.openai_client = AsyncOpenAI(api_key=api_key)
|
| 29 |
-
self.model = "gpt-4o" # Or "gpt-
|
| 30 |
|
| 31 |
# Define the functions OpenAI can "call"
|
| 32 |
self.functions = [
|
|
@@ -59,10 +64,10 @@ class OpenAIAgent(Player):
|
|
| 59 |
},
|
| 60 |
},
|
| 61 |
]
|
|
|
|
| 62 |
|
| 63 |
def _format_battle_state(self, battle: Battle) -> str:
|
| 64 |
"""Formats the current battle state into a string for the LLM."""
|
| 65 |
-
|
| 66 |
# Own active Pokemon details
|
| 67 |
active_pkmn = battle.active_pokemon
|
| 68 |
active_pkmn_info = f"Your active Pokemon: {active_pkmn.species} " \
|
|
@@ -176,8 +181,8 @@ class OpenAIAgent(Player):
|
|
| 176 |
"""
|
| 177 |
# 1. Format battle state
|
| 178 |
battle_state_str = self._format_battle_state(battle)
|
| 179 |
-
# print(f"\n--- Turn {battle.turn} ---")
|
| 180 |
-
# print(battle_state_str) #
|
| 181 |
|
| 182 |
# 2. Get decision from OpenAI
|
| 183 |
decision = await self._get_openai_decision(battle_state_str)
|
|
@@ -217,7 +222,8 @@ class OpenAIAgent(Player):
|
|
| 217 |
# Ensure options exist before choosing randomly
|
| 218 |
available_options = battle.available_moves + battle.available_switches
|
| 219 |
if available_options:
|
|
|
|
| 220 |
return self.choose_random_move(battle)
|
| 221 |
else:
|
| 222 |
# Should only happen if forced to Struggle
|
| 223 |
-
return self.choose_default_move(battle)
|
|
|
|
| 1 |
+
# agent.py
|
| 2 |
import os
|
| 3 |
import json
|
| 4 |
import asyncio
|
| 5 |
import random
|
| 6 |
from openai import AsyncOpenAI # Use AsyncOpenAI for async compatibility with poke-env
|
| 7 |
|
| 8 |
+
# Import necessary poke-env components for type hinting and functionality
|
| 9 |
from poke_env.player import Player
|
| 10 |
from poke_env.environment.battle import Battle
|
| 11 |
from poke_env.environment.move import Move
|
| 12 |
from poke_env.environment.pokemon import Pokemon
|
| 13 |
+
from poke_env.player import Observation # Observation might not be directly used here, but good to keep if extending
|
|
|
|
| 14 |
|
| 15 |
|
| 16 |
class OpenAIAgent(Player):
|
| 17 |
"""
|
| 18 |
An AI agent for Pokemon Showdown that uses OpenAI's API
|
| 19 |
with function calling to decide its moves.
|
| 20 |
+
Requires OPENAI_API_KEY environment variable to be set.
|
| 21 |
"""
|
| 22 |
def __init__(self, *args, **kwargs):
|
| 23 |
+
# Pass account_configuration and other Player args/kwargs to the parent
|
| 24 |
super().__init__(*args, **kwargs)
|
| 25 |
|
| 26 |
# Initialize OpenAI client
|
| 27 |
+
# It's slightly better practice to get the key here rather than relying solely on the global env scope
|
| 28 |
api_key = os.environ["OPENAI_API_KEY"]
|
| 29 |
if not api_key:
|
| 30 |
+
raise ValueError("OPENAI_API_KEY environment variable not set or loaded.")
|
| 31 |
+
|
| 32 |
# Use AsyncOpenAI for compatibility with poke-env's async nature
|
| 33 |
self.openai_client = AsyncOpenAI(api_key=api_key)
|
| 34 |
+
self.model = "gpt-4o" # Or "gpt-3.5-turbo", "gpt-4-turbo-preview", etc.
|
| 35 |
|
| 36 |
# Define the functions OpenAI can "call"
|
| 37 |
self.functions = [
|
|
|
|
| 64 |
},
|
| 65 |
},
|
| 66 |
]
|
| 67 |
+
self.battle_history = [] # Optional: To potentially add context later
|
| 68 |
|
| 69 |
def _format_battle_state(self, battle: Battle) -> str:
|
| 70 |
"""Formats the current battle state into a string for the LLM."""
|
|
|
|
| 71 |
# Own active Pokemon details
|
| 72 |
active_pkmn = battle.active_pokemon
|
| 73 |
active_pkmn_info = f"Your active Pokemon: {active_pkmn.species} " \
|
|
|
|
| 181 |
"""
|
| 182 |
# 1. Format battle state
|
| 183 |
battle_state_str = self._format_battle_state(battle)
|
| 184 |
+
# print(f"\n--- Turn {battle.turn} ---") # Debugging
|
| 185 |
+
# print(battle_state_str) # Debugging
|
| 186 |
|
| 187 |
# 2. Get decision from OpenAI
|
| 188 |
decision = await self._get_openai_decision(battle_state_str)
|
|
|
|
| 222 |
# Ensure options exist before choosing randomly
|
| 223 |
available_options = battle.available_moves + battle.available_switches
|
| 224 |
if available_options:
|
| 225 |
+
# Use the built-in random choice method from Player for fallback
|
| 226 |
return self.choose_random_move(battle)
|
| 227 |
else:
|
| 228 |
# Should only happen if forced to Struggle
|
| 229 |
+
return self.choose_default_move(battle)
|