GuglielmoTor commited on
Commit
1cbff0c
·
verified ·
1 Parent(s): 27a3988

Create agentic_module.py

Browse files
Files changed (1) hide show
  1. ui/agentic_module.py +222 -0
ui/agentic_module.py ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ui/agentic_module.py
2
+ import gradio as gr
3
+ import logging
4
+ from collections import defaultdict
5
+
6
+ # --- Module Imports ---
7
+ try:
8
+ from run_agentic_pipeline import run_full_analytics_orchestration
9
+ from ui.insights_ui_generator import (
10
+ format_report_to_markdown,
11
+ extract_key_results_for_selection,
12
+ format_single_okr_for_display
13
+ )
14
+ AGENTIC_MODULES_LOADED = True
15
+ except ImportError as e:
16
+ logging.error(f"Could not import agentic pipeline modules in agentic_module.py: {e}.")
17
+ AGENTIC_MODULES_LOADED = False
18
+ async def run_full_analytics_orchestration(*args, **kwargs): return None
19
+ def format_report_to_markdown(report_string): return "Agentic modules not loaded. Report unavailable."
20
+ def extract_key_results_for_selection(okrs_dict): return []
21
+ def format_single_okr_for_display(okr_data, **kwargs): return "Agentic modules not loaded. OKR display unavailable."
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+ # Store references to UI components that handlers need to update
26
+ _agentic_report_display_md = None
27
+ _key_results_cbg = None
28
+ _okr_detail_display_md = None
29
+ _agentic_pipeline_status_md = None
30
+
31
+
32
+ def handle_update_okr_display(selected_kr_unique_ids: list, raw_orchestration_results: dict, all_krs_for_selection: list):
33
+ if not raw_orchestration_results or not AGENTIC_MODULES_LOADED:
34
+ return gr.update(value="Nessun dato dalla pipeline AI o moduli non caricati.")
35
+
36
+ actionable_okrs_dict = raw_orchestration_results.get("actionable_okrs_and_tasks")
37
+ if not actionable_okrs_dict or not isinstance(actionable_okrs_dict.get("okrs"), list):
38
+ return gr.update(value="Nessun OKR trovato nei risultati della pipeline.")
39
+
40
+ okrs_list = actionable_okrs_dict["okrs"]
41
+ # Rebuild kr_id_to_indices based on the structure of all_krs_for_selection
42
+ # all_krs_for_selection is: [{'okr_index': int, 'kr_index': int, 'unique_kr_id': str, ...}]
43
+ kr_id_to_indices = {kr_info['unique_kr_id']: (kr_info['okr_index'], kr_info['kr_index'])
44
+ for kr_info in all_krs_for_selection if isinstance(kr_info, dict) and 'unique_kr_id' in kr_info}
45
+
46
+ selected_krs_by_okr_idx = defaultdict(list)
47
+ if selected_kr_unique_ids:
48
+ for kr_unique_id in selected_kr_unique_ids:
49
+ if kr_unique_id in kr_id_to_indices:
50
+ okr_idx, kr_idx = kr_id_to_indices[kr_unique_id]
51
+ selected_krs_by_okr_idx[okr_idx].append(kr_idx)
52
+ else:
53
+ logger.warning(f"Selected KR ID '{kr_unique_id}' not found in kr_id_to_indices map.")
54
+
55
+
56
+ output_md_parts = []
57
+ if not okrs_list:
58
+ output_md_parts.append("Nessun OKR generato.")
59
+ else:
60
+ for okr_idx, okr_data in enumerate(okrs_list):
61
+ accepted_indices_for_this_okr = selected_krs_by_okr_idx.get(okr_idx)
62
+ # If specific KRs are selected, only show OKRs that have at least one of those selected KRs
63
+ if selected_kr_unique_ids: # User has made a selection
64
+ if accepted_indices_for_this_okr is not None: # This OKR has some selected KRs
65
+ output_md_parts.append(format_single_okr_for_display(okr_data, accepted_kr_indices=accepted_indices_for_this_okr, okr_main_index=okr_idx))
66
+ else: # No KRs selected, show all OKRs with all their KRs
67
+ output_md_parts.append(format_single_okr_for_display(okr_data, accepted_kr_indices=None, okr_main_index=okr_idx))
68
+
69
+ if not output_md_parts and selected_kr_unique_ids:
70
+ final_md = "Nessun OKR corrisponde alla selezione corrente o i KR selezionati non hanno task dettagliati."
71
+ elif not output_md_parts and not selected_kr_unique_ids and okrs_list : # OKRs exist but somehow didn't format
72
+ final_md = "Nessun OKR da visualizzare in base alla selezione (o tutti OKR visualizzati)."
73
+ elif not output_md_parts and not okrs_list:
74
+ final_md = "Nessun OKR generato."
75
+ else:
76
+ final_md = "\n\n---\n\n".join(output_md_parts)
77
+
78
+ return gr.update(value=final_md)
79
+
80
+
81
+ async def handle_run_agentic_pipeline(current_token_state_val, orchestration_raw_results_st_val, key_results_for_selection_st_val, selected_key_result_ids_st_val):
82
+ logger.info(f"Agentic pipeline check triggered. Current token: {'Set' if current_token_state_val.get('token') else 'Not Set'}")
83
+
84
+ if not current_token_state_val or not current_token_state_val.get("token"):
85
+ logger.info("Agentic pipeline: Token not available in token_state. Skipping.")
86
+ yield (
87
+ gr.update(value="Pipeline AI: In attesa dei dati necessari..."), # report_display
88
+ gr.update(choices=[], value=[], interactive=False), # key_results_cbg
89
+ gr.update(value="Pipeline AI: In attesa dei dati necessari..."), # okr_detail_display
90
+ None, # orchestration_raw_results_st
91
+ [], # selected_key_result_ids_st
92
+ [], # key_results_for_selection_st
93
+ "Pipeline AI: In attesa dei dati..." # agentic_pipeline_status_md
94
+ )
95
+ return
96
+
97
+ logger.info("Agentic pipeline starting autonomously with 'Sempre' filter.")
98
+ yield (
99
+ gr.update(value="Analisi AI (Sempre) in corso..."),
100
+ gr.update(choices=[], value=[], interactive=False),
101
+ gr.update(value="Dettagli OKR (Sempre) in corso di generazione..."),
102
+ orchestration_raw_results_st_val, # Preserve existing results
103
+ selected_key_result_ids_st_val,
104
+ key_results_for_selection_st_val,
105
+ "Esecuzione pipeline AI (Sempre)..."
106
+ )
107
+
108
+ if not AGENTIC_MODULES_LOADED:
109
+ logger.warning("Agentic modules not loaded. Skipping autonomous pipeline.")
110
+ yield (
111
+ gr.update(value="Moduli AI non caricati. Report non disponibile."),
112
+ gr.update(choices=[], value=[], interactive=False),
113
+ gr.update(value="Moduli AI non caricati. OKR non disponibili."),
114
+ None, [], [], "Pipeline AI: Moduli non caricati."
115
+ )
116
+ return
117
+
118
+ try:
119
+ date_filter_val_agentic = "Sempre"
120
+ custom_start_val_agentic = None
121
+ custom_end_val_agentic = None
122
+
123
+ orchestration_output = await run_full_analytics_orchestration(
124
+ current_token_state_val, date_filter_val_agentic,
125
+ custom_start_val_agentic, custom_end_val_agentic
126
+ )
127
+ agentic_status_text = "Pipeline AI (Sempre) completata."
128
+ logger.info(f"Autonomous agentic pipeline finished. Output keys: {orchestration_output.keys() if orchestration_output else 'None'}")
129
+
130
+ if orchestration_output:
131
+ orchestration_results_update = orchestration_output
132
+ report_str = orchestration_output.get('comprehensive_analysis_report')
133
+ agentic_report_md_update = gr.update(value=format_report_to_markdown(report_str))
134
+
135
+ actionable_okrs = orchestration_output.get('actionable_okrs_and_tasks')
136
+ krs_for_ui_selection_list = extract_key_results_for_selection(actionable_okrs)
137
+ krs_for_selection_update = krs_for_ui_selection_list # This is the list of dicts for the state
138
+
139
+ kr_choices_for_cbg = [(kr['kr_description'], kr['unique_kr_id']) for kr in krs_for_ui_selection_list if isinstance(kr, dict)]
140
+ key_results_cbg_update = gr.update(choices=kr_choices_for_cbg, value=[], interactive=True)
141
+
142
+ # Default display for OKRs: show all, as if no KR is selected yet.
143
+ all_okrs_md_parts = []
144
+ if actionable_okrs and isinstance(actionable_okrs.get("okrs"), list):
145
+ for okr_idx, okr_item in enumerate(actionable_okrs["okrs"]):
146
+ all_okrs_md_parts.append(format_single_okr_for_display(okr_item, accepted_kr_indices=None, okr_main_index=okr_idx))
147
+
148
+ if not all_okrs_md_parts:
149
+ okr_detail_display_md_update = gr.update(value="Nessun OKR generato o trovato (Sempre).")
150
+ else:
151
+ okr_detail_display_md_update = gr.update(value="\n\n---\n\n".join(all_okrs_md_parts))
152
+
153
+ selected_krs_update = [] # Reset selection
154
+ else:
155
+ agentic_report_md_update = gr.update(value="Nessun report generato dalla pipeline AI (Sempre).")
156
+ key_results_cbg_update = gr.update(choices=[], value=[], interactive=False)
157
+ okr_detail_display_md_update = gr.update(value="Nessun OKR generato o errore nella pipeline AI (Sempre).")
158
+ orchestration_results_update = None
159
+ selected_krs_update = []
160
+ krs_for_selection_update = []
161
+
162
+ yield (agentic_report_md_update, key_results_cbg_update, okr_detail_display_md_update,
163
+ orchestration_results_update, selected_krs_update, krs_for_selection_update, agentic_status_text)
164
+
165
+ except Exception as e:
166
+ logger.error(f"Error during autonomous agentic pipeline execution: {e}", exc_info=True)
167
+ agentic_status_text = f"Errore pipeline AI (Sempre): {str(e)}"
168
+ yield (
169
+ gr.update(value=f"Errore generazione report AI (Sempre): {str(e)}"),
170
+ gr.update(choices=[], value=[], interactive=False),
171
+ gr.update(value=f"Errore generazione OKR AI (Sempre): {str(e)}"),
172
+ None, [], [], agentic_status_text
173
+ )
174
+
175
+
176
+ def build_and_wire_tabs(orchestration_raw_results_st, key_results_for_selection_st, selected_key_result_ids_st):
177
+ """Builds the UI for Agentic Tabs and wires up internal event handlers."""
178
+ global _agentic_report_display_md, _key_results_cbg, _okr_detail_display_md, _agentic_pipeline_status_md
179
+
180
+ with gr.TabItem("3️⃣ Agentic Analysis Report", id="tab_agentic_report", visible=AGENTIC_MODULES_LOADED):
181
+ gr.Markdown("## 🤖 Comprehensive Analysis Report (AI Generated)")
182
+ _agentic_pipeline_status_md = gr.Markdown("Stato Pipeline AI (filtro 'Sempre'): In attesa...", visible=True)
183
+ gr.Markdown("Questo report è generato da un agente AI con filtro 'Sempre' sui dati disponibili. Rivedi criticamente.")
184
+ _agentic_report_display_md = gr.Markdown("La pipeline AI si avvierà automaticamente dopo il caricamento iniziale dei dati o dopo una sincronizzazione.")
185
+ if not AGENTIC_MODULES_LOADED:
186
+ gr.Markdown("🔴 **Error:** Agentic pipeline modules could not be loaded. This tab is disabled.")
187
+
188
+ with gr.TabItem("4️⃣ Agentic OKRs & Tasks", id="tab_agentic_okrs", visible=AGENTIC_MODULES_LOADED):
189
+ gr.Markdown("## 🎯 AI Generated OKRs and Actionable Tasks (filtro 'Sempre')")
190
+ gr.Markdown("Basato sull'analisi AI (filtro 'Sempre'), l'agente ha proposto i seguenti OKR e task. Seleziona i Key Results per dettagli.")
191
+ if not AGENTIC_MODULES_LOADED:
192
+ gr.Markdown("🔴 **Error:** Agentic pipeline modules could not be loaded. This tab is disabled.")
193
+
194
+ with gr.Row():
195
+ with gr.Column(scale=1):
196
+ gr.Markdown("### Suggested Key Results (da analisi 'Sempre')")
197
+ _key_results_cbg = gr.CheckboxGroup(label="Select Key Results", choices=[], value=[], interactive=True)
198
+ with gr.Column(scale=3):
199
+ gr.Markdown("### Detailed OKRs and Tasks for Selected Key Results")
200
+ _okr_detail_display_md = gr.Markdown("I dettagli OKR appariranno qui dopo l'esecuzione della pipeline AI.")
201
+
202
+ if AGENTIC_MODULES_LOADED:
203
+ _key_results_cbg.change(
204
+ fn=handle_update_okr_display, # This handler now correctly returns gr.update()
205
+ inputs=[_key_results_cbg, orchestration_raw_results_st, key_results_for_selection_st],
206
+ outputs=[_okr_detail_display_md]
207
+ )
208
+
209
+ # Components to be updated by handle_run_agentic_pipeline
210
+ # Order must match the yield tuple in handle_run_agentic_pipeline
211
+ agentic_pipeline_outputs_components = [
212
+ _agentic_report_display_md,
213
+ _key_results_cbg,
214
+ _okr_detail_display_md,
215
+ # orchestration_raw_results_st, # State
216
+ # selected_key_result_ids_st, # State
217
+ # key_results_for_selection_st, # State
218
+ _agentic_pipeline_status_md
219
+ ]
220
+
221
+ return agentic_pipeline_outputs_components
222
+