-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathretry_loop.py
More file actions
84 lines (62 loc) · 2.79 KB
/
Copy pathretry_loop.py
File metadata and controls
84 lines (62 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
"""A deterministic failed action whose feedback changes the next decision."""
from __future__ import annotations
if __package__:
from ._bootstrap import persist_and_print_summary
else:
from _bootstrap import prepare_script_imports, persist_and_print_summary
prepare_script_imports(__file__)
from loop_engineering.actions import Action, ActionResult, NumericAction
from loop_engineering.evaluators import Evaluation, Evaluator, GoalEvaluator
from loop_engineering.models import Feedback, LoopState, LoopTrace
from loop_engineering.policies import Decision, Policy
from loop_engineering.runner import LoopRunner
from loop_engineering.stopping import MaxSteps, SuccessReached
class FailOnceAction(Action):
"""Fail the first action without changing the value, then increment normally."""
def __init__(self) -> None:
self._has_failed = False
self._numeric_action = NumericAction()
def apply(self, state: LoopState, decision: Decision) -> ActionResult:
if not self._has_failed:
self._has_failed = True
return ActionResult(
state=state.with_value(state.value, injected_failure=True),
success=False,
cost=0.0,
)
return self._numeric_action.apply(state, decision)
class RetryAwareEvaluator(Evaluator):
"""Convert the injected failure into feedback a policy can act upon."""
def __init__(self) -> None:
self._goal_evaluator = GoalEvaluator(tolerance=0.0)
def evaluate(self, before: LoopState, result: ActionResult) -> Evaluation:
if not result.success:
return Evaluation(
score=0.0,
success=False,
message="Injected action failure; retry with a larger increment",
signals={"retry_required": 1.0},
)
return self._goal_evaluator.evaluate(before, result)
class FeedbackRetryPolicy(Policy):
"""Use retry feedback to select a larger second action."""
def decide(self, state: LoopState, feedback: Feedback) -> Decision:
amount = 2.0 if feedback.signals.get("retry_required") else 1.0
return Decision(
name="increment",
parameters={"amount": min(amount, max(state.goal - state.value, 0.0))},
)
def run() -> LoopTrace:
"""Run one injected failure followed by feedback-driven recovery."""
runner = LoopRunner(
policy=FeedbackRetryPolicy(),
action=FailOnceAction(),
evaluator=RetryAwareEvaluator(),
stop_conditions=[SuccessReached(), MaxSteps(4)],
)
return runner.run(LoopState(step=0, value=0.0, goal=3.0))
def main() -> None:
"""Print the completed trace summary for command-line exploration."""
persist_and_print_summary(run(), __file__)
if __name__ == "__main__":
main()