Demo / app.py
ElDoctor's picture
creat
70cd3eb verified
Raw History Blame Contribute Delete
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