File size: 5,190 Bytes
2d161de |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# -*- coding: utf-8 -*-
"""app.ipynb
Automatically generated by Colab.
Original file is located at
https://colab.research.google.com/drive/1e3y3OTjQnNFZ7FLgs2elviYcG7ptj2fI
"""
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
from sentence_transformers import SentenceTransformer, util
import numpy as np
import joblib
import torch
import gradio as gr
from transformers import TextGenerationPipeline
# === Cargar modelos entrenados ===
modelo_riesgo = joblib.load("modelo_riesgo.pkl")
modelo_violencia = joblib.load("modelo_tipo_violencia.pkl")
modelo_medida = joblib.load("modelo_tipo_medida.pkl")
codificadores = joblib.load("codificadores_label_encoder.pkl")
modelo_vector = SentenceTransformer("Snowflake/snowflake-arctic-embed-xs")
# === Cargar modelo de lenguaje OpenHermes-2.5 ===
model_id = "teknium/OpenHermes-2.5-Mistral-7B"
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
model_id,
trust_remote_code=True,
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
device_map="auto"
)
modelo_llm = TextGenerationPipeline(
model=model,
tokenizer=tokenizer,
max_new_tokens=300,
temperature=0.5,
do_sample=True,
)
# === Frases prototipo para verificador semántico ===
frases_fisica = [
"Me golpeó con el puño cerrado", "Me pateó", "Me lanzó contra la pared",
"Me estranguló", "Me fracturó una costilla", "Me tiró al piso violentamente"
]
frases_sexual = [
"Me obligó a tener relaciones sexuales", "Me tocó sin consentimiento",
"Me violó", "Me forzó a tener sexo", "Me agredió sexualmente"
]
embeds_fisica = modelo_vector.encode(frases_fisica)
embeds_sexual = modelo_vector.encode(frases_sexual)
# === FUNCIÓN PRINCIPAL ===
def predecir_con_recomendacion(edad, genero, hijos, convivencia_agresor, consumo_sustancias, apoyo_familiar, descripcion):
# Codificar variables
vector_tabular = np.array([
int(edad),
int(hijos),
codificadores["genero"].transform([genero])[0],
0, 0, 0,
codificadores["convivencia_agresor"].transform([convivencia_agresor])[0],
codificadores["consumo_sustancias"].transform([consumo_sustancias])[0],
codificadores["apoyo_familiar"].transform([apoyo_familiar])[0]
])
# Vectorizar descripción
vector_desc = modelo_vector.encode([descripcion])[0]
entrada = np.concatenate([vector_tabular, vector_desc])
# Predicciones
riesgo_cod = modelo_riesgo.predict([entrada])[0]
tipo_violencia_cod = modelo_violencia.predict([entrada])[0]
tipo_medida_cod = modelo_medida.predict([entrada])[0]
# Decodificar
riesgo = codificadores["riesgo"].inverse_transform([riesgo_cod])[0]
tipo_violencia = codificadores["tipo_violencia"].inverse_transform([tipo_violencia_cod])[0]
tipo_medida = codificadores["tipo_medida"].inverse_transform([tipo_medida_cod])[0]
# Verificador semántico
emb_desc = modelo_vector.encode(descripcion)
sim_fisica = max(util.cos_sim(emb_desc, embeds_fisica)[0])
sim_sexual = max(util.cos_sim(emb_desc, embeds_sexual)[0])
if sim_fisica > 0.7:
tipo_violencia = "física"
elif sim_sexual > 0.7:
tipo_violencia = "sexual"
# PROMPT legal
prompt = f"""[INSTRUCCIÓN]
Como asistente legal, tu tarea es determinar qué medida de protección debe aplicarse en un caso de violencia intrafamiliar, de acuerdo al Artículo 5 de la Ley 575 de 2000 (modificado por la Ley 1257 de 2008 y la Ley 2126 de 2021).
[CASO]
Tipo de violencia: {tipo_violencia}
Nivel de riesgo: {riesgo}
Tipo de medida cautelar: {tipo_medida}
Descripción del caso: {descripcion}
[OBJETIVO]
Con base en la descripción del caso y la ley, indica:
- Qué literal(es) del Artículo 5 (a-n) deben aplicarse.
- Justifica legalmente tu elección con argumentos claros y precisos.
[RESPUESTA]
"""
respuesta = modelo_llm(prompt, max_new_tokens=350, temperature=0.5)[0]["generated_text"]
razonamiento = respuesta.split("[RESPUESTA]")[-1].strip()
return tipo_violencia, riesgo, tipo_medida, razonamiento
# === Gradio UI ===
gr.Interface(
fn=predecir_con_recomendacion,
inputs=[
gr.Slider(18, 65, value=30, label="Edad"),
gr.Radio(["F", "M"], label="Género"),
gr.Slider(0, 5, step=1, value=1, label="Número de hijos"),
gr.Radio(["sí", "no"], label="¿Convive con el agresor?"),
gr.Radio(["sí", "no"], label="¿Hay consumo de sustancias?"),
gr.Radio(["sí", "no"], label="¿Tiene apoyo familiar?"),
gr.Textbox(lines=4, label="Descripción del caso")
],
outputs=[
gr.Textbox(label="🛑 Tipo de violencia predicho"),
gr.Textbox(label="⚠️ Nivel de riesgo"),
gr.Textbox(label="🧾 Tipo de medida cautelar"),
gr.Textbox(label="📜 Recomendación legal razonada")
],
title="LEGALFAMI – Asistente Legal con Razonamiento Jurídico",
description="Predice tipo de violencia, nivel de riesgo y medida cautelar según Ley 575 Artículo 5, y recomienda la acción legal correspondiente.",
theme="default"
).launch() |