Spaces:
Runtime error
Runtime error
from typing import Union, List | |
from tinytroupe.extraction import logger | |
from tinytroupe.utils import JsonSerializableRegistry | |
from tinytroupe.experimentation import Proposition | |
from tinytroupe.environment import TinyWorld | |
from tinytroupe.agent import TinyPerson | |
import tinytroupe.utils as utils | |
# TODO under development | |
class Intervention: | |
def __init__(self, targets: Union[TinyPerson, TinyWorld, List[TinyPerson], List[TinyWorld]], | |
first_n:int=None, last_n:int=5, | |
name: str = None): | |
""" | |
Initialize the intervention. | |
Args: | |
target (Union[TinyPerson, TinyWorld, List[TinyPerson], List[TinyWorld]]): the target to intervene on | |
first_n (int): the number of first interactions to consider in the context | |
last_n (int): the number of last interactions (most recent) to consider in the context | |
name (str): the name of the intervention | |
""" | |
self.targets = targets | |
# initialize the possible preconditions | |
self.text_precondition = None | |
self.precondition_func = None | |
# effects | |
self.effect_func = None | |
# which events to pay attention to? | |
self.first_n = first_n | |
self.last_n = last_n | |
# name | |
if name is None: | |
self.name = self.name = f"Intervention {utils.fresh_id()}" | |
else: | |
self.name = name | |
# the most recent precondition proposition used to check the precondition | |
self._last_text_precondition_proposition = None | |
self._last_functional_precondition_check = None | |
################################################################################################ | |
# Intervention flow | |
################################################################################################ | |
def __call__(self): | |
""" | |
Execute the intervention. | |
Returns: | |
bool: whether the intervention effect was applied. | |
""" | |
return self.execute() | |
def execute(self): | |
""" | |
Execute the intervention. It first checks the precondition, and if it is met, applies the effect. | |
This is the simplest method to run the intervention. | |
Returns: | |
bool: whether the intervention effect was applied. | |
""" | |
logger.debug(f"Executing intervention: {self}") | |
if self.check_precondition(): | |
self.apply_effect() | |
logger.debug(f"Precondition was true, intervention effect was applied.") | |
return True | |
logger.debug(f"Precondition was false, intervention effect was not applied.") | |
return False | |
def check_precondition(self): | |
""" | |
Check if the precondition for the intervention is met. | |
""" | |
self._last_text_precondition_proposition = Proposition(self.targets, self.text_precondition, first_n=self.first_n, last_n=self.last_n) | |
if self.precondition_func is not None: | |
self._last_functional_precondition_check = self.precondition_func(self.targets) | |
else: | |
self._last_functional_precondition_check = True # default to True if no functional precondition is set | |
llm_precondition_check = self._last_text_precondition_proposition.check() | |
return llm_precondition_check and self._last_functional_precondition_check | |
def apply_effect(self): | |
""" | |
Apply the intervention's effects. This won't check the precondition, | |
so it should be called after check_precondition. | |
""" | |
self.effect_func(self.targets) | |
################################################################################################ | |
# Pre and post conditions | |
################################################################################################ | |
def set_textual_precondition(self, text): | |
""" | |
Set a precondition as text, to be interpreted by a language model. | |
Args: | |
text (str): the text of the precondition | |
""" | |
self.text_precondition = text | |
return self # for chaining | |
def set_functional_precondition(self, func): | |
""" | |
Set a precondition as a function, to be evaluated by the code. | |
Args: | |
func (function): the function of the precondition. | |
Must have the a single argument, targets (either a TinyWorld or TinyPerson, or a list). Must return a boolean. | |
""" | |
self.precondition_func = func | |
return self # for chaining | |
def set_effect(self, effect_func): | |
""" | |
Set the effect of the intervention. | |
Args: | |
effect (str): the effect function of the intervention | |
""" | |
self.effect_func = effect_func | |
return self # for chaining | |
################################################################################################ | |
# Inspection | |
################################################################################################ | |
def precondition_justification(self): | |
""" | |
Get the justification for the precondition. | |
""" | |
justification = "" | |
# text precondition justification | |
if self._last_text_precondition_proposition is not None: | |
justification += f"{self._last_text_precondition_proposition.justification} (confidence = {self._last_text_precondition_proposition.confidence})\n\n" | |
# functional precondition justification | |
elif self._last_functional_precondition_check == True: | |
justification += f"Functional precondition was met.\n\n" | |
else: | |
justification += "Preconditions do not appear to be met.\n\n" | |
return justification | |