Initialise observations in agent interface
This commit is contained in:
0
src/primaite/game/__init__.py
Normal file
0
src/primaite/game/__init__.py
Normal file
0
src/primaite/game/actor/__init__.py
Normal file
0
src/primaite/game/actor/__init__.py
Normal file
21
src/primaite/game/actor/actions.py
Normal file
21
src/primaite/game/actor/actions.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class AbstractAction(BaseModel):
|
||||
@abstractmethod
|
||||
def __call__(self, action: Any) -> List[str]:
|
||||
"""_summary_
|
||||
|
||||
:param action: _description_
|
||||
:type action: Any
|
||||
:return: _description_
|
||||
:rtype: List[str]
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class ActionSpace:
|
||||
...
|
||||
32
src/primaite/game/actor/interface.py
Normal file
32
src/primaite/game/actor/interface.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# TODO: remove this comment... This is just here to point out that I've named this 'actor' rather than 'agent'
|
||||
# That's because I want to point out that this is disctinct from 'agent' in the reinforcement learning sense of the word
|
||||
# If you disagree, make a comment in the PR review and we can discuss
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from primaite.game.actor.actions import ActionSpace
|
||||
from primaite.game.actor.observations import ObservationSpace
|
||||
from primaite.game.actor.rewards import RewardFunction
|
||||
|
||||
|
||||
class AbstractActor(BaseModel):
|
||||
"""Base class for scripted and RL agents."""
|
||||
|
||||
...
|
||||
|
||||
|
||||
class AbstractScriptedActor(AbstractActor):
|
||||
"""Base class for actors which generate their own behaviour."""
|
||||
|
||||
...
|
||||
|
||||
|
||||
class AbstractPuppetActor(AbstractActor):
|
||||
"""Base class for actors controlled via external messages, such as RL policies."""
|
||||
|
||||
...
|
||||
|
||||
|
||||
# class AbstractRLActor(AbstractPuppetActor): ??
|
||||
107
src/primaite/game/actor/observations.py
Normal file
107
src/primaite/game/actor/observations.py
Normal file
@@ -0,0 +1,107 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Dict, Hashable, List
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
def access_from_nested_dict(dictionary: Dict, keys: List[Hashable]) -> Any:
|
||||
"""
|
||||
Access an item from a deeply dictionary with a list of keys.
|
||||
|
||||
For example, if the dictionary is {1: 'a', 2: {3: {4: 'b'}}}, then the key [2, 3, 4] would return 'b', and the key
|
||||
[2, 3] would return {4: 'b'}. Raises a KeyError if specified key does not exist at any level of nesting.
|
||||
|
||||
:param dictionary: Deeply nested dictionary
|
||||
:type dictionary: Dict
|
||||
:param keys: List of dict keys used to traverse the nested dict. Each item corresponds to one level of depth.
|
||||
:type keys: List[Hashable]
|
||||
:return: The value in the dictionary
|
||||
:rtype: Any
|
||||
"""
|
||||
if not keys:
|
||||
return dictionary
|
||||
k = keys.pop(0)
|
||||
try:
|
||||
return access_from_nested_dict(dictionary[k], keys)
|
||||
except (TypeError, KeyError):
|
||||
raise KeyError(f"Cannot find requested key `{k}` in nested dictionary")
|
||||
|
||||
|
||||
class AbstractObservation(BaseModel):
|
||||
@abstractmethod
|
||||
def __call__(self, state: Dict) -> Any:
|
||||
"""_summary_
|
||||
|
||||
:param state: _description_
|
||||
:type state: Dict
|
||||
:return: _description_
|
||||
:rtype: Any
|
||||
"""
|
||||
...
|
||||
# receive state dict
|
||||
|
||||
|
||||
class FileObservation(AbstractObservation):
|
||||
where: List[str]
|
||||
"""Store information about where in the simulation state dictionary to find the relevatn information."""
|
||||
|
||||
def __call__(self, state: Dict) -> Dict:
|
||||
file_state = access_from_nested_dict(state, self.where)
|
||||
|
||||
|
||||
class ObservationSpace:
|
||||
"""Manage the observations of an Actor."""
|
||||
|
||||
...
|
||||
# what this class does:
|
||||
# keep a list of observations
|
||||
# create observations for an actor from the config
|
||||
|
||||
|
||||
# Example YAML file for agent observation space
|
||||
"""
|
||||
arcd_gate:
|
||||
rl_framework: SB3
|
||||
rl_algo: PPO
|
||||
n_learn_steps: 128
|
||||
n_learn_episodes: 1000
|
||||
|
||||
game_layer:
|
||||
agents:
|
||||
- ref: client_1_green_user
|
||||
type: GREEN
|
||||
node_ref: client_1
|
||||
service: WebBrowser
|
||||
pol:
|
||||
- step: 1
|
||||
action: START
|
||||
|
||||
- ref: client_1_data_manip_red_bot
|
||||
node_ref: client_1
|
||||
service: DataManipulationBot
|
||||
execution_definition:
|
||||
- server_ip_address: 192.168.1.10
|
||||
- server_password:
|
||||
- payload: 'ATTACK'
|
||||
|
||||
pol:
|
||||
- step: 75
|
||||
action: EXECUTE
|
||||
|
||||
|
||||
|
||||
|
||||
simulation:
|
||||
nodes:
|
||||
- ref: client_1
|
||||
hostname: client_1
|
||||
node_type: Computer
|
||||
ip_address: 192.168.10.100
|
||||
services:
|
||||
- name: DataManipulationBot
|
||||
links:
|
||||
endpoint_a:
|
||||
endpoint_b: 1524552-fgfg4147gdh-25gh4gd
|
||||
rewards:
|
||||
|
||||
"""
|
||||
20
src/primaite/game/actor/rewards.py
Normal file
20
src/primaite/game/actor/rewards.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class AbstractReward(BaseModel):
|
||||
def __call__(self, states: List[Dict]) -> float:
|
||||
"""_summary_
|
||||
|
||||
:param state: _description_
|
||||
:type state: Dict
|
||||
:return: _description_
|
||||
:rtype: float
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class RewardFunction(BaseModel):
|
||||
...
|
||||
6
src/primaite/game/session.py
Normal file
6
src/primaite/game/session.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# What do? Be an entry point for using PrimAITE
|
||||
# 1. parse monoconfig
|
||||
# 2. craete simulation
|
||||
# 3. create actors and configure their actions/observations/rewards/ anything else
|
||||
# 4. Create connection with ARCD GATE
|
||||
# 5. idk
|
||||
Reference in New Issue
Block a user