@@ -83,7 +83,7 @@ class StepId:
8383@dataclass
8484class Info :
8585 results_dir : Path = None # to root directory of all experiments
86- exp_list_dir : Path = None # the path of the currently selected experiment
86+ study_dirs : Path = None # the path of the currently selected experiment
8787 result_df : pd .DataFrame = None # the raw loaded df
8888 agent_df : pd .DataFrame = None # the df filtered for selected agent
8989 tasks_df : pd .DataFrame = None # the unique tasks for selected agent
@@ -178,6 +178,8 @@ def run_gradio(results_dir: Path):
178178 agent_task_id = gr .State (value = None )
179179 step_id = gr .State (value = None )
180180
181+ hidden_key_input = gr .Textbox (visible = False , elem_id = "key_capture" )
182+
181183 with gr .Accordion ("Help" , open = False ):
182184 gr .Markdown (
183185 """\
@@ -207,6 +209,7 @@ def run_gradio(results_dir: Path):
207209 exp_dir_choice = gr .Dropdown (
208210 choices = get_directory_contents (results_dir ),
209211 value = select_dir_instructions ,
212+ multiselect = True ,
210213 label = "Experiment Directory" ,
211214 show_label = False ,
212215 scale = 6 ,
@@ -502,6 +505,32 @@ def run_gradio(results_dir: Path):
502505
503506 demo .load (fn = refresh_exp_dir_choices , inputs = exp_dir_choice , outputs = exp_dir_choice )
504507
508+ demo .load (
509+ None ,
510+ None ,
511+ None ,
512+ js = """
513+ function() {
514+ document.addEventListener('keydown', function(e) {
515+ if ((e.key === 'ArrowLeft' || e.key === 'ArrowRight') && (e.metaKey || e.ctrlKey)) {
516+ e.preventDefault();
517+ const hiddenInput = document.querySelector('#key_capture input, #key_capture textarea');
518+ if (hiddenInput) {
519+ let event = e.key === 'ArrowLeft' ? 'Cmd+Left' : 'Cmd+Right';
520+ hiddenInput.value = event;
521+ hiddenInput.dispatchEvent(new Event('input', {bubbles: true}));
522+ }
523+ }
524+ });
525+ }
526+ """ ,
527+ )
528+ hidden_key_input .change (
529+ handle_key_event ,
530+ inputs = [hidden_key_input , step_id ],
531+ outputs = [hidden_key_input , step_id ],
532+ )
533+
505534 demo .queue ()
506535
507536 do_share = os .getenv ("AGENTXRAY_SHARE_GRADIO" , "false" ).lower () == "true"
@@ -511,6 +540,25 @@ def run_gradio(results_dir: Path):
511540 demo .launch (server_port = port , share = do_share )
512541
513542
543+ def handle_key_event (key_event , step_id : StepId ):
544+
545+ if key_event :
546+ global info
547+
548+ # print(f"Key event: {key_event}")
549+ step = step_id .step
550+ if key_event .startswith ("Cmd+Left" ):
551+ step = max (0 , step - 1 )
552+ elif key_event .startswith ("Cmd+Right" ):
553+ step = min (len (info .exp_result .steps_info ) - 2 , step + 1 )
554+ else :
555+ return gr .update ()
556+ # print(f"Updating step to {step} from key event {key_event}")
557+ info .step = step
558+ step_id = StepId (episode_id = step_id .episode_id , step = step )
559+ return ("" , step_id )
560+
561+
514562def tab_select (evt : gr .SelectData ):
515563 global info
516564 info .active_tab = evt .value
@@ -546,8 +594,8 @@ def get_screenshot(
546594):
547595 if step is None :
548596 step = info .step
549- step_info = info .exp_result .steps_info [step ]
550597 try :
598+ step_info = info .exp_result .steps_info [step ]
551599 is_som = som_or_not == "SOM Screenshots"
552600 img = info .exp_result .get_screenshot (step , som = is_som )
553601 if annotate :
@@ -557,7 +605,7 @@ def get_screenshot(
557605 else :
558606 action_colored = None
559607 return img , action_colored
560- except FileNotFoundError :
608+ except ( FileNotFoundError , IndexError ) :
561609 return None , None
562610
563611
@@ -839,6 +887,10 @@ def get_episode_info(info: Info):
839887 try :
840888 env_args = info .exp_result .exp_args .env_args
841889 steps_info = info .exp_result .steps_info
890+ if info .step >= len (steps_info ):
891+ info .step = len (steps_info ) - 1
892+ if len (steps_info ) == 0 :
893+ return "No steps were taken in this episode."
842894 step_info = steps_info [info .step ]
843895 try :
844896 goal = step_info .obs ["goal_object" ]
@@ -1040,31 +1092,29 @@ def update_global_stats():
10401092
10411093
10421094def update_error_report ():
1043- report_files = list (info .exp_list_dir .glob ("error_report*.md" ))
1044- if len (report_files ) == 0 :
1045- return "No error report found"
1046- report_files = sorted (report_files , key = os .path .getctime , reverse = True )
1047- return report_files [0 ].read_text ()
1095+ return inspect_results .error_report (info .result_df , max_stack_trace = 3 , use_log = True )
10481096
10491097
1050- def new_exp_dir (exp_dir , progress = gr .Progress (), just_refresh = False ):
1051- if exp_dir == select_dir_instructions :
1052- return None , None
1098+ def new_exp_dir (study_names : list , progress = gr .Progress (), just_refresh = False ):
1099+ global info
10531100
1054- exp_dir = exp_dir .split (" - " )[0 ]
1101+ # remove select_dir_instructions from study_names
1102+ if select_dir_instructions in study_names :
1103+ study_names .remove (select_dir_instructions )
10551104
1056- if len (exp_dir ) == 0 :
1057- info .exp_list_dir = None
1105+ if len (study_names ) == 0 :
10581106 return None , None
10591107
1060- info .exp_list_dir = info .results_dir / exp_dir
1061- info .result_df = inspect_results .load_result_df (info .exp_list_dir , progress_fn = progress .tqdm )
1108+ info .study_dirs = [ info .results_dir / study_name . split ( " - " )[ 0 ] for study_name in study_names ]
1109+ info .result_df = inspect_results .load_result_df (info .study_dirs , progress_fn = progress .tqdm )
10621110 info .result_df = remove_args_from_col (info .result_df )
10631111
10641112 study_summary = inspect_results .summarize_study (info .result_df )
10651113 # save study_summary
1066- study_summary .to_csv (info .exp_list_dir / "summary_df.csv" , index = False )
1067- agent_report = display_table (study_summary )
1114+
1115+ for study_dir in info .study_dirs :
1116+ study_summary .to_csv (study_dir / "summary_df.csv" , index = False )
1117+ agent_report = display_table (study_summary )
10681118
10691119 info .agent_id_keys = agent_report .index .names
10701120 agent_report .reset_index (inplace = True )
0 commit comments