#3110: fix links in how-to guides

This commit is contained in:
Nick Todd
2025-03-11 12:27:45 +00:00
parent b4df227af3
commit 42f7925748
10 changed files with 72 additions and 68 deletions

View File

@@ -39,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated tests that don't use YAMLs to still use the new action and agent schemas
- Nodes now use a config schema and are extensible, allowing for plugin support.
- Node tests have been updated to use the new node config schemas when not using YAML files.
- Documentation has been updated to include details of extensability with PrimAITE.
- Documentation has been updated to include details of extensibility with PrimAITE.
- Software is created in the GOOD health state instead of UNUSED.
- Standardised naming convention for YAML config files using kebab-case.
This naming convention is used for configuring software, observations, actions and node types.

View File

@@ -2,6 +2,8 @@
© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
.. _action_masking:
Action Masking
**************
The PrimAITE simulation is able to provide action masks in the environment output. These action masks let the agents know

View File

@@ -2,6 +2,8 @@
© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
.. _Configurable_Items:
PrimAITE |VERSION| Configuration
********************************

View File

@@ -42,4 +42,4 @@ Should your custom environment need any additional PrimAITE plugins, each must b
Configuration Items
===================
For detailed information about the remaining configuration items found within the configuration file, see :ref:`Configurable Items`.
For detailed information about the remaining configuration items found within the configuration file, see :ref:`Configurable_Items`.

View File

@@ -9,7 +9,7 @@ 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.
Rewards within PrimAITE have been updated to facilitate extensability and the creation of plugins with the release of PrimAITE version 4.0. Additional information about this is covered within :ref:`extensible_rewards`.
Rewards within PrimAITE have been updated to facilitate extensibility and the creation of plugins with the release of PrimAITE version 4.0. Additional information about this is covered within :ref:`extensible_rewards`.
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.

View File

@@ -17,50 +17,50 @@ All agent types within PrimAITE must be subclassed from ``AbstractAgent`` in ord
The core features that should be implemented in any new agent are detailed below:
#. **ConfigSchema**:
**ConfigSchema**:
Configurable items within a new agent within PrimAITE should contain a ``ConfigSchema`` which holds all configurable variables of the agent. This should not include parameters related to its *state*, these would be listed seperately.
Agent generation will fail pydantic checks if incorrect or invalid parameters are passed to the ConfigSchema of the chosen Agent.
Configurable items within a new agent within PrimAITE should contain a ``ConfigSchema`` which holds all configurable variables of the agent. This should not include parameters related to its *state*, these would be listed seperately.
Agent generation will fail pydantic checks if incorrect or invalid parameters are passed to the ConfigSchema of the chosen Agent.
.. code-block:: python
.. code-block:: python
class ExampleAgent(AbstractAgent, discriminator = "ExampleAgent"):
"""An example agent for demonstration purposes."""
class ExampleAgent(AbstractAgent, discriminator = "ExampleAgent"):
"""An example agent for demonstration purposes."""
config: "ExampleAgent.ConfigSchema" = Field(default_factory= lambda: ExampleAgent.ConfigSchema())
"""Agent configuration"""
num_executions: int = 0
"""Number of action executions by agent"""
config: "ExampleAgent.ConfigSchema" = Field(default_factory= lambda: ExampleAgent.ConfigSchema())
"""Agent configuration"""
num_executions: int = 0
"""Number of action executions by agent"""
class ConfigSchema(AbstractAgent.ConfigSchema):
"""ExampleAgent configuration schema"""
class ConfigSchema(AbstractAgent.ConfigSchema):
"""ExampleAgent configuration schema"""
type: str = "ExampleAgent
"""Name of agent"""
starting_host: int
"""Host node that this agent should start from in the given environment."""
type: str = "ExampleAgent
"""Name of agent"""
starting_host: int
"""Host node that this agent should start from in the given environment."""
.. code-block:: yaml
.. code-block:: yaml
- ref: example_green_agent
team: GREEN
type: example-agent
- ref: example_green_agent
team: GREEN
type: example-agent
action_space:
action_map:
0:
action: do-nothing
options: {}
agent_settings:
start_step: 25
frequency: 20
variance: 5
starting_host: "Server_1"
action_space:
action_map:
0:
action: do-nothing
options: {}
agent_settings:
start_step: 25
frequency: 20
variance: 5
starting_host: "Server_1"
#. **discriminators**:
**discriminators**:
All agent classes should have an ``discriminator`` attribute, a unique kebab-case string, for when they are added to the base ``AbstractAgent`` registry. This is then specified in your configuration YAML, and used by PrimAITE to generate the correct Agent.

View File

@@ -22,30 +22,30 @@ An example of how additional Node classes is below, taken from `router.py` withi
.. code-block:: Python
class Router(NetworkNode, identifier="router"):
""" Represents a network router within the simulation, managing routing and forwarding of IP packets across network interfaces."""
class Router(NetworkNode, identifier="router"):
""" Represents a network router within the simulation, managing routing and forwarding of IP packets across network interfaces."""
SYSTEM_SOFTWARE: ClassVar[Dict] = {
"user-session-manager": UserSessionManager,
"user-manager": UserManager,
"terminal": Terminal,
}
SYSTEM_SOFTWARE: ClassVar[Dict] = {
"user-session-manager": UserSessionManager,
"user-manager": UserManager,
"terminal": Terminal,
}
network_interfaces: Dict[str, RouterInterface] = {}
"The Router Interfaces on the node."
network_interface: Dict[int, RouterInterface] = {}
"The Router Interfaces on the node by port id."
network_interfaces: Dict[str, RouterInterface] = {}
"The Router Interfaces on the node."
network_interface: Dict[int, RouterInterface] = {}
"The Router Interfaces on the node by port id."
sys_log: SysLog
sys_log: SysLog
config: "Router.ConfigSchema" = Field(default_factory=lambda: Router.ConfigSchema())
config: "Router.ConfigSchema" = Field(default_factory=lambda: Router.ConfigSchema())
class ConfigSchema(NetworkNode.ConfigSchema):
"""Configuration Schema for Router Objects."""
class ConfigSchema(NetworkNode.ConfigSchema):
"""Configuration Schema for Router Objects."""
num_ports: int = 5
num_ports: int = 5
hostname: str = "Router"
hostname: str = "Router"

View File

@@ -28,30 +28,28 @@ To add a new reward class follow the example below. Note that the type attribute
.. code-block:: Python
class DatabaseFileIntegrity(AbstractReward, discriminator="database-file-integrity"):
"""Reward function component which rewards the agent for maintaining the integrity of a database file."""
class DatabaseFileIntegrity(AbstractReward, discriminator="database-file-integrity"):
"""Reward function component which rewards the agent for maintaining the integrity of a database file."""
config: "DatabaseFileIntegrity.ConfigSchema"
location_in_state: List[str] = [""]
reward: float = 0.0
config: "DatabaseFileIntegrity.ConfigSchema"
location_in_state: List[str] = [""]
reward: float = 0.0
class ConfigSchema(AbstractReward.ConfigSchema):
"""ConfigSchema for DatabaseFileIntegrity."""
class ConfigSchema(AbstractReward.ConfigSchema):
"""ConfigSchema for DatabaseFileIntegrity."""
type: str = "database-file-integrity"
node_hostname: str
folder_name: str
file_name: str
type: str = "database-file-integrity"
node_hostname: str
folder_name: str
file_name: str
def calculate(self, state: Dict, last_action_response: "AgentHistoryItem") -> float:
"""Calculate the reward for the current state.
pass
def calculate(self, state: Dict, last_action_response: "AgentHistoryItem") -> float:
"""Calculate the reward for the current state.
pass
Changes to YAML file.
=====================
.. code:: YAML
There's no longer a need to provide a `dns_server` as an option in the simulation section
of the config file.

View File

@@ -33,7 +33,7 @@ However, a few more options have been introduced:
sys_log_level: WARNING
agent_log_level: INFO
More information can be found in the detailed in the configuration page: :ref:`_io_settings`.
More information can be found in the detailed in the configuration page: :ref:`io_settings`.
``game``
========

View File

@@ -2,6 +2,8 @@
© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
.. _Rewards:
Rewards
#######