vvillarreal-cfee commited on
Commit
d183fa0
·
1 Parent(s): ded429a

Add Google Gemini integration and enhance post-mortem report generation UI

Browse files
Files changed (2) hide show
  1. requirements.txt +2 -1
  2. src/streamlit_app.py +146 -38
requirements.txt CHANGED
@@ -1,3 +1,4 @@
1
  altair
2
  pandas
3
- streamlit
 
 
1
  altair
2
  pandas
3
+ streamlit
4
+ google-genai
src/streamlit_app.py CHANGED
@@ -1,40 +1,148 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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(
7
+ page_title="Generador de Post-Mortem (Gemini AI)",
8
+ layout="wide"
9
+ )
10
+
11
+ # Inicializar el estado de la sesión para la API Key si no existe
12
+ if 'gemini_api_key' not in st.session_state:
13
+ st.session_state['gemini_api_key'] = ''
14
+
15
+ st.title("📄 Generador de Informes Post-Mortem con Gemini AI")
16
+ st.markdown("Ingresa los detalles de la incidencia y la IA generará un informe técnico estructurado.")
17
+
18
+ # --- Sidebar para la configuración de la API Key ---
19
+ with st.sidebar:
20
+ st.header("⚙️ Configuración")
21
+
22
+ # Campo de entrada para la API Key
23
+ st.session_state['gemini_api_key'] = st.text_input(
24
+ "Ingresa tu API Key de Gemini",
25
+ type="password",
26
+ value=st.session_state['gemini_api_key']
27
+ )
28
+
29
+ if st.session_state['gemini_api_key']:
30
+ st.success("API Key cargada. ¡Puedes generar el informe!")
31
+ else:
32
+ st.warning("🚨 Por favor, ingresa tu API Key de Gemini.")
33
+
34
+
35
+ # --- Función para generar el Post-Mortem ---
36
+ def generar_post_mortem(api_key, tipo_alerta, sistema, fecha_hora, impacto, acciones):
37
+ """
38
+ Construye el prompt, inicializa el cliente con la API Key y genera el informe.
39
+ """
40
+ MODEL_NAME = "gemini-2.5-flash"
41
+
42
+ # 1. Inicializar el cliente con la clave ingresada
43
+ try:
44
+ client = genai.Client(api_key=api_key)
45
+ except Exception as e:
46
+ return f"🚨 Error al inicializar el cliente de Gemini: {e}"
47
+
48
+ # 2. Definir la instrucción (System Instruction)
49
+ system_instruction = (
50
+ "Eres un analista técnico de IT. Tu tarea es generar un informe "
51
+ "Post-Mortem conciso y profesional, estructurado con las secciones: "
52
+ "'Resumen Ejecutivo', 'Qué Sucedió (Timeline)', 'Análisis de Causa Raíz', "
53
+ "'Impacto del Negocio' y 'Acciones Correctivas (Plan de Acción)'. "
54
+ "Usa Markdown (##) para los encabezados y un tono técnico y formal. "
55
+ "No añadas introducciones ni conclusiones fuera del formato solicitado."
56
+ )
57
+
58
+ # 3. Construir el contenido del prompt
59
+ prompt_content = f"""
60
+ Genera un informe Post-Mortem usando la siguiente información de la incidencia:
61
+ - **Tipo de Alerta/Problema Principal**: {tipo_alerta}
62
+ - **Sistema Afectado**: {sistema}
63
+ - **Fecha y Hora de Inicio**: {fecha_hora}
64
+ - **Impacto Reportado**: {impacto}
65
+ - **Acciones Inmediatas Tomadas**: {acciones}
66
+ """
67
+
68
+ try:
69
+ # Llamar a la API de Gemini
70
+ response = client.models.generate_content(
71
+ model=MODEL_NAME,
72
+ contents=prompt_content,
73
+ config=genai.types.GenerateContentConfig(
74
+ system_instruction=system_instruction
75
+ )
76
+ )
77
+ return response.text
78
+ except Exception as e:
79
+ # Muestra errores comunes de autenticación si la clave es incorrecta
80
+ return f"🚨 Error al generar el informe con Gemini (posible API Key inválida o límite excedido): {e}"
81
+
82
+
83
+ # --- Formulario de entrada de datos principal ---
84
+ with st.form("post_mortem_form"):
85
+ st.subheader("Detalles de la Incidencia")
86
+
87
+ col1, col2 = st.columns(2)
88
+ with col1:
89
+ tipo_alerta = st.text_input(
90
+ "Tipo de Alerta / Título del Problema",
91
+ placeholder="Ej: High CPU usage en DB Server; Caída del servicio de Login"
92
+ )
93
+ sistema_afectado = st.text_input(
94
+ "Sistema Afectado",
95
+ placeholder="Ej: Servidor de Base de Datos; Microservicio de Autenticación"
96
+ )
97
+
98
+ with col2:
99
+ fecha_hora = st.text_input(
100
+ "Fecha y Hora",
101
+ placeholder="Ej: 26/Sep/2025 21:45 PM UTC-3"
102
+ )
103
+
104
+ st.subheader("Descripción y Consecuencias")
105
+ impacto_detalle = st.text_area(
106
+ "Impacto del Negocio y Observaciones",
107
+ placeholder="Ej: Latencia elevada afectó al 20% de los usuarios.",
108
+ height=150
109
+ )
110
+
111
+ acciones_tomadas = st.text_area(
112
+ "Acciones Tomadas (Mitigación Inmediata)",
113
+ placeholder="Ej: Se escaló a Dev Team. Se reinició el servicio crítico.",
114
+ height=150
115
+ )
116
+
117
+ # Botón de envío
118
+ submitted = st.form_submit_button("🚀 Generar Informe Post-Mortem")
119
+
120
+ # --- Lógica de procesamiento ---
121
+ if submitted:
122
+ api_key = st.session_state.get('gemini_api_key')
123
+
124
+ if not api_key:
125
+ st.error("❌ Por favor, ingresa tu API Key de Gemini en el panel lateral (sidebar) antes de continuar.")
126
+ elif not all([tipo_alerta, sistema_afectado, fecha_hora, impacto_detalle, acciones_tomadas]):
127
+ st.error("❌ Por favor, completa todos los campos del formulario para generar el informe.")
128
+ else:
129
+ with st.spinner("⏳ Generando informe técnico con Google Gemini..."):
130
+ informe = generar_post_mortem(
131
+ api_key,
132
+ tipo_alerta,
133
+ sistema_afectado,
134
+ fecha_hora,
135
+ impacto_detalle,
136
+ acciones_tomadas
137
+ )
138
+
139
+ # Mostrar el resultado
140
+ st.divider()
141
+ st.subheader("✅ Informe Post-Mortem Generado")
142
+ st.markdown(informe)
143
+ st.download_button(
144
+ label="Descargar Informe (.md)",
145
+ data=informe,
146
+ file_name="post_mortem_incidencia.md",
147
+ mime="text/markdown"
148
+ )