km1lo commited on
Commit
68c0ddf
·
verified ·
1 Parent(s): ad23675

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +158 -0
  2. requirements.txt +10 -0
app.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """app.ipynb
3
+
4
+ Automatically generated by Colab.
5
+
6
+ Original file is located at
7
+ https://colab.research.google.com/drive/1WQ2YqAcXFp-14DglIYkV4rawVDSbyhCe
8
+ """
9
+
10
+ # -*- coding: utf-8 -*-
11
+ from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
12
+ from sentence_transformers import SentenceTransformer, util
13
+ import numpy as np
14
+ import joblib
15
+ import torch
16
+ import gradio as gr
17
+ from transformers import TextGenerationPipeline
18
+
19
+ # === Cargar modelos entrenados ===
20
+ modelo_riesgo = joblib.load("modelo_riesgo.pkl")
21
+ modelo_violencia = joblib.load("modelo_tipo_violencia.pkl")
22
+ modelo_medida = joblib.load("modelo_tipo_medida.pkl")
23
+ codificadores = joblib.load("codificadores_label_encoder.pkl")
24
+ modelo_vector = SentenceTransformer("Snowflake/snowflake-arctic-embed-xs")
25
+
26
+ # === Cargar modelo de lenguaje Mistral 7B Instruct ===
27
+ model_id = "mistralai/Mistral-7B-Instruct-v0.1"
28
+
29
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
30
+ model = AutoModelForCausalLM.from_pretrained(
31
+ model_id,
32
+ torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
33
+ device_map="auto"
34
+ )
35
+
36
+ modelo_llm = TextGenerationPipeline(
37
+ model=model,
38
+ tokenizer=tokenizer,
39
+ max_new_tokens=1000,
40
+ temperature=0.2,
41
+ do_sample=False,
42
+ )
43
+
44
+ # === Frases prototipo para verificador semántico ===
45
+ frases_fisica = [
46
+ "Me golpeó con el puño cerrado", "Me pateó", "Me lanzó contra la pared",
47
+ "Me estranguló", "Me fracturó una costilla", "Me tiró al piso violentamente"
48
+ ]
49
+ frases_sexual = [
50
+ "Me obligó a tener relaciones sexuales", "Me tocó sin consentimiento",
51
+ "Me violó", "Me forzó a tener sexo", "Me agredió sexualmente"
52
+ ]
53
+ embeds_fisica = modelo_vector.encode(frases_fisica)
54
+ embeds_sexual = modelo_vector.encode(frases_sexual)
55
+
56
+ # === Verificador semántico ===
57
+ def verificar_semantico(descripcion):
58
+ emb_desc = modelo_vector.encode(descripcion)
59
+ tipos_detectados = []
60
+ if max(util.cos_sim(emb_desc, embeds_fisica)[0]) > 0.7:
61
+ tipos_detectados.append("física")
62
+ if max(util.cos_sim(emb_desc, embeds_sexual)[0]) > 0.7:
63
+ tipos_detectados.append("sexual")
64
+ return tipos_detectados
65
+
66
+ # === FUNCIÓN PRINCIPAL MODIFICADA ===
67
+ def predecir_con_recomendacion(edad, genero, hijos, convivencia_agresor, consumo_sustancias, apoyo_familiar, descripcion):
68
+ # Codificar variables tabulares
69
+ vector_tabular = np.array([
70
+ int(edad),
71
+ int(hijos),
72
+ codificadores["genero"].transform([genero])[0],
73
+ 0, 0, 0,
74
+ codificadores["convivencia_agresor"].transform([convivencia_agresor])[0],
75
+ codificadores["consumo_sustancias"].transform([consumo_sustancias])[0],
76
+ codificadores["apoyo_familiar"].transform([apoyo_familiar])[0]
77
+ ])
78
+
79
+ # Vectorizar descripción
80
+ vector_desc = modelo_vector.encode([descripcion])[0]
81
+ entrada = np.concatenate([vector_tabular, vector_desc])
82
+
83
+ # Modelos clásicos
84
+ riesgo_cod = modelo_riesgo.predict([entrada])[0]
85
+ tipo_violencia_cod = modelo_violencia.predict([entrada])[0]
86
+ tipo_medida_cod = modelo_medida.predict([entrada])[0]
87
+
88
+ # Decodificación
89
+ riesgo = codificadores["riesgo"].inverse_transform([riesgo_cod])[0]
90
+ tipo_violencia_pred = codificadores["tipo_violencia"].inverse_transform([tipo_violencia_cod])[0]
91
+ tipo_medida = codificadores["tipo_medida"].inverse_transform([tipo_medida_cod])[0]
92
+
93
+ # Verificador semántico
94
+ tipos_semantico = verificar_semantico(descripcion)
95
+
96
+ # Unir modelo + semántico sin duplicados
97
+ tipos_combinados = list(set([tipo_violencia_pred] + tipos_semantico))
98
+ tipos_str = ", ".join(tipos_combinados)
99
+
100
+ # PROMPT claro y detallado
101
+ prompt = f"""Eres un jurista colombiano experto en violencia intrafamiliar.
102
+ Analiza este caso y redacta un Auto de Medida Provisional conforme a la Ley 575 de 2000, Ley 1257 de 2008 y Ley 2126 de 2021.
103
+
104
+ Hechos del caso:
105
+ Tipo de violencia: {tipos_str}
106
+ Nivel de riesgo: {riesgo}
107
+ Medida cautelar sugerida: {tipo_medida}
108
+ Descripción detallada: {descripcion}
109
+
110
+ Redacta con este formato:
111
+
112
+ CONSIDERACIONES:
113
+ - Hechos relevantes y valoración del riesgo.
114
+ - Fundamentos jurídicos aplicables.
115
+ - Justificación breve de cada literal del Artículo 5 aplicable.
116
+
117
+ RESUELVE:
118
+ PRIMERO: Admitir la solicitud.
119
+ SEGUNDO: Ordenar las siguientes medidas (una por línea).
120
+ TERCERO: Cúmplase y notifíquese.
121
+
122
+ Limita tu respuesta a máximo 600 palabras, en estilo formal.
123
+ """
124
+
125
+ salida = modelo_llm(prompt)[0]["generated_text"]
126
+ auto_redactado = salida.strip()
127
+
128
+ return tipos_str, riesgo, tipo_medida, auto_redactado
129
+
130
+ # === Interfaz Gradio (idéntica) ===
131
+ with gr.Blocks(theme=gr.themes.Soft()) as interfaz:
132
+ gr.Markdown("<h1 style='text-align:center; color:#004aad;'>LEGALFAMI – Asistente Legal con Razonamiento Jurídico</h1>")
133
+ gr.Markdown("Predice tipo de violencia, riesgo, medida cautelar y genera un Auto conforme a la Ley 575 Art.5.")
134
+
135
+ with gr.Row():
136
+ with gr.Column():
137
+ edad = gr.Slider(18, 65, value=30, label="Edad de la Víctima")
138
+ genero = gr.Radio(["F", "M"], label="Género")
139
+ hijos = gr.Slider(0, 5, step=1, value=1, label="Número de Hijos")
140
+ convivencia_agresor = gr.Radio(["sí", "no"], label="¿Convive con el Agresor?")
141
+ consumo_sustancias = gr.Radio(["sí", "no"], label="¿Hay Consumo de Sustancias?")
142
+ apoyo_familiar = gr.Radio(["sí", "no"], label="¿Tiene Apoyo Familiar?")
143
+ descripcion = gr.Textbox(lines=5, placeholder="Describa detalladamente el caso de violencia...", label="Descripción del Caso")
144
+ boton = gr.Button("🔍 Analizar Caso")
145
+
146
+ with gr.Column():
147
+ tipo_violencia_out = gr.Textbox(label="🛑 Tipo de Violencia Detectada", interactive=False)
148
+ riesgo_out = gr.Textbox(label="⚠️ Nivel de Riesgo Estimado", interactive=False)
149
+ medida_out = gr.Textbox(label="🧾 Tipo de Medida Cautelar Sugerida", interactive=False)
150
+ recomendacion_out = gr.Textbox(label="📋 Auto de Medida Provisional", lines=12, interactive=False)
151
+
152
+ boton.click(
153
+ fn=predecir_con_recomendacion,
154
+ inputs=[edad, genero, hijos, convivencia_agresor, consumo_sustancias, apoyo_familiar, descripcion],
155
+ outputs=[tipo_violencia_out, riesgo_out, medida_out, recomendacion_out]
156
+ )
157
+
158
+ interfaz.launch()
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ transformers==4.40.2
2
+ torch==2.1.2
3
+ sentence-transformers==2.6.1
4
+ scikit-learn==1.3.2
5
+ joblib==1.3.2
6
+ gradio==4.29.0
7
+ numpy==1.26.4
8
+ sentencepiece==0.1.99
9
+ accelerate==0.28.0
10
+