#2869 - initial creation of how to section for the new extendable agents.
This commit is contained in:
@@ -5,6 +5,13 @@ 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/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [4.0.0] = TBC
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
- Agents now follow a common configuration format, simplifying the configuration of agents and their extensibilty.
|
||||
|
||||
## [3.3.0] - 2024-09-04
|
||||
|
||||
### Added
|
||||
|
||||
73
docs/source/how_to_guides/extensible_agents.rst
Normal file
73
docs/source/how_to_guides/extensible_agents.rst
Normal file
@@ -0,0 +1,73 @@
|
||||
.. only:: comment
|
||||
|
||||
© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||
|
||||
.. _about:
|
||||
|
||||
Extensible Agents
|
||||
*****************
|
||||
|
||||
Agents defined within PrimAITE have been updated to allow for easier creation of new bespoke agents.
|
||||
|
||||
|
||||
Developing Agents for PrimAITE
|
||||
==============================
|
||||
|
||||
Agents within PrimAITE, follow the shown inheritance structure, and
|
||||
|
||||
# TODO: Turn this into an inheritance diagram
|
||||
|
||||
AbstractAgent
|
||||
|
|
||||
| - AbstractScriptedAgent
|
||||
| |
|
||||
| | - AbstractTAPAgent
|
||||
| | |
|
||||
| | | - DataManipulationAgent
|
||||
| |
|
||||
| |
|
||||
| | - RandomAgent
|
||||
| |
|
||||
| | - PeriodicAgent
|
||||
| |
|
||||
| | - RandomAgent
|
||||
|
|
||||
|
|
||||
| - ProxyAgent
|
||||
|
|
||||
| - ControlledAgent
|
||||
|
||||
|
||||
#. **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*.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class ExampleAgent(AbstractAgent, identifier = "example_agent"):
|
||||
"""An example agent for demonstration purposes."""
|
||||
|
||||
config: "ExampleAgent.ConfigSchema"
|
||||
"""Agent configuration"""
|
||||
num_executions: int
|
||||
"""Number of action executions by agent"""
|
||||
|
||||
class ConfigSchema(AbstractAgent.ConfigSchema):
|
||||
"""ExampleAgent configuration schema"""
|
||||
|
||||
agent_name: str
|
||||
"""Name of agent"""
|
||||
action_interval: int
|
||||
"""Number of steps between agent actions"""
|
||||
|
||||
#. **identifier**:
|
||||
|
||||
All agent classes should have a unique ``identifier`` attribute, for when they are added to the base ``AbstractAgent`` registry. PrimAITE notation is for these to be written in snake_case
|
||||
|
||||
Changes to YAML file
|
||||
====================
|
||||
|
||||
Agent configurations specified within YAML files used for earlier versions of PrimAITE will need updating to be compatible with PrimAITE v4.0.0+.
|
||||
|
||||
# TODO: Show changes to YAML config needed here
|
||||
@@ -30,6 +30,7 @@ class AgentLog(BaseModel):
|
||||
agent_name: str = "unnamed_agent"
|
||||
current_episode: int = 1
|
||||
current_timestep: int = 0
|
||||
logger: logging
|
||||
|
||||
def __init__(self, agent_name: Optional[str]):
|
||||
"""
|
||||
|
||||
@@ -53,16 +53,6 @@ class PeriodicAgent(AbstractScriptedAgent, identifier="Periodic_Agent"):
|
||||
next_execution_timestep: int = 0
|
||||
"""Timestep of the next action execution by the agent."""
|
||||
|
||||
@property
|
||||
def num_executions(self) -> int:
|
||||
"""Convenience method for accessing num_executions from config."""
|
||||
return self.config.num_executions
|
||||
|
||||
@property
|
||||
def next_execution_timestep(self) -> int:
|
||||
"""Convenience method for accessing next_execution_timestep from config."""
|
||||
return self.config.next_execution_timestep
|
||||
|
||||
def _set_next_execution_timestep(self, timestep: int, variance: int) -> None:
|
||||
"""Set the next execution timestep with a configured random variance.
|
||||
|
||||
@@ -78,7 +68,8 @@ class PeriodicAgent(AbstractScriptedAgent, identifier="Periodic_Agent"):
|
||||
"""Do nothing, unless the current timestep is the next execution timestep, in which case do the action."""
|
||||
if timestep == self.next_execution_timestep and self.num_executions < self.config.max_executions:
|
||||
self.num_executions += 1
|
||||
self._set_next_execution_timestep(timestep + self.config.frequency, self.config.variance)
|
||||
return "NODE_APPLICATION_EXECUTE", {"node_id": 0, "application_id": 0}
|
||||
self._set_next_execution_timestep(timestep + self.frequency, self.variance)
|
||||
self.target_node = self.action_manager.node_names[0]
|
||||
return "node_application_execute", {"node_name": self.target_node, "application_name": 0}
|
||||
|
||||
return "DONOTHING", {}
|
||||
|
||||
Reference in New Issue
Block a user