Skip to content

Fact retraction and cascading feature #59

@segfly

Description

@segfly

Is your feature request related to a problem? Please describe.
In some cases, inverting the value of the fact is not desired as it may trigger evaluation of dependent rules that should be skipped.

engine.rule(
    when=~condition(lambda: Analysis.passed),
    then=action(AnalysisResultsPassed()),
    inverse=action(AnalysisResultsPassed(value=False)),
)

In the above case, even though dependent rules may not fire their actions if value=False, it is better to not evaluate the rules at all, especially in the case of LLM rules.

The reason why inverse can't be simply omitted, is for the need to "undo" previous actions if the rule condition evaluation changed due to working memory state change.

Describe the solution you'd like
We may need a mechanism to retract Facts. E.g.:

engine.rule(
    when=~condition(lambda: Analysis.passed),
    then=action(AnalysisResultsPassed()),
    inverse=retract(AnalysisResultsPassed),
)

Here, retract can take a single or list of Fact types, where the fact AnalysisResultsPassed would be removed from the working memory, both indicating that the condition is no longer meant (due to the naming of the Fact) and preventing any dependent rules from having their conditions evaluated.

This may need further consideration for some use cases, such as cascading fact retractions:

engine.rule(
    when=~condition(lambda: Analysis.passed),
    then=action(AnalysisResultsPassed()),
    inverse=retract(AnalysisResultsPassed),
)

engine.rule(
    when=~condition(lambda: AnalysisResultsPassed.value),
    then=action(SomeOtherFact()),
    on_retract=retract(SomeOtherFact),
)

engine.rule(
    when=~condition(lambda: SomeOtherFact.value),
    then=action(YetAnotherFact()),
    on_retract=action(YetAnotherFact(value=False)),
)

Without a mechanism for cascading retract information to dependent rules, it is possible to create a fragmented and inconsistent knowledge graph, where some values from previous evaluations are no longer consistent with parent Fact because no rules were fired to "cleanup" on retraction. Allowing a on_retract trigger or similar allows for explicit cleanup behavior.

All this being said, it may also be possible to automate fact retraction and retraction cascading by setting a set of semantics and introspecting the actions for the modified/inserted Facts. The decision regarding either an explicit, implied, or combined approach needs further design consideration.

Describe alternatives you've considered
Simply not adding an inverse action, but in some cases this means that a new rules engine instance needs to be created for evaluation to ensure a clean state.

Additional context
None

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions