machinelearning / utils /gemini_explainer.py
JersonRuizAlva
Add application file
97a4bf8
# utils/gemini_explainer.py
import streamlit as st
import google.generativeai as genai
from typing import Dict, Any, Optional
import h2o
import os
def generate_dataset_explanation(dataset, api_key=None):
"""
Generate a dataset explanation using Gemini AI
Args:
dataset (pd.DataFrame): DataFrame to explain
api_key (str, optional): Gemini API key
Returns:
str: Explanation of the dataset
"""
try:
# Prepare dataset information
dataset_info = {
'rows': len(dataset),
'columns': len(dataset.columns),
'column_names': list(dataset.columns),
'data_types': str(dataset.dtypes),
'first_rows': dataset.head().to_string(),
'basic_stats': dataset.describe().to_string()
}
# Initialize Gemini Explainer
explainer = GeminiExplainer(api_key)
# Generate explanation
explanation = explainer.generate_dataset_explanation(dataset_info)
return explanation
except Exception as e:
return f"Error generating dataset explanation: {str(e)}"
def generate_model_explanation(self, model_info: Dict[str, Any]) -> str:
"""
Generar una explicación detallada de un modelo de machine learning
Args:
model_info (dict): Información del modelo
Returns:
str: Explicación generada por Gemini
"""
prompt = f"""Proporciona una explicación detallada del modelo de machine learning:
Información del Modelo:
- Nombre del Modelo: {model_info.get('name', 'N/A')}
- Tipo de Problema: {model_info.get('problem_type', 'N/A')}
- Hiperparámetros: {model_info.get('hyperparameters', 'N/A')}
- Métricas de Rendimiento:
* Accuracy/R²: {model_info.get('performance_metric', 'N/A')}
* Otras métricas: {model_info.get('additional_metrics', 'N/A')}
En tu explicación, incluye:
1. Descripción del algoritmo
2. Funcionamiento interno del modelo
3. Interpretación de los hiperparámetros
4. Análisis de las métricas de rendimiento
5. Fortalezas y limitaciones del modelo
6. Recomendaciones para posibles mejoras"""
try:
response = self.model.generate_content(prompt)
return response.text
except Exception as e:
return f"Error al generar explicación: {str(e)}"
class GeminiExplainer:
def __init__(self, api_key: Optional[str] = None):
"""
Inicializar el explicador de Gemini
Args:
api_key (str, opcional): API key de Google Generative AI
"""
self.api_key = api_key or st.session_state.get('gemini_api_key')
if not self.api_key:
raise ValueError("No se ha proporcionado una API key de Gemini")
# Configurar la API de Gemini
genai.configure(api_key=self.api_key)
# Seleccionar modelo
self.model = genai.GenerativeModel('gemini-1.5-flash')
def generate_dataset_explanation(self, dataset_info: Dict[str, Any]) -> str:
"""
Generar una explicación detallada del dataset
Args:
dataset_info (dict): Información del dataset
Returns:
str: Explicación generada por Gemini
"""
prompt = f"""Analiza este dataset y proporciona una explicación clara y concisa de su estructura y contenido:
Información del Dataset:
- Dimensiones: {dataset_info.get('rows', 'N/A')} filas × {dataset_info.get('columns', 'N/A')} columnas
- Columnas: {', '.join(dataset_info.get('column_names', []))}
- Tipos de datos: {dataset_info.get('data_types', 'N/A')}
- Primeras filas: {dataset_info.get('first_rows', 'N/A')}
- Estadísticas básicas: {dataset_info.get('basic_stats', 'N/A')}
En tu explicación, incluye:
1. Descripción general del dataset
2. Tipos de variables presentes
3. Posibles desafíos o consideraciones para el análisis
4. Sugerencias iniciales de preprocesamiento
5. Potenciales insights o patrones preliminares"""
try:
response = self.model.generate_content(prompt)
return response.text
except Exception as e:
return f"Error al generar explicación: {str(e)}"
def generate_model_explanation(self, model_info: Dict[str, Any]) -> str:
"""
Generar una explicación detallada de un modelo de machine learning
Args:
model_info (dict): Información del modelo
Returns:
str: Explicación generada por Gemini
"""
# Extraer hiperparámetros en formato legible
hyperparameters = model_info.get('hyperparameters', {})
if isinstance(hyperparameters, dict):
hyperparams_str = "\n".join([f"- {k}: {v}" for k, v in hyperparameters.items()])
else:
hyperparams_str = str(hyperparameters)
prompt = f"""Proporciona una explicación detallada del modelo de machine learning:
Información del Modelo:
- Nombre del Modelo: {model_info.get('name', 'N/A')}
- Tipo de Problema: {model_info.get('problem_type', 'N/A')}
- Hiperparámetros:
{hyperparams_str}
- Métricas de Rendimiento:
* Accuracy/R²: {model_info.get('performance_metric', 'N/A')}
* Tiempo de Entrenamiento: {model_info.get('training_time', 'N/A')}
En tu explicación, incluye:
1. Descripción del algoritmo
2. Funcionamiento interno del modelo
3. Interpretación de los hiperparámetros
4. Análisis de las métricas de rendimiento
5. Fortalezas y limitaciones del modelo
6. Recomendaciones para posibles mejoras"""
try:
response = self.model.generate_content(prompt)
return response.text
except Exception as e:
return f"Error al generar explicación: {str(e)}"
def generate_clustering_explanation(self, clustering_info: Dict[str, Any]) -> str:
"""
Generar una explicación de resultados de clustering
Args:
clustering_info (dict): Información del clustering
Returns:
str: Explicación generada por Gemini
"""
prompt = f"""Analiza los resultados del método de clustering:
Información del Clustering:
- Método: {clustering_info.get('method', 'N/A')}
- Número de Clusters: {clustering_info.get('n_clusters', 'N/A')}
- Parámetros: {clustering_info.get('parameters', 'N/A')}
- Métricas:
* Silhouette Score: {clustering_info.get('silhouette_score', 'N/A')}
* Calinski-Harabasz: {clustering_info.get('calinski_score', 'N/A')}
* Davies-Bouldin: {clustering_info.get('davies_bouldin', 'N/A')}
En tu explicación, incluye:
1. Descripción del método de clustering
2. Interpretación de los parámetros utilizados
3. Significado de las métricas de evaluación
4. Análisis de la calidad de los clusters
5. Posibles insights o patrones detectados
6. Recomendaciones para ajustar el clustering"""
try:
response = self.model.generate_content(prompt)
return response.text
except Exception as e:
return f"Error al generar explicación: {str(e)}"
def generate_feature_importance_explanation(self, feature_importance_info: Dict[str, Any]) -> str:
"""
Generar una explicación de la importancia de características
Args:
feature_importance_info (dict): Información de importancia de características
Returns:
str: Explicación generada por Gemini
"""
method = feature_importance_info.get('method', 'N/A')
features = feature_importance_info.get('features', [])
importance_values = feature_importance_info.get('importance_values', {})
# Formatear la información de importancia
importance_str = "\n".join([f"- {feat}: {val}" for feat, val in importance_values.items()])
prompt = f"""Analiza la importancia de las características en el modelo:
Información de Importancia de Características:
- Método de Evaluación: {method}
- Características:
{importance_str}
En tu explicación, incluye:
1. Descripción del método de evaluación de importancia
2. Análisis de las características más importantes
3. Interpretación de los valores de importancia
4. Posibles implicaciones para el modelado
5. Recomendaciones para selección de características"""
try:
response = self.model.generate_content(prompt)
return response.text
except Exception as e:
return f"Error al generar explicación: {str(e)}"
def initialize_gemini_explainer():
"""
Función de utilidad para inicializar el explicador de Gemini en Streamlit
Returns:
GeminiExplainer: Instancia del explicador de Gemini o None si hay error
"""
try:
if 'gemini_api_key' not in st.session_state:
st.warning("Por favor configura tu API key de Gemini primero")
return None
api_key = st.session_state.get('gemini_api_key')
if not api_key:
st.warning("API key de Gemini no encontrada")
return None
# Inicializar explicador con la API key
explainer = GeminiExplainer(api_key=api_key)
return explainer
except Exception as e:
st.error(f"Error al inicializar el explicador: {str(e)}")
return None
# Ejemplo de uso en Streamlit
def main():
st.title("Explicaciones con Gemini")
# Verificar configuración de API key
if 'gemini_api_key' not in st.session_state:
st.warning("Configura tu API key de Gemini")
return
explainer = initialize_gemini_explainer()
if explainer:
# Ejemplo de uso de métodos de explicación
st.subheader("Explicación de Dataset")
dataset_info = {
'rows': 100,
'columns': 5,
'column_names': ['age', 'income', 'education', 'credit_score', 'loan_approved'],
'data_types': 'Mixed (numeric and categorical)',
'first_rows': 'Sample data preview',
'basic_stats': 'Mean, median, standard deviation'
}
if st.button("Explicar Dataset"):
explanation = explainer.generate_dataset_explanation(dataset_info)
st.markdown(explanation)
st.subheader("Explicación de Modelo")
model_info = {
'name': 'Random Forest Classifier',
'problem_type': 'Clasificación binaria',
'hyperparameters': {
'n_estimators': 100,
'max_depth': 5,
'learning_rate': 0.1
},
'performance_metric': 0.85,
'additional_metrics': {
'precision': 0.82,
'recall': 0.88,
'f1_score': 0.85
}
}
if st.button("Explicar Modelo"):
explanation = explainer.generate_model_explanation(model_info)
st.markdown(explanation)
st.subheader("Explicación de Clustering")
clustering_info = {
'method': 'K-Means',
'n_clusters': 3,
'parameters': {
'eps': 0.5,
'min_samples': 5
},
'silhouette_score': 0.7,
'calinski_score': 150.5,
'davies_bouldin': 0.4
}
if st.button("Explicar Clustering"):
explanation = explainer.generate_clustering_explanation(clustering_info)
st.markdown(explanation)
st.subheader("Explicación de Importancia de Características")
feature_importance_info = {
'method': 'SHAP Values',
'features': ['age', 'income', 'education', 'credit_score'],
'importance_values': {
'age': 0.35,
'income': 0.25,
'education': 0.2,
'credit_score': 0.2
}
}
if st.button("Explicar Importancia de Características"):
explanation = explainer.generate_feature_importance_explanation(feature_importance_info)
st.markdown(explanation)
# Función para manejar errores de API key
def validate_gemini_api_key(api_key: str) -> bool:
"""
Validar la API key de Gemini
Args:
api_key (str): API key a validar
Returns:
bool: True si la API key es válida, False en caso contrario
"""
try:
genai.configure(api_key=api_key)
model = genai.GenerativeModel('gemini-1.5-flash')
# Intentar generar una respuesta simple
response = model.generate_content("Hola, ¿estás funcionando?")
return True
except Exception as e:
st.error(f"Error de validación de API key: {str(e)}")
return False
# Función de configuración de API key en Streamlit
def setup_gemini_api_key():
"""
Configurar y validar la API key de Gemini en Streamlit
"""
st.sidebar.header("🔑 Configuración de Gemini API")
# Input para la API key
api_key = st.sidebar.text_input(
"Ingresa tu Gemini API Key",
type="password",
help="Puedes obtener tu API key en Google AI Studio"
)
# Botón de validación
if st.sidebar.button("Validar API Key"):
if api_key:
if validate_gemini_api_key(api_key):
st.session_state.gemini_api_key = api_key
st.sidebar.success("✅ API Key validada correctamente")
else:
st.sidebar.error("❌ API Key inválida")
else:
st.sidebar.warning("Por favor, ingresa una API Key")
# Mostrar estado actual
if 'gemini_api_key' in st.session_state:
st.sidebar.info("API Key configurada")
# Configuraciones adicionales y documentación
def get_gemini_documentation():
"""
Generar documentación sobre el uso de Gemini en el proyecto
Returns:
str: Documentación en formato markdown
"""
documentation = """
## 🤖 Explicaciones con Gemini AI
### Características
- Generación de explicaciones detalladas para:
* Datasets
* Modelos de Machine Learning
* Resultados de Clustering
* Importancia de Características
### Requisitos
- API Key de Google AI Studio
- Conexión a internet
- Biblioteca `google-generativeai`
### Configuración
1. Obtén tu API Key en [Google AI Studio](https://makersuite.google.com/app/apikey)
2. Configura la API Key en la barra lateral
3. Valida la conexión con el botón "Validar API Key"
### Limitaciones
- Depende de la disponibilidad del servicio
- Consumo de tokens de API
- Explicaciones generadas por IA pueden no ser 100% precisas
### Mejores Prácticas
- Usar como complemento, no como única fuente de verdad
- Verificar siempre las explicaciones generadas
- Tener contexto del problema al interpretar resultados
"""
return documentation
# Punto de entrada principal
if __name__ == "__main__":
main()