88from llama_index .core .workflow import (
99 Context ,
1010 Event ,
11+ HumanResponseEvent ,
12+ InputRequiredEvent ,
1113 StartEvent ,
1214 StopEvent ,
1315 Workflow ,
4244uipath = UiPath ()
4345
4446class CustomStartEvent (StartEvent ):
45- query : str
46- add_data_to_index : bool
47+ query : str = ""
48+ add_data_to_index : bool = False
4749
4850
4951class QueryEvent (Event ):
@@ -66,6 +68,12 @@ class AgentAnswerEvent(Event):
6668 agent_answer : str
6769
6870
71+ class FormattedAnswerEvent (Event ):
72+ """Event containing the formatted answer awaiting human confirmation."""
73+ formatted_answer : str
74+ iteration_count : int
75+
76+
6977class OutputEvent (StopEvent ):
7078 """Event representing the final, formatted output."""
7179 output : str
@@ -154,6 +162,8 @@ async def workflow_entrypoint(
154162 self , ctx : Context , ev : CustomStartEvent
155163 ) -> QueryEvent | AddDataToIndexEvent :
156164 await ctx .store .set ("original_query" , ev .query )
165+ await ctx .store .set ("iteration_count" , 0 )
166+ await ctx .store .set ("feedback_history" , [])
157167
158168 if ev .add_data_to_index :
159169 return AddDataToIndexEvent ()
@@ -322,13 +332,22 @@ async def process_query(
322332 @step
323333 async def format_final_answer (
324334 self , ctx : Context , ev : AgentAnswerEvent
325- ) -> OutputEvent :
335+ ) -> FormattedAnswerEvent :
326336 """
327337 Takes the ReAct Agent's raw answer and formats it into the final structure.
328338 """
329339 original_query = await ctx .store .get ("original_query" )
340+ iteration_count = await ctx .store .get ("iteration_count" )
341+ feedback_history = await ctx .store .get ("feedback_history" , [])
330342 agent_answer = ev .agent_answer
331343
344+ feedback_context = ""
345+ if feedback_history :
346+ feedback_context = "\n \n Previous feedback from the user:\n "
347+ for i , feedback in enumerate (feedback_history , 1 ):
348+ feedback_context += f"{ i } . { feedback } \n "
349+ feedback_context += "\n Please address the feedback above in your reformatted answer.\n "
350+
332351 prompt = f"""
333352 You are a final synthesis engine. You are given the user's original query and
334353 a comprehensive answer generated by an intelligent multi-tool agent.
@@ -352,6 +371,7 @@ async def format_final_answer(
352371 If applicable, suggest actionable items or state relevant policies.
353372
354373 Original query: { original_query }
374+ { feedback_context }
355375
356376 Agent's Comprehensive Answer to be Formatted:
357377 ---
@@ -364,10 +384,59 @@ async def format_final_answer(
364384
365385 print ("Final formatting complete." )
366386
367- return OutputEvent (
368- output = response .text ,
387+ return FormattedAnswerEvent (
388+ formatted_answer = response .text ,
389+ iteration_count = iteration_count
390+ )
391+
392+ @step
393+ async def request_human_confirmation (
394+ self , ctx : Context , ev : FormattedAnswerEvent
395+ ) -> OutputEvent | QueryEvent :
396+ """
397+ Present the formatted answer to the user and request confirmation.
398+ """
399+ await ctx .store .set ("last_formatted_answer" , ev .formatted_answer )
400+
401+ print ("\n " + "=" * 80 )
402+ print ("FORMATTED ANSWER:" )
403+ print ("=" * 80 )
404+ print (ev .formatted_answer )
405+ print ("=" * 80 )
406+
407+ ctx .write_event_to_stream (
408+ InputRequiredEvent (
409+ prefix = "\n Is this answer satisfactory? (yes/no or provide feedback): "
410+ )
369411 )
370412
413+ response = await ctx .wait_for_event (HumanResponseEvent )
414+ feedback = response .response .strip ().lower ()
415+
416+ print (f"Received response: { feedback } " )
417+
418+ if feedback == "yes" :
419+ print ("\n Answer approved by user." )
420+ return OutputEvent (output = ev .formatted_answer )
421+
422+ max_iterations = 3
423+ iteration_count = ev .iteration_count
424+
425+ if iteration_count >= max_iterations :
426+ print (f"\n Maximum iterations ({ max_iterations } ) reached." )
427+ return OutputEvent (
428+ output = f"{ ev .formatted_answer } \n \n ---\n Note: Maximum iteration limit reached. Please refine your query or requirements."
429+ )
430+
431+ feedback_history = await ctx .store .get ("feedback_history" , [])
432+ feedback_history .append (feedback )
433+ await ctx .store .set ("feedback_history" , feedback_history )
434+ await ctx .store .set ("iteration_count" , iteration_count + 1 )
435+
436+ print (f"\n Feedback received: '{ feedback } '. Re-querying (iteration { iteration_count + 1 } )..." )
437+
438+ return QueryEvent ()
439+
371440
372441agent = AgentWorkflow (timeout = 600 , verbose = True )
373442
0 commit comments