What is the problem?
Setting the system instructions for Agent involves a lot of logic (e.g: ANES, personas, templates) that should be factored out out from the main class. Agent should ideally be limited to only the logic for processing tasks. Also, this refactor will make things more future-proof when adding other initialization methods.
What is the high-level solution?
Implement a Strategy pattern.
class Agent:
def __init__(self,
task: Optional[str] = None,
combination_instructions: Optional[str] = None,
ideology: Optional[str] = None,
query_str: Optional[str] = None,
model: str = "gpt-4o",
system_instructions: Optional[str] = None,
persona_template: Optional[str] = None,
persona: Optional[str] = None,
kwargs: Optional[Dict[str, Any]] = None):
# ... blah blah blah
# get strategy
self.system_instruction_strategy = self._get_system_instruction_strategy()
# use strategy
self._set_system_instructions()
def _get_system_instruction_strategy(self):
if self.system_instructions is not None:
return DirectSystemInstructionStrategy()
elif not self.system_instructions and not self.persona and not self.ideology and not self.query_str:
return DefaultSystemInstructionStrategy()
else:
return PersonaBasedSystemInstructionStrategy()
def _set_system_instructions(self):
self.system_instruction_strategy.set_system_instructions(self)
How the strategy class is set up
from abc import ABC, abstractmethod
class SystemInstructionStrategy(ABC):
@abstractmethod
def set_system_instructions(self, agent):
pass
# write over w/ concrete strategies
class DefaultSystemInstructionStrategy(SystemInstructionStrategy):
def set_system_instructions(self, agent):
# implement
class DirectSystemInstructionStrategy(SystemInstructionStrategy):
def set_system_instructions(self, agent):
# implement
class PersonaBasedSystemInstructionStrategy(SystemInstructionStrategy):
def set_system_instructions(self, agent):
# this will implement all the persona logic
The most involved will definitely be PersonaBasedSystemInstructionStrategy.
One judgment call is whether PersonaBasedSystemInstructionStrategy(SystemInstructionStrategy) should have child classes of its own, since I am just imagining ANES is one dataset but when we add another dataset later on.
Test implications
We have a bunch of Aget initialization tests and these can stay, but we also want tests where we test whether Agent chose the correct strategy based on initialization.
Summing up
[ ] Break off Agent system instruction logic into its own class
[ ] Make sure Agent gets the correct strategy when it is initialized
[ ] Update tests to verify Agent is getting the right strategy
What is the problem? Setting the system instructions for Agent involves a lot of logic (e.g: ANES, personas, templates) that should be factored out out from the main class.
Agent
should ideally be limited to only the logic for processing tasks. Also, this refactor will make things more future-proof when adding other initialization methods.What is the high-level solution? Implement a
Strategy
pattern.Agent
classSystemInstructionsStrategy
classAgent
nowHere is a good link on this design pattern (https://refactoring.guru/design-patterns/strategy)
Low-level details
How this looks in Agent
How the strategy class is set up
The most involved will definitely be
PersonaBasedSystemInstructionStrategy
.One judgment call is whether
PersonaBasedSystemInstructionStrategy(SystemInstructionStrategy)
should have child classes of its own, since I am just imagining ANES is one dataset but when we add another dataset later on.Test implications
We have a bunch of Aget initialization tests and these can stay, but we also want tests where we test whether Agent chose the correct strategy based on initialization.
Summing up