Merged PR 544: #2871 - Add show functions to Agents
## Summary This PR introduces a `show_history` function that can be used to view what actions have been taken by an agent over a training session. Be default, this won't show any `DONOTHING` actions. ## Test process  ## Checklist - [X] PR is linked to a **work item** - [X] **acceptance criteria** of linked ticket are met - [X] performed **self-review** of the code - [X] written **tests** for any new functionality added with this PR - [X] updated the **documentation** if this PR changes or adds functionality - [ ] written/updated **design docs** if this PR implements new functionality - [X] updated the **change log** - [X] ran **pre-commit** checks for code style - [X] attended to any **TO-DOs** left in the code Related work items: #2871
This commit is contained in:
@@ -5,10 +5,11 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [3.3.0] - 2024-09-04
|
## [3.4.0]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Log observation space data by episode and step.
|
- Log observation space data by episode and step.
|
||||||
|
- Added `show_history` method to Agents, allowing you to view actions taken by an agent per step. By default, `DONOTHING` actions are omitted.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- ACL's are no longer applied to layer-2 traffic.
|
- ACL's are no longer applied to layer-2 traffic.
|
||||||
|
|||||||
@@ -177,3 +177,4 @@ If ``True``, gymnasium flattening will be performed on the observation space bef
|
|||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Agents will record their action log for each step. This is a summary of what the agent did, along with response information from requests within the simulation.
|
Agents will record their action log for each step. This is a summary of what the agent did, along with response information from requests within the simulation.
|
||||||
|
A summary of the actions taken by the agent can be viewed using the `show_history()` function. By default, this will display all actions taken apart from ``DONOTHING``.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from abc import ABC, abstractmethod
|
|||||||
from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING
|
from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING
|
||||||
|
|
||||||
from gymnasium.core import ActType, ObsType
|
from gymnasium.core import ActType, ObsType
|
||||||
|
from prettytable import PrettyTable
|
||||||
from pydantic import BaseModel, model_validator
|
from pydantic import BaseModel, model_validator
|
||||||
|
|
||||||
from primaite.game.agent.actions import ActionManager
|
from primaite.game.agent.actions import ActionManager
|
||||||
@@ -126,6 +127,37 @@ class AbstractAgent(ABC):
|
|||||||
self.history: List[AgentHistoryItem] = []
|
self.history: List[AgentHistoryItem] = []
|
||||||
self.logger = AgentLog(agent_name)
|
self.logger = AgentLog(agent_name)
|
||||||
|
|
||||||
|
def add_agent_action(self, item: AgentHistoryItem, table: PrettyTable) -> PrettyTable:
|
||||||
|
"""Update the given table with information from given AgentHistoryItem."""
|
||||||
|
node, application = "unknown", "unknown"
|
||||||
|
if (node_id := item.parameters.get("node_id")) is not None:
|
||||||
|
node = self.action_manager.node_names[node_id]
|
||||||
|
if (application_id := item.parameters.get("application_id")) is not None:
|
||||||
|
application = self.action_manager.application_names[node_id][application_id]
|
||||||
|
if (application_name := item.parameters.get("application_name")) is not None:
|
||||||
|
application = application_name
|
||||||
|
table.add_row([item.timestep, item.action, node, application, item.response.status])
|
||||||
|
return table
|
||||||
|
|
||||||
|
def show_history(self, ignored_actions: Optional[list] = None):
|
||||||
|
"""
|
||||||
|
Print an agent action provided it's not the DONOTHING action.
|
||||||
|
|
||||||
|
:param ignored_actions: OPTIONAL: List of actions to be ignored when displaying the history.
|
||||||
|
If not provided, defaults to ignore DONOTHING actions.
|
||||||
|
"""
|
||||||
|
if not ignored_actions:
|
||||||
|
ignored_actions = ["DONOTHING"]
|
||||||
|
table = PrettyTable()
|
||||||
|
table.field_names = ["Step", "Action", "Node", "Application", "Response"]
|
||||||
|
print(f"Actions for '{self.agent_name}':")
|
||||||
|
for item in self.history:
|
||||||
|
if item.action in ignored_actions:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
table = self.add_agent_action(item=item, table=table)
|
||||||
|
print(table)
|
||||||
|
|
||||||
def update_observation(self, state: Dict) -> ObsType:
|
def update_observation(self, state: Dict) -> ObsType:
|
||||||
"""
|
"""
|
||||||
Convert a state from the simulator into an observation for the agent using the observation space.
|
Convert a state from the simulator into an observation for the agent using the observation space.
|
||||||
|
|||||||
@@ -1800,6 +1800,16 @@
|
|||||||
"\n",
|
"\n",
|
||||||
"display_obs_diffs(tcp_c2_obs, udp_c2_obs, blue_config_env.game.step_counter)"
|
"display_obs_diffs(tcp_c2_obs, udp_c2_obs, blue_config_env.game.step_counter)"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"\n",
|
||||||
|
"env.game.agents[\"CustomC2Agent\"].show_history()"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
|
|||||||
@@ -675,6 +675,15 @@
|
|||||||
" print(f\"step: {env.game.step_counter}, Red action: {info['agent_actions']['data_manipulation_attacker'].action}, Blue reward:{reward:.2f}\" )"
|
" print(f\"step: {env.game.step_counter}, Red action: {info['agent_actions']['data_manipulation_attacker'].action}, Blue reward:{reward:.2f}\" )"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"env.game.agents[\"data_manipulation_attacker\"].show_history()"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
@@ -708,7 +717,7 @@
|
|||||||
"name": "python",
|
"name": "python",
|
||||||
"nbconvert_exporter": "python",
|
"nbconvert_exporter": "python",
|
||||||
"pygments_lexer": "ipython3",
|
"pygments_lexer": "ipython3",
|
||||||
"version": "3.10.12"
|
"version": "3.10.11"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
|||||||
@@ -144,6 +144,49 @@
|
|||||||
"PRIMAITE_CONFIG[\"developer_mode\"][\"enabled\"] = was_enabled\n",
|
"PRIMAITE_CONFIG[\"developer_mode\"][\"enabled\"] = was_enabled\n",
|
||||||
"PRIMAITE_CONFIG[\"developer_mode\"][\"output_sys_logs\"] = was_syslogs_enabled"
|
"PRIMAITE_CONFIG[\"developer_mode\"][\"output_sys_logs\"] = was_syslogs_enabled"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Viewing Agent history\n",
|
||||||
|
"\n",
|
||||||
|
"It's possible to view the actions carried out by an agent for a given training session using the `show_history()` method. By default, this will be all actions apart from DONOTHING actions."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"with open(data_manipulation_config_path(), 'r') as f:\n",
|
||||||
|
" cfg = yaml.safe_load(f)\n",
|
||||||
|
"\n",
|
||||||
|
"env = PrimaiteGymEnv(env_config=cfg)\n",
|
||||||
|
"\n",
|
||||||
|
"# Run the training session to generate some resultant data.\n",
|
||||||
|
"for i in range(100):\n",
|
||||||
|
" env.step(0)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Calling `.show_history()` should show us when the Data Manipulation used the `NODE_APPLICATION_EXECUTE` action."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"attacker = env.game.agents[\"data_manipulation_attacker\"]\n",
|
||||||
|
"\n",
|
||||||
|
"attacker.show_history()"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
@@ -162,7 +205,7 @@
|
|||||||
"name": "python",
|
"name": "python",
|
||||||
"nbconvert_exporter": "python",
|
"nbconvert_exporter": "python",
|
||||||
"pygments_lexer": "ipython3",
|
"pygments_lexer": "ipython3",
|
||||||
"version": "3.10.8"
|
"version": "3.10.11"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
|||||||
Reference in New Issue
Block a user