Agent-Biotech / app.py
C2MV's picture
Update app.py
ea504fb verified
import gradio as gr
from gradio_client import Client, handle_file
import pandas as pd
import json
import tempfile
import os
from datetime import datetime
import plotly.graph_objects as go
import plotly.express as px
import matplotlib.pyplot as plt
import numpy as np
# Configuración de clientes
biotech_client = Client("C2MV/BiotechU4")
analysis_client = Client("C2MV/Project-HF-2025")
# Tema personalizado
theme = gr.themes.Soft(
primary_hue="blue",
secondary_hue="indigo",
neutral_hue="slate",
spacing_size="md",
radius_size="lg",
)
def process_biotech_data(file, models, component, use_de, maxfev, exp_names):
"""Procesa los datos en el primer endpoint de BiotechU4"""
try:
result = biotech_client.predict(
file=handle_file(file.name),
models=models,
component=component,
use_de=use_de,
maxfev=maxfev,
exp_names=exp_names,
theme=False,
api_name="/run_analysis_wrapper"
)
return result
except Exception as e:
return None, None, f"Error en el análisis: {str(e)}"
def create_dummy_plot():
"""Crea un plot de ejemplo cuando no se pueden parsear los datos"""
fig = go.Figure()
# Añadir datos de ejemplo
x = np.linspace(0, 10, 100)
y = np.exp(-x/5) * np.cos(2*np.pi*x)
fig.add_trace(go.Scatter(
x=x,
y=y,
mode='lines',
name='Datos de ejemplo',
line=dict(color='blue', width=2)
))
fig.update_layout(
title="Visualización de Resultados",
xaxis_title="Tiempo",
yaxis_title="Valor",
template="plotly_white",
height=500
)
return fig
def parse_plot_data(plot_dict):
"""Convierte el diccionario del plot en un objeto visualizable"""
if not plot_dict:
return create_dummy_plot()
try:
# Si es un diccionario con tipo y plot
if isinstance(plot_dict, dict) and 'type' in plot_dict and 'plot' in plot_dict:
plot_type = plot_dict['type']
plot_data = plot_dict['plot']
# Si es plotly
if plot_type == 'plotly':
if isinstance(plot_data, str):
try:
# Intentar parsear como JSON
plot_json = json.loads(plot_data)
# Crear figura de Plotly desde JSON
fig = go.Figure(plot_json)
return fig
except:
# Si falla, intentar evaluar como dict
try:
import ast
plot_dict = ast.literal_eval(plot_data)
fig = go.Figure(plot_dict)
return fig
except:
pass
elif isinstance(plot_data, dict):
# Si ya es un diccionario, crear figura directamente
fig = go.Figure(plot_data)
return fig
# Si es matplotlib, crear una figura simple
elif plot_type == 'matplotlib':
return create_dummy_plot()
# Si es altair o bokeh, también crear dummy
elif plot_type in ['altair', 'bokeh']:
return create_dummy_plot()
# Si el plot_dict ya es una figura válida, devolverla
if hasattr(plot_dict, 'data') or hasattr(plot_dict, 'figure'):
return plot_dict
except Exception as e:
print(f"Error parsing plot: {str(e)}")
# En caso de error, devolver plot dummy
return create_dummy_plot()
def download_results_as_csv(df_data):
"""Descarga los resultados como CSV desde BiotechU4"""
try:
result = biotech_client.predict(
df=df_data,
api_name="/download_results_excel"
)
return result
except Exception as e:
# Si falla, crear un archivo temporal con los datos
if df_data and 'data' in df_data and 'headers' in df_data:
try:
df = pd.DataFrame(df_data['data'], columns=df_data['headers'])
temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False)
df.to_csv(temp_file.name, index=False)
temp_file.close()
return temp_file.name
except:
pass
return None
def generate_claude_report(csv_file, model, detail_level, language, additional_specs):
"""Genera el informe usando Claude"""
try:
result = analysis_client.predict(
files=[handle_file(csv_file)],
model=model,
detail=detail_level,
language=language,
additional_specs=additional_specs,
api_name="/process_and_store"
)
return result
except Exception as e:
return f"Error en el análisis: {str(e)}", ""
def export_report(format_type, language, analysis, code):
"""Exporta el informe en el formato seleccionado"""
try:
result = analysis_client.predict(
format=format_type,
language=language,
api_name="/handle_export"
)
return result[1], result[0]
except Exception as e:
return None, f"Error al exportar: {str(e)}"
def process_complete_pipeline(
file,
models,
component,
use_de,
maxfev,
exp_names,
claude_model,
detail_level,
language,
additional_specs,
export_format
):
"""Pipeline completo de procesamiento"""
progress_updates = []
if not file:
empty_fig = create_dummy_plot()
return empty_fig, None, None, None, None, "❌ Por favor, sube un archivo para procesar"
if not models:
empty_fig = create_dummy_plot()
return empty_fig, None, None, None, None, "❌ Por favor, selecciona al menos un modelo"
# Paso 1: Procesar con BiotechU4
progress_updates.append("🔄 Procesando datos biotecnológicos...")
plot_data, df_data, status = process_biotech_data(
file, models, component, use_de, maxfev, exp_names
)
if plot_data is None or "Error" in str(status):
empty_fig = create_dummy_plot()
return empty_fig, None, None, None, None, status
# Parsear el plot correctamente
plot = parse_plot_data(plot_data)
progress_updates.append("✅ Análisis biotecnológico completado")
# Paso 2: Descargar resultados como CSV
progress_updates.append("📥 Descargando resultados...")
csv_file = download_results_as_csv(df_data)
if not csv_file:
return plot, df_data, None, None, None, "\n".join(progress_updates) + "\n❌ Error al descargar resultados"
# Paso 3: Generar análisis con Claude
progress_updates.append(f"🤖 Generando análisis con {claude_model}...")
analysis, code = generate_claude_report(
csv_file, claude_model, detail_level, language, additional_specs
)
if "Error" in analysis:
return plot, df_data, analysis, code, None, "\n".join(progress_updates) + f"\n❌ {analysis}"
progress_updates.append("✅ Análisis con Claude completado")
# Paso 4: Exportar informe
progress_updates.append(f"📄 Exportando informe en formato {export_format}...")
report_file, export_status = export_report(export_format, language, analysis, code)
if report_file:
progress_updates.append("✅ Informe exportado exitosamente")
else:
progress_updates.append(f"❌ {export_status}")
final_status = "\n".join(progress_updates)
return plot, df_data, analysis, code, report_file, final_status
# CSS personalizado
custom_css = """
.container {
max-width: 1400px;
margin: auto;
}
.file-upload {
border: 2px dashed #3b82f6;
border-radius: 12px;
padding: 20px;
text-align: center;
transition: all 0.3s ease;
}
.file-upload:hover {
border-color: #2563eb;
background-color: #eff6ff;
}
button.primary {
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
border: none;
color: white;
font-weight: bold;
transition: all 0.3s ease;
}
button.primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(59, 130, 246, 0.3);
}
.tabs {
border-radius: 12px;
overflow: hidden;
}
.tab-nav {
background-color: #f3f4f6;
padding: 5px;
}
.tab-nav button {
border-radius: 8px;
margin: 0 2px;
}
.tab-nav button.selected {
background-color: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.gr-dataframe {
border-radius: 8px;
overflow: hidden;
}
.gr-dataframe table {
font-size: 14px;
}
"""
# Interfaz de Gradio
with gr.Blocks(theme=theme, title="BioTech Analysis & Report Generator", css=custom_css) as demo:
gr.Markdown(
"""
# 🧬 BioTech Analysis & Report Generator
### Pipeline completo de análisis biotecnológico con IA
Este sistema combina análisis avanzado de datos biotecnológicos con generación de informes mediante Claude 3.5.
"""
)
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("## 📊 Configuración del Análisis")
# Inputs para BiotechU4
file_input = gr.File(
label="📁 Archivo de datos (CSV/Excel)",
file_types=[".csv", ".xlsx", ".xls"],
elem_classes=["file-upload"]
)
with gr.Group():
gr.Markdown("### 🔬 Parámetros de Análisis")
models_input = gr.CheckboxGroup(
choices=['logistic', 'gompertz', 'moser', 'baranyi', 'monod',
'contois', 'andrews', 'tessier', 'richards', 'stannard', 'huang'],
value=['logistic', 'gompertz', 'moser', 'baranyi'],
label="📊 Modelos a probar"
)
component_input = gr.Dropdown(
choices=['all', 'biomass', 'substrate', 'product'],
value='all',
label="📈 Componente a visualizar"
)
exp_names_input = gr.Textbox(
label="🏷️ Nombres de experimentos",
placeholder="Experimento 1, Experimento 2...",
value="Análisis Biotecnológico"
)
with gr.Row():
use_de_input = gr.Checkbox(
label="🧮 Usar Evolución Diferencial",
value=False
)
maxfev_input = gr.Number(
label="🔄 Iteraciones máximas",
value=50000,
minimum=1000,
maximum=100000,
step=1000
)
with gr.Group():
gr.Markdown("### 🤖 Configuración de Claude")
claude_model_input = gr.Dropdown(
choices=[
'claude-3-7-sonnet-20250219',
'claude-3-5-sonnet-20241022',
'claude-3-5-haiku-20241022',
'claude-sonnet-4-20250514',
'claude-opus-4-20250514'
],
value='claude-3-7-sonnet-20250219',
label="🤖 Modelo de Claude"
)
detail_level_input = gr.Radio(
choices=['detailed', 'summarized'],
value='detailed',
label="📋 Nivel de detalle del análisis"
)
language_input = gr.Dropdown(
choices=['en', 'es', 'fr', 'de', 'pt'],
value='es',
label="🌐 Idioma del informe"
)
additional_specs_input = gr.Textbox(
label="📝 Especificaciones adicionales",
placeholder="Añade contexto o requisitos específicos para el análisis...",
lines=3,
value="Proporciona un análisis detallado de los modelos ajustados, incluyendo métricas de bondad de ajuste, comparación entre modelos y recomendaciones prácticas."
)
export_format_input = gr.Radio(
choices=['PDF', 'DOCX'],
value='PDF',
label="📄 Formato de exportación"
)
process_btn = gr.Button(
"🚀 Ejecutar Pipeline Completo",
variant="primary",
size="lg",
elem_classes=["primary"]
)
with gr.Column(scale=2):
gr.Markdown("## 📈 Resultados")
with gr.Tabs(elem_classes=["tabs"]):
with gr.TabItem("📊 Visualización"):
plot_output = gr.Plot(label="Gráfico interactivo")
with gr.TabItem("📋 Tabla de Resultados"):
table_output = gr.Dataframe(
label="Resultados del ajuste",
interactive=False
)
with gr.TabItem("📝 Análisis de Claude"):
analysis_output = gr.Markdown(label="Análisis comparativo")
with gr.TabItem("💻 Código"):
code_output = gr.Code(
label="Código de implementación",
language="python"
)
with gr.Row():
status_output = gr.Textbox(
label="📊 Estado del proceso",
lines=6,
interactive=False
)
with gr.Row():
report_output = gr.File(
label="📥 Descargar informe",
interactive=False
)
# Conectar la función principal
process_btn.click(
fn=process_complete_pipeline,
inputs=[
file_input,
models_input,
component_input,
use_de_input,
maxfev_input,
exp_names_input,
claude_model_input,
detail_level_input,
language_input,
additional_specs_input,
export_format_input
],
outputs=[
plot_output,
table_output,
analysis_output,
code_output,
report_output,
status_output
]
)
# Footer
gr.Markdown(
"""
---
### 📚 Instrucciones de uso:
1. **Sube tu archivo de datos** en formato CSV o Excel
2. **Selecciona los modelos** que deseas probar para el ajuste
3. **Configura los parámetros** de análisis según tus necesidades
4. **Elige el modelo de Claude** para generar el informe
5. **Especifica el idioma y formato** de exportación deseado
6. **Haz clic en "Ejecutar Pipeline Completo"** y espera los resultados
El sistema procesará tus datos, realizará el ajuste de modelos, generará un análisis
detallado con IA y producirá un informe profesional descargable.
"""
)
if __name__ == "__main__":
demo.launch(
share=False,
show_error=True
)