Add Human Feedback with Walk¶
AutoForm is a small, low-level library; it does not prescribe an approval UI, review queue, or feedback service. The core idea is that human feedback can be an executor policy over traced primitive equations.
Use ir.walk(...) when human feedback belongs to the executor rather than the
traced program. Tags mark which primitive equations require review; the walk
runner pauses after those equations, asks for feedback, then continues execution
with the accepted or edited output.
Concept
Mark the Review Point¶
Use tag around the primitive call that should emit a
reviewable equation:
import autoform as af
review = "human-review"
def draft_then_finalize(topic: str) -> str:
with af.tag(review):
draft = af.format("draft for {}: method A maps x to y.", topic)
return af.format("final answer:\n{}", draft)
ir = af.trace(draft_then_finalize)("topic x")
The tag is attached to equations emitted during tracing. It does not change the primitive result or execution order by itself.
Ask for Feedback¶
The feedback function can block on user input. Returning the original value accepts it; returning a different value patches what downstream equations see.
def ask_for_feedback(draft: str) -> str:
print("review output:")
print(draft)
note = input("feedback, or empty to accept: ")
if not note:
return draft
return draft + "\nhuman feedback: " + note
The pause happens at input(...). The runner decides when to call this
function.
Pause on Tagged Equations¶
The runner executes one equation at a time. When a yielded equation has the
review tag, it passes the equation output to feedback(...) before sending it
back into the generator.
def run_with_human_feedback(ir, *args, tag: str, feedback):
gen = ir.walk(*args)
ir_eqn, in_values = next(gen)
while ir_eqn is not None:
out_values = ir_eqn.bind(in_values, **ir_eqn.params)
if tag in ir_eqn.tags:
out_values = feedback(out_values)
ir_eqn, in_values = gen.send(out_values)
return in_values
The pause happens before gen.send(...). Execution continues only after the
runner sends the accepted or edited output back to the walk generator.
Run the Reviewed Program¶
Call the runner with the traced IR and the feedback function:
result = run_with_human_feedback(
ir,
"topic x",
tag=review,
feedback=ask_for_feedback,
)
print(result)
Execution resumes after run_with_human_feedback(...) sends the accepted or
edited value back to the walk generator.
Choose the Review Boundary¶
Use checkpoint and
inject when the traced function should expose named
review points. Use ir.walk(...) when the review policy belongs to a custom
runner and should stay outside the traced function.