Download app.py from ElDoctor/Demo: direct link, hf CLI and curl.
- Browser
- Download file 5.85 kB
-
https://huggingface.co/spaces/ElDoctor/Demo/resolve/main/app.py
- Command line
-
hf download hf://spaces/ElDoctor/Demo/app.py
-
curl -L -o app.py https://huggingface.co/spaces/ElDoctor/Demo/resolve/main/app.py
5.85 kB
| from huggingface_hub import hf_hub_download | |
| import pickle | |
| import os | |
| import re | |
| from transformers import pipeline | |
| import pandas as pd | |
| # 🚀 Cargar modelo principal o usar Hugging Face como alternativa | |
| def cargar_modelo(): | |
| try: | |
| modelo_path = hf_hub_download(repo_id="ElDoctor/contractor", filename="modelo.pkl") | |
| with open(modelo_path, 'rb') as f: | |
| return pickle.load(f) | |
| except Exception: | |
| return pipeline("text-classification", model="distilbert-base-uncased-finetuned-sst-2-english") | |
| modelo = cargar_modelo() | |
| def predecir_con_modelo_original(precio): | |
| try: | |
| entrada = torch.tensor([float(precio)], dtype=torch.float32) | |
| with torch.no_grad(): | |
| resultado = modelo_original(entrada) | |
| # Explicitly check for torch.Tensor or numbers | |
| return resultado.item() if isinstance(resultado, (torch.Tensor, int, float, np.ndarray)) else resultado | |
| except Exception as e: | |
| print(f"Error en predicción con modelo original: {e}") | |
| return None | |
| # 🔍 Detección automática de la columna de precios | |
| def detectar_columna_precios(df): | |
| nombres = ['tender price', 'precio', 'monto', 'valor', 'costo', 'importe', 'amount', 'price', 'contract value', 'cost'] | |
| for columna in df.columns: | |
| if any(nombre in columna.lower() for nombre in nombres): | |
| if pd.to_numeric(df[columna], errors='coerce').notna().sum() > 0.5 * len(df): | |
| return columna | |
| return None | |
| # 🧹 Limpieza de precios | |
| def limpiar_precio(valor): | |
| if pd.isna(valor): | |
| return np.nan | |
| if isinstance(valor, str): | |
| valor = re.sub(r'[^\d.,]', '', valor).replace(',', '.') | |
| try: | |
| return float(valor) | |
| except: | |
| return np.nan | |
| # 📤 Cargar archivo CSV | |
| def cargar_contrataciones(archivo_csv): | |
| try: | |
| df = pd.read_csv(archivo_csv.name) | |
| columna_precio = detectar_columna_precios(df) | |
| if not columna_precio: | |
| return None, "⚠️ No se encontró una columna con precios." | |
| df['Precio_Procesado'] = df[columna_precio].apply(limpiar_precio) | |
| df.dropna(subset=['Precio_Procesado'], inplace=True) | |
| df.to_csv("archivo_completo.csv", index=False) | |
| return "archivo_completo.csv", f"✅ {len(df)} contrataciones cargadas." | |
| except Exception as e: | |
| return None, f"❌ Error al procesar: {e}" | |
| def aplicar_color(val): | |
| color = 'green' if val > 90 else 'red' if val < 10 else 'orange' | |
| return f'color: {color}' | |
| # 📊 Analizar contrataciones | |
| # 🎨 Ajuste de colores basado en valores altos = más rojo | |
| def aplicar_estilo(df): | |
| return df.style.background_gradient( | |
| cmap="Reds", subset=["Precio_Procesado", "Confianza Ajustada"] | |
| ).set_properties(**{"text-align": "center"}) | |
| # 📊 Analizar contrataciones | |
| def analizar_contrataciones(n_filas): | |
| try: | |
| if not os.path.exists("archivo_completo.csv"): | |
| return None, "⚠️ Carga un archivo primero.", None | |
| df = pd.read_csv("archivo_completo.csv") | |
| columna_precio = detectar_columna_precios(df) | |
| if not columna_precio: | |
| return None, "⚠️ No se encontró una columna de precios.", None | |
| df['Precio_Procesado'] = df[columna_precio].apply(limpiar_precio) | |
| df.dropna(subset=['Precio_Procesado'], inplace=True) | |
| n_filas = min(max(1, int(n_filas)), len(df)) | |
| df = df.sample(n=n_filas) | |
| # 🔮 Predicción con el modelo | |
| if callable(modelo): # Verifica si el modelo es una función (Hugging Face o PyTorch) | |
| if "transformers.pipelines" in str(type(modelo)): # Modelo Hugging Face | |
| textos = [f"El precio del contrato es {precio}" for precio in df['Precio_Procesado'].astype(str)] | |
| resultados = modelo(textos) | |
| df['Etiqueta'] = [r["label"] for r in resultados] | |
| df['Confianza'] = [r["score"] for r in resultados] | |
| else: # Modelo PyTorch | |
| df['Confianza'] = df['Precio_Procesado'].apply(lambda x: modelo(torch.tensor([x], dtype=torch.float32)).item()) | |
| #DEBEMOS AJUSTAR EL VALOR PARA QUE TENGA MAYOR COHERENCIA | |
| # 📊 Ajuste de datos | |
| df['Confianza Ajustada'] = df['Confianza'] * 100000 | |
| # 🗑️ Eliminar la columna Precio_Formatado | |
| df.drop(columns=["Precio_Formatado"], errors="ignore", inplace=True) | |
| # 🎨 Aplicar estilo de colores | |
| df_styled = df.style.background_gradient( | |
| cmap="Reds", subset=["Precio_Procesado", "Confianza Ajustada"] | |
| ).set_properties(**{"text-align": "center"}) | |
| df.to_csv("resultados.csv", index=False) | |
| return "resultados.csv", f"✅ Analizadas {len(df)} filas.", df_styled.to_html() | |
| except Exception as e: | |
| return None, f"❌ Error: {e}", None | |
| # 🌟 Interfaz en Gradio | |
| with gr.Blocks(title="Análisis de Contratos Públicos") as app: | |
| gr.Markdown("# 📢 Análisis de Contratos Públicos 🚀") | |
| archivo_input = gr.File(label="📂 Sube tu archivo CSV") | |
| btn_cargar = gr.Button("📋 Cargar") | |
| estado_carga = gr.Text(label="Estado de carga") | |
| archivo_descargar = gr.File(label="📥 Descargar datos cargados", visible=False) | |
| btn_cargar.click(cargar_contrataciones, inputs=[archivo_input], outputs=[archivo_descargar, estado_carga]) | |
| gr.Markdown("## 🔍 Análisis") | |
| num_filas = gr.Number(label="Filas a analizar", value=500) | |
| btn_analizar = gr.Button("🔎 Analizar") | |
| estado_analisis = gr.Text(label="Estado del análisis") | |
| archivo_resultado = gr.File(label="📥 Descargar Resultados") | |
| tabla_resultados = gr.HTML(label="📊 Resultados") | |
| btn_analizar.click(analizar_contrataciones, inputs=[num_filas], outputs=[archivo_resultado, estado_analisis, tabla_resultados]) | |
| app.launch(share=True) # Moved inside the with gr.blocks() statement |