Initialise observations in agent interface

This commit is contained in:
Marek Wolan
2023-09-21 10:13:01 +01:00
parent fd1a4403f4
commit f54f278fca
10 changed files with 333 additions and 7 deletions

View File

View File

View 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:
...

View 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): ??

View 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:
"""

View 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):
...

View 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