Add custom how-to guides to documentation, additional notebook around how to use dev cli

This commit is contained in:
Charlie Crane
2025-02-26 11:02:00 +00:00
parent 5a7caa33f0
commit 4268e387c4
6 changed files with 696 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
.. only:: comment
© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
.. _custom_action:
Creating Custom Actions in PrimAITE
***********************************
PrimAITE contains a selection of available actions that can be exercised within a training session, listed within ``actions.py``. `Note`: Agents are only able to perform the actions listed within it's action_map, defined within it's configuration YAML. See :ref:`custom_environment` for more information.
Developing Custom Actions
============================
Actions within PrimAITE follow a default format, as seen below and in ``actions.py``. It's important that they have an identifier when declared, as this is used when creating the training environment.
.. code:: Python
class ExampleActionClass(AbstractAction, identifier="ExampleActions"):
"""Example Action Class"""
def __init__(self, manager: "ActionManager", num_nodes: int, num_folders: int, **kwargs) -> None:
super().__init(manager, num_nodes=num_nodes, num_folders=num_folders, **kwargs)
self.verb: str = "ExampleAction"
Integration with PrimAITE ActionManager
==========================================
Any custom actions should then be added to the `ActionManager` class, and the `act_class_identifiers` dictionary. This will map the action class to the corresponding action type string that would be passed through the PrimAITE `request_system`.
Interaction with the PrimAITE Request Manager
================================================
Where an action would cause a request to be sent through the PrimAITE RequestManager, a `form_request` method is expected to be defined within the Action Class. This should format the action into a format that can be ingested by the `RequestManager`. Examples of this include the `NodeFolderCreateAction`, which sends a formed request to create a folder on a given node (seen below).
.. code:: Python
def form_request(self, node_id: int, folder_name: str) -> RequestFormat:
"""Return the action formatted as a request which can be ingested by the PrimAITE simulation."""
node_name = self.manager.get_node_name_by_idx(node_id)
if node_name is None or folder_name is None:
return ["do_nothing"]
return ["network", "node", node_name, "file_system", "create", "folder", folder_name]
Action Masking
==============
Agents which use the `ProxyAgent` class within PrimAITE are able to use Action Masking. This allows the agent to know if the actions are valid/invalid based on the current environment.
Information on how to ensure this can be applied to your custom action can be found in :ref:`action_masking`

View File

@@ -0,0 +1,26 @@
.. only:: comment
© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
.. _custom_environment:
Creating Custom Environments for PrimAITE
*****************************************
PrimAITE generates it's training configuration/Environments through ingestion of YAML files. A detailed walkthrough of how to create your own environment can be found within the ``Creating-Custom-Environments`` jupyter notebook.
You configuration file should follow the hierarchy seen below:
.. code:: yaml
io_settings:
...
game:
...
agents:
...
simulation:
...
For detailed information about each configuration item found within the configuration file, see :ref:`Configurable Items`.

View File

@@ -0,0 +1,46 @@
.. only:: comment
© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
.. _custom_rewards:
Creating Custom Rewards in PrimAITE
***********************************
Rewards within PrimAITE are contained within ``rewards.py``, which details the rewards available for all agents within training sessions, how they are calculated and any other specific information where necessary.
Custom Rewards within PrimAITE should inherit from the ``AbstractReward`` class, found in ``rewards.py``. It's important to include an identifier for any class created within PrimAITE.
.. code:: Python
class ExampleAward(AbstractReward, identifier="ExampleAward"):
"""Example Reward Class """
def calculate(self, state: Dict, last_action_response: "AgentHistoryItem") -> float:
"""Calculate the reward for the current state."""
return 1.0
@classmethod
def from_config(cls, config: dict) -> "AbstractReward":
"""Create a reward function component from a config dictionary."""
return cls()
Custom rewards that have been created should be added to the ``rew_class_identifiers`` dictionary within the ``RewardFunction`` class in ``rewards.py``.
Including Custom Rewards within PrimAITE configuration
======================================================
Custom rewards can then be included within an agents configuration by it's inclusion within the training session configuration YAML.
.. code:: yaml
agents:
- ref: agent_name
reward_function:
reward_components:
- type: DUMMY
weight: 1.0
More detailed information about rewards within PrimAITE can be found within :ref:`Rewards`

View File

@@ -0,0 +1,78 @@
.. only:: comment
© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
Creating Custom Software for PrimAITE
*************************************
This page aims to provide a how-to guide on how to create your own custom software for use within PrimAITE.
PrimAITE has a base software class which should be inherited from when building custom software. Examples of this can be seen in the ``IOSoftware`` and ``Process`` classes.
It's important that any new software created within PrimAITE has the ``identifier`` attribute defined, for use when generating the environment.
Some default attributes may need to be adjusted to align with the intended application of the custom software.
.. code:: Python
from src.primaite.simulator.system.software import Software
class CustomSoftware(Software, identifier="CustomSoftware"):
"""
An example of Custom Software within PrimAITE.
"""
operating_state: OperatingState
"The current operating state of the Custom software"
def describe_state(self) -> Dict:
"""
Produce a dictionary describing the current state of this object.
:return: Current state of this object and child objects.
:rtype: Dict
"""
state = super().describe_state()
state.update({"operating_state": self.operating_state.value})
Default Install
###############
Software can be set to auto-install onto a Node by adding it to the ``SYSTEM_SOFTWARE`` dictionary for the node. An example can be seen in the ``HostNode`` class, which pre-installs some key software that is expected on Nodes, such as the ``NTPClient`` and ``UserManager``.
Requirements
############
Any custom software will need to provide an implementation of the ``describe_state`` method, and conform to the general Pydantic requirements.
It's a good idea, if possible, to also create a ``.show()`` method, as this can be used for visualising the software's status when developing within PrimAITE.
Interaction with the PrimAITE Request System
############################################
If the software is intended to be used by an agent via a :ref:`custom_action`, then it will likely need an implementation of the ``RequestManager``.
Detailed information about the PrimAITE request system can be seen in :ref:`request_system`. An example implementation, derived from the `Application` class is seen below:
.. code:: Python
def _init_request_manager(self) -> RequestManager:
"""
Initialise the request manager.
More information in user guide and docstring for SimComponent._init_request_manager.
"""
_is_application_running = Application._StateValidator(application=self, state=ApplicationOperatingState.RUNNING)
rm = super()._init_request_manager()
rm.add_request(
"scan",
RequestType(
func=lambda request, context: RequestResponse.from_bool(self.scan()), validator=_is_application_running
),
)
return rm
Further information
###################
For more detailed information about the implementation of software within PrimAITE, see :ref:`software`.

View File

@@ -0,0 +1,8 @@
.. only:: comment
© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
Utilising the PrimAITE dev-mode cli
***********************************
A guide for utilising `primaite dev-mode` can be found within the ``How-To-Use-Primaite-Dev-Mode`` jupyter notebook, and also :ref:`Developer Tools`.