vvillarreal-cfee commited on
Commit
41f9f93
·
verified ·
1 Parent(s): 1615826

feat: Remove auto-complete IA feature. Added CrewAI dep

Browse files
Files changed (2) hide show
  1. Pipfile +1 -0
  2. src/app.py +9 -95
Pipfile CHANGED
@@ -6,6 +6,7 @@ name = "pypi"
6
  [packages]
7
  streamlit = "~=1.50.0"
8
  google-genai = "~=1.42.0"
 
9
 
10
  [dev-packages]
11
 
 
6
  [packages]
7
  streamlit = "~=1.50.0"
8
  google-genai = "~=1.42.0"
9
+ crewai = {extras = ["tools", "google-genai"], version = "*"}
10
 
11
  [dev-packages]
12
 
src/app.py CHANGED
@@ -1,6 +1,8 @@
 
 
1
  import streamlit as st
2
  from google import genai
3
- import os
4
 
5
  # --- Interfaz de Usuario con Streamlit ---
6
  st.set_page_config(
@@ -15,87 +17,6 @@ if 'gemini_api_key' not in st.session_state:
15
 
16
  st.title("📄 Generador IA de Informes Post-Mortem")
17
 
18
- with st.expander("ℹ️ Dejar que la IA precomplete los campos", expanded=False):
19
- # --- Cuadro de texto libre para pegar el texto raw de la alerta/incidente ---
20
- if 'raw_text' not in st.session_state:
21
- st.session_state['raw_text'] = ''
22
- if 'precomplete_triggered' not in st.session_state:
23
- st.session_state['precomplete_triggered'] = False
24
-
25
- raw_text = st.text_area(
26
- "Texto de la alerta/incidente (puede pegar aquí el mensaje completo)",
27
- value=st.session_state['raw_text'],
28
- height=120,
29
- key="raw_text"
30
- )
31
-
32
- # Botón para precompletar los campos con IA
33
- precomplete = st.button("Precompletar campos con IA", icon="🧠")
34
-
35
- # --- Lógica para precompletar campos ---
36
- def precompletar_campos_con_ia(api_key, raw_text):
37
- """
38
- Llama a Gemini para analizar el texto raw y extraer los campos estructurados.
39
- """
40
- MODEL_NAME = "gemini-2.5-flash"
41
- try:
42
- client = genai.Client(api_key=api_key)
43
- except Exception as e:
44
- return {"error": f"Error al inicializar el cliente de Gemini: {e}"}
45
-
46
- system_instruction = (
47
- "Eres un especialista Incident Response en Ciberseguridad. Analiza el siguiente texto de alerta/incidente y extrae los siguientes campos en formato JSON:\n"
48
- "- tipo_alerta: Título o tipo principal del problema\n"
49
- "- sistema_afectado: Sistema, servicio o componente afectado\n"
50
- "- fecha_hora: Fecha y hora de inicio del incidente\n"
51
- "- impacto_detalle: Impacto del negocio y observaciones\n"
52
- "- acciones_tomadas: Acciones inmediatas tomadas\n"
53
- "Responde solo con el JSON, sin explicaciones ni texto adicional."
54
- )
55
- prompt_content = f"""
56
- Extrae los campos solicitados del siguiente texto de alerta/incidente:\n\n{raw_text}
57
- """
58
- try:
59
- response = client.models.generate_content(
60
- model=MODEL_NAME,
61
- contents=prompt_content,
62
- config=genai.types.GenerateContentConfig(
63
- system_instruction=system_instruction
64
- )
65
- )
66
- import json
67
- # Buscar el primer bloque JSON en la respuesta
68
- import re
69
- match = re.search(r'\{[\s\S]*\}', response.text)
70
- if match:
71
- campos = json.loads(match.group(0))
72
- return campos
73
- else:
74
- return {"error": "No se pudo extraer el JSON de la respuesta de la IA."}
75
- except Exception as e:
76
- return {"error": f"Error al analizar el texto con Gemini: {e}"}
77
-
78
- # Si el usuario presiona el botón de precompletar
79
- if precomplete:
80
- # No reasignar st.session_state['raw_text'] aquí: el widget con key 'raw_text'
81
- # ya fue instanciado arriba y Streamlit no permite modificarlo después.
82
- st.session_state['precomplete_triggered'] = True
83
- api_key = st.session_state.get('gemini_api_key')
84
- if not api_key:
85
- st.error("❌ Por favor, ingresa tu API Key de Gemini en el panel lateral (sidebar) antes de continuar.")
86
- elif not raw_text.strip():
87
- st.error("❌ Por favor, pega el texto de la alerta o incidente para analizar.")
88
- else:
89
- with st.spinner("🔎 Analizando texto y extrayendo campos con Gemini..."):
90
- resultado = precompletar_campos_con_ia(api_key, raw_text)
91
- if 'error' in resultado:
92
- st.error(resultado['error'])
93
- else:
94
- # Guardar los campos extraídos en session_state para precompletar el formulario
95
- for campo in ['tipo_alerta', 'sistema_afectado', 'fecha_hora', 'impacto_detalle', 'acciones_tomadas']:
96
- st.session_state[campo] = resultado.get(campo, '')
97
- st.success("Campos precompletados. Revisa y edita antes de generar el informe.")
98
-
99
 
100
  # --- Sidebar para la configuración de la API Key ---
101
  with st.sidebar:
@@ -171,44 +92,35 @@ def generar_post_mortem(api_key, tipo_alerta, sistema, fecha_hora, impacto, acci
171
 
172
  # --- Formulario de entrada de datos principal ---
173
  with st.form("post_mortem_form"):
174
- st.subheader("Detalles de la Incidencia")
175
  # Usar session_state para precompletar si corresponde
176
  col1, col2 = st.columns(2)
177
  with col1:
178
  tipo_alerta = st.text_input(
179
  "Tipo de Alerta / Título del Problema",
180
- value=st.session_state.get('tipo_alerta', ''),
181
  placeholder="Ej: High CPU usage en DB Server; Caída del servicio de Login",
182
- key="tipo_alerta"
183
  )
184
  sistema_afectado = st.text_input(
185
  "Sistema Afectado",
186
- value=st.session_state.get('sistema_afectado', ''),
187
  placeholder="Ej: Servidor de Base de Datos; Microservicio de Autenticación",
188
- key="sistema_afectado"
189
  )
190
  with col2:
191
  fecha_hora = st.text_input(
192
  "Fecha y Hora",
193
- value=st.session_state.get('fecha_hora', ''),
194
  placeholder="Ej: 26/Sep/2025 21:45 PM UTC-3",
195
- key="fecha_hora"
196
  )
197
- st.subheader("Descripción y Consecuencias")
198
  impacto_detalle = st.text_area(
199
  "Impacto del Negocio y Observaciones",
200
- value=st.session_state.get('impacto_detalle', ''),
201
  placeholder="Ej: Latencia elevada afectó al 20% de los usuarios.",
202
  height=150,
203
- key="impacto_detalle"
204
  )
 
205
  acciones_tomadas = st.text_area(
206
  "Acciones Tomadas (Mitigación Inmediata)",
207
- value=st.session_state.get('acciones_tomadas', ''),
208
  placeholder="Ej: Se escaló a Dev Team. Se reinició el servicio crítico.",
209
  height=150,
210
- key="acciones_tomadas"
211
  )
 
212
  # Botón de envío
213
  submitted = st.form_submit_button("🚀 Generar Informe Post-Mortem")
214
 
@@ -218,8 +130,10 @@ if submitted:
218
 
219
  if not api_key:
220
  st.error("❌ Por favor, ingresa tu API Key de Gemini en el panel lateral (sidebar) antes de continuar.")
 
221
  elif not all([tipo_alerta, sistema_afectado, fecha_hora, impacto_detalle, acciones_tomadas]):
222
  st.error("❌ Por favor, completa todos los campos del formulario para generar el informe.")
 
223
  else:
224
  with st.spinner("⏳ Generando informe técnico con Google Gemini..."):
225
  informe = generar_post_mortem(
@@ -233,7 +147,7 @@ if submitted:
233
 
234
  # Mostrar el resultado
235
  st.divider()
236
- st.subheader("✅ Informe Post-Mortem Generado")
237
  st.markdown(informe)
238
  st.download_button(
239
  label="Descargar Informe (.md)",
 
1
+ import os
2
+
3
  import streamlit as st
4
  from google import genai
5
+ from crewai import Agent, Task, Crew, Process
6
 
7
  # --- Interfaz de Usuario con Streamlit ---
8
  st.set_page_config(
 
17
 
18
  st.title("📄 Generador IA de Informes Post-Mortem")
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  # --- Sidebar para la configuración de la API Key ---
22
  with st.sidebar:
 
92
 
93
  # --- Formulario de entrada de datos principal ---
94
  with st.form("post_mortem_form"):
 
95
  # Usar session_state para precompletar si corresponde
96
  col1, col2 = st.columns(2)
97
  with col1:
98
  tipo_alerta = st.text_input(
99
  "Tipo de Alerta / Título del Problema",
 
100
  placeholder="Ej: High CPU usage en DB Server; Caída del servicio de Login",
 
101
  )
102
  sistema_afectado = st.text_input(
103
  "Sistema Afectado",
 
104
  placeholder="Ej: Servidor de Base de Datos; Microservicio de Autenticación",
 
105
  )
106
  with col2:
107
  fecha_hora = st.text_input(
108
  "Fecha y Hora",
 
109
  placeholder="Ej: 26/Sep/2025 21:45 PM UTC-3",
 
110
  )
111
+
112
  impacto_detalle = st.text_area(
113
  "Impacto del Negocio y Observaciones",
 
114
  placeholder="Ej: Latencia elevada afectó al 20% de los usuarios.",
115
  height=150,
 
116
  )
117
+
118
  acciones_tomadas = st.text_area(
119
  "Acciones Tomadas (Mitigación Inmediata)",
 
120
  placeholder="Ej: Se escaló a Dev Team. Se reinició el servicio crítico.",
121
  height=150,
 
122
  )
123
+
124
  # Botón de envío
125
  submitted = st.form_submit_button("🚀 Generar Informe Post-Mortem")
126
 
 
130
 
131
  if not api_key:
132
  st.error("❌ Por favor, ingresa tu API Key de Gemini en el panel lateral (sidebar) antes de continuar.")
133
+
134
  elif not all([tipo_alerta, sistema_afectado, fecha_hora, impacto_detalle, acciones_tomadas]):
135
  st.error("❌ Por favor, completa todos los campos del formulario para generar el informe.")
136
+
137
  else:
138
  with st.spinner("⏳ Generando informe técnico con Google Gemini..."):
139
  informe = generar_post_mortem(
 
147
 
148
  # Mostrar el resultado
149
  st.divider()
150
+ st.success("✅ Informe Post-Mortem Generado")
151
  st.markdown(informe)
152
  st.download_button(
153
  label="Descargar Informe (.md)",