vcasas commited on
Commit
5a62acc
·
verified ·
1 Parent(s): 9a6554e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +179 -77
app.py CHANGED
@@ -3,63 +3,126 @@ import gradio as gr
3
  from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
4
  from dotenv import load_dotenv
5
 
6
- # Cargar variables de entorno
7
- # load_dotenv()
8
-
9
- # Sistema de prompt mejorado (igual que antes)
10
- SYSTEM_PROMPT = """Responde con precisión sobre el delito que se consulta, citando la legislación vigente en España y proporcionando contexto legal actualizado:
11
- - Menciona siempre los artículos específicos del Código Penal español al inicio.
12
- - Si el delito ha sido modificado en reformas recientes, indica en qué consistió la reforma.
13
- - Define el **tipo básico del delito**.
14
- - Explica los **subtipos agravados y atenuados** si existen.
15
- - Cita los artículos correspondientes.
16
- - Menciona sentencias recientes del Tribunal Supremo cuando sea posible."""
17
-
18
- # Cargar modelo y tokenizador de Hugging Face
19
- MODEL_NAME = "EleutherAI/gpt-neo-2.7B" # Puedes cambiarlo por otro modelo (ej: "tiiuae/falcon-7b" -ram exceeded- o "meta-llama/Llama-2-7b-chat-hf" -se debe solictar acesso en meta ai-)
20
- tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
21
- model = AutoModelForCausalLM.from_pretrained(MODEL_NAME)
22
-
23
- # Crear pipeline de generación de texto
24
- generator = pipeline("text-generation", model=model, tokenizer=tokenizer)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  # Historial global de chat
27
  chat_history = []
28
 
 
 
 
 
29
  def consulta_penalista(mensaje, tipo_consulta):
30
  """Procesa una consulta jurídica y devuelve la respuesta del modelo."""
31
  global chat_history
32
 
33
- # Crear un prompt que indique directamente qué responder
34
- prompt = f"""A continuación hay una consulta jurídica sobre el sistema penal español.
35
-
36
- Consulta: {mensaje}
37
-
38
- Respuesta sobre el delito consultado según la legislación española:
39
- - Artículos del Código Penal español: """
40
 
41
  try:
42
- # Crear el prompt completo (sistema + historial)
43
- # prompt = SYSTEM_PROMPT + "\n\n" + "\n".join([msg["content"] for msg in chat_history])
44
- prompt = SYSTEM_PROMPT + mensaje
45
 
46
  # Generar respuesta con el modelo
47
  respuesta = generator(
48
  prompt,
49
- max_length=1000, # Longitud máxima de la respuesta (antes 500)
50
- num_return_sequences=1, # Número de respuestas a generar
51
-
52
- # (NUEVO)
53
- temperature=0.5, # Controlar la creatividad (valores más bajos = más determinista)
54
- top_p=0.9, # Usar muestreo de núcleo (nucleus sampling)
 
55
  truncation=True,
56
- pad_token_id=tokenizer.eos_token_id,
57
- do_sample=True
58
  )
59
 
60
  respuesta_texto = respuesta[0]["generated_text"]
61
 
62
- # Añadir la respuesta del asistente al historial
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  chat_history.append({"role": "assistant", "content": respuesta_texto})
64
 
65
  # Formatear el historial para mostrarlo en la interfaz
@@ -71,7 +134,9 @@ Respuesta sobre el delito consultado según la legislación española:
71
  return respuesta_texto, historial_formateado
72
 
73
  except Exception as e:
74
- return f"Error al procesar la solicitud: {str(e)}", "\n".join(str(m) for m in chat_history)
 
 
75
 
76
  def limpiar_historial():
77
  """Limpia el historial de conversación."""
@@ -79,44 +144,81 @@ def limpiar_historial():
79
  chat_history = []
80
  return "", "Historial limpiado."
81
 
82
- # Interfaz de usuario con Gradio (igual que antes)
83
- interfaz = gr.Blocks()
84
-
85
- with interfaz:
86
- gr.Markdown("# ⚖️ Asistente Jurídico Penal")
87
- gr.Markdown("Realiza consultas sobre derecho penal y recibe respuestas fundamentadas.")
88
 
89
- tipo_consulta = gr.Radio(
90
- choices=["Asesoría General", "Jurisprudencia", "Redacción de Documentos"],
91
- label="Tipo de Consulta",
92
- value="Asesoría General"
93
- )
94
-
95
- entrada_texto = gr.Textbox(
96
- label="Pregunta Jurídica",
97
- placeholder="Escribe tu consulta aquí..."
98
- )
99
-
100
- with gr.Row():
101
- boton_enviar = gr.Button("Consultar")
102
- boton_limpiar = gr.Button("Limpiar Historial")
103
-
104
- salida_texto = gr.Textbox(label="Respuesta")
105
- historial_texto = gr.Textbox(
106
- label="Historial de Conversación",
107
- interactive=False,
108
- lines=10
109
- )
110
-
111
- boton_enviar.click(
112
- consulta_penalista,
113
- inputs=[entrada_texto, tipo_consulta],
114
- outputs=[salida_texto, historial_texto]
115
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
- boton_limpiar.click(
118
- limpiar_historial,
119
- outputs=[salida_texto, historial_texto]
120
- )
121
 
122
- interfaz.launch()
 
 
 
 
3
  from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
4
  from dotenv import load_dotenv
5
 
6
+ # Sistema de prompt mejorado
7
+ SYSTEM_PROMPT = """Tu tarea es proporcionar información precisa sobre delitos según el Código Penal español.
8
+
9
+ Has sido entrenado con conocimientos jurídicos especializados y debes responder siguiendo este formato:
10
+
11
+ 1. ARTÍCULOS APLICABLES: [Enumera los artículos relevantes del Código Penal]
12
+ 2. TIPO BÁSICO DEL DELITO: [Describe el tipo básico]
13
+ 3. SUBTIPOS Y MODALIDADES: [Describe los subtipos agravados o atenuados]
14
+ 4. JURISPRUDENCIA RELEVANTE: [Menciona sentencias recientes del Tribunal Supremo]
15
+ 5. REFORMAS LEGISLATIVAS: [Indica si ha habido reformas recientes]
16
+
17
+ A continuación te daré una consulta sobre un delito específico y debes responder según el formato anterior."""
18
+
19
+ # Definir ejemplos de pares pregunta-respuesta para few-shot learning
20
+ EJEMPLOS = """
21
+ Consulta: Delito de robo
22
+
23
+ Respuesta:
24
+ 1. ARTÍCULOS APLICABLES: Arts. 237-242 del Código Penal español.
25
+ 2. TIPO BÁSICO DEL DELITO: El robo se define en el artículo 237 como la apropiación de cosas muebles ajenas empleando fuerza en las cosas o violencia/intimidación en las personas.
26
+ 3. SUBTIPOS Y MODALIDADES: El artículo 240 establece que el robo con fuerza se castiga con pena de prisión de 1 a 3 años. El robo con violencia/intimidación (art. 242) se castiga con pena de 2 a 5 años.
27
+ 4. JURISPRUDENCIA RELEVANTE: STS 382/2023 estableció criterios para diferenciar entre robo y hurto.
28
+ 5. REFORMAS LEGISLATIVAS: La última modificación significativa fue con la LO 1/2015, que modificó las penas.
29
+
30
+ Consulta: Delito de estafa
31
+
32
+ Respuesta:
33
+ 1. ARTÍCULOS APLICABLES: Arts. 248-251 bis del Código Penal español.
34
+ 2. TIPO BÁSICO DEL DELITO: La estafa se define en el artículo 248 como la utilización de engaño bastante para producir error en otro, induciéndolo a realizar un acto de disposición patrimonial en perjuicio propio o ajeno.
35
+ 3. SUBTIPOS Y MODALIDADES: Las estafas agravadas (art. 250) prevén penas de 1 a 6 años cuando el valor supera los 50.000€ o afecta a vivienda habitual.
36
+ 4. JURISPRUDENCIA RELEVANTE: STS 420/2022 clarificó los requisitos del engaño en estafas digitales.
37
+ 5. REFORMAS LEGISLATIVAS: La LO 1/2019 introdujo nuevas modalidades de estafa informática.
38
+ """
39
+
40
+ # Cargar modelo y tokenizador
41
+ # Cambio a un modelo con mejor rendimiento para tareas jurídicas
42
+ MODEL_NAME = "EleutherAI/gpt-neo-2.7B" # Mantenemos este por compatibilidad, pero ideal cambiarlo si es posible
43
+
44
+ try:
45
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
46
+ model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto")
47
+
48
+ # Crear pipeline de generación de texto
49
+ generator = pipeline(
50
+ "text-generation",
51
+ model=model,
52
+ tokenizer=tokenizer,
53
+ device_map="auto" # Usar GPU si está disponible
54
+ )
55
+
56
+ modelo_cargado = True
57
+ error_modelo = None
58
+
59
+ except Exception as e:
60
+ modelo_cargado = False
61
+ error_modelo = str(e)
62
 
63
  # Historial global de chat
64
  chat_history = []
65
 
66
+ def construir_prompt(mensaje):
67
+ """Construye un prompt efectivo con few-shot learning para mejorar la respuesta."""
68
+ return f"{SYSTEM_PROMPT}\n\n{EJEMPLOS}\n\nConsulta: {mensaje}\n\nRespuesta:\n1. ARTÍCULOS APLICABLES:"
69
+
70
  def consulta_penalista(mensaje, tipo_consulta):
71
  """Procesa una consulta jurídica y devuelve la respuesta del modelo."""
72
  global chat_history
73
 
74
+ if not modelo_cargado:
75
+ return f"Error al cargar el modelo: {error_modelo}", "El modelo no está disponible."
76
+
77
+ # Añadir mensaje del usuario al historial
78
+ chat_history.append({"role": "user", "content": f"[{tipo_consulta}] {mensaje}"})
 
 
79
 
80
  try:
81
+ # Construir prompt con few-shot learning
82
+ prompt = construir_prompt(mensaje)
 
83
 
84
  # Generar respuesta con el modelo
85
  respuesta = generator(
86
  prompt,
87
+ max_length=1500, # Aumentado para permitir respuestas más completas
88
+ num_return_sequences=1,
89
+ temperature=0.3, # Reducido para mayor coherencia
90
+ top_p=0.85,
91
+ top_k=40,
92
+ repetition_penalty=1.2, # Evita repeticiones
93
+ do_sample=True,
94
  truncation=True,
95
+ pad_token_id=tokenizer.eos_token_id
 
96
  )
97
 
98
  respuesta_texto = respuesta[0]["generated_text"]
99
 
100
+ # Eliminar el prompt de la respuesta generada
101
+ if respuesta_texto.startswith(prompt):
102
+ respuesta_texto = respuesta_texto[len(prompt):].strip()
103
+
104
+ # Limpiar respuesta para evitar repeticiones
105
+ if "1. ARTÍCULOS APLICABLES:" not in respuesta_texto:
106
+ respuesta_texto = "1. ARTÍCULOS APLICABLES:" + respuesta_texto
107
+
108
+ # Limitar la respuesta a 5 secciones si se repite
109
+ secciones = []
110
+ for i, seccion in enumerate(["1. ARTÍCULOS APLICABLES:", "2. TIPO BÁSICO DEL DELITO:",
111
+ "3. SUBTIPOS Y MODALIDADES:", "4. JURISPRUDENCIA RELEVANTE:",
112
+ "5. REFORMAS LEGISLATIVAS:"]):
113
+ if seccion in respuesta_texto:
114
+ inicio = respuesta_texto.find(seccion)
115
+ fin = len(respuesta_texto)
116
+ if i < 4: # Si no es la última sección
117
+ siguiente = respuesta_texto.find(f"{i+2}. ", inicio)
118
+ if siguiente != -1:
119
+ fin = siguiente
120
+ secciones.append(respuesta_texto[inicio:fin])
121
+
122
+ if secciones:
123
+ respuesta_texto = "\n".join(secciones)
124
+
125
+ # Añadir la respuesta al historial
126
  chat_history.append({"role": "assistant", "content": respuesta_texto})
127
 
128
  # Formatear el historial para mostrarlo en la interfaz
 
134
  return respuesta_texto, historial_formateado
135
 
136
  except Exception as e:
137
+ error_msg = f"Error al procesar la solicitud: {str(e)}"
138
+ chat_history.append({"role": "assistant", "content": error_msg})
139
+ return error_msg, "\n\n".join([f"{'Usuario' if msg['role'] == 'user' else 'Asistente'}: {msg['content']}" for msg in chat_history])
140
 
141
  def limpiar_historial():
142
  """Limpia el historial de conversación."""
 
144
  chat_history = []
145
  return "", "Historial limpiado."
146
 
147
+ def iniciar_interfaz():
148
+ """Inicia la interfaz de usuario con Gradio."""
149
+ interfaz = gr.Blocks(theme=gr.themes.Soft())
 
 
 
150
 
151
+ with interfaz:
152
+ gr.Markdown("# ⚖️ Asistente Jurídico Penal Español")
153
+ gr.Markdown("Realiza consultas sobre derecho penal y recibe respuestas fundamentadas en la legislación española.")
154
+
155
+ if not modelo_cargado:
156
+ gr.Markdown(f"⚠️ **Error al cargar el modelo**: {error_modelo}")
157
+ gr.Markdown("Intenta ejecutar el script con un entorno que tenga más memoria o usar un modelo más pequeño.")
158
+
159
+ tipo_consulta = gr.Radio(
160
+ choices=["Delito específico", "Jurisprudencia", "Reforma legislativa"],
161
+ label="Tipo de Consulta",
162
+ value="Delito específico"
163
+ )
164
+
165
+ with gr.Row():
166
+ entrada_texto = gr.Textbox(
167
+ label="Consulta Jurídica",
168
+ placeholder="Ejemplo: Consultar sobre el delito de robo con violencia",
169
+ lines=2
170
+ )
171
+
172
+ with gr.Row():
173
+ boton_enviar = gr.Button("📝 Consultar", variant="primary")
174
+ boton_limpiar = gr.Button("🗑️ Limpiar Historial")
175
+
176
+ with gr.Accordion("Consejos para mejores resultados", open=False):
177
+ gr.Markdown("""
178
+ - Sé específico en tu consulta (ej: "Delito de estafa informática" es mejor que "Estafa")
179
+ - Puedes preguntar sobre aspectos específicos como "Agravantes del delito de lesiones"
180
+ - Menciona si buscas información sobre alguna reforma reciente
181
+ """)
182
+
183
+ salida_texto = gr.Textbox(
184
+ label="Respuesta del Asistente",
185
+ lines=12
186
+ )
187
+
188
+ historial_texto = gr.Textbox(
189
+ label="Historial de Conversación",
190
+ interactive=False,
191
+ lines=10,
192
+ visible=True
193
+ )
194
+
195
+ boton_enviar.click(
196
+ consulta_penalista,
197
+ inputs=[entrada_texto, tipo_consulta],
198
+ outputs=[salida_texto, historial_texto]
199
+ )
200
+
201
+ entrada_texto.submit(
202
+ consulta_penalista,
203
+ inputs=[entrada_texto, tipo_consulta],
204
+ outputs=[salida_texto, historial_texto]
205
+ )
206
+
207
+ boton_limpiar.click(
208
+ limpiar_historial,
209
+ outputs=[salida_texto, historial_texto]
210
+ )
211
+
212
+ gr.Markdown("### ℹ️ Información importante")
213
+ gr.Markdown("""
214
+ - Este asistente proporciona información general sobre legislación penal española.
215
+ - No constituye asesoramiento jurídico profesional.
216
+ - Para casos reales, consulte siempre con un abogado.
217
+ """)
218
 
219
+ return interfaz
 
 
 
220
 
221
+ # Ejecutar la aplicación si este script es el principal
222
+ if __name__ == "__main__":
223
+ interfaz = iniciar_interfaz()
224
+ interfaz.launch(share=True) # Usar share=True para crear un enlace público temporal