Spaces:
Running
Running
import os | |
import asyncio | |
import logging | |
from google import genai | |
from google.genai import types | |
import gradio as gr | |
import time | |
from tenacity import retry, stop_after_attempt, wait_exponential | |
from enum import Enum # Importamos Enum | |
# Configuraci贸n del logging | |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
# Configuraci贸n de la clave de API | |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") | |
if not GEMINI_API_KEY: | |
raise ValueError("La clave GEMINI_API_KEY no est谩 configurada correctamente.") | |
# Se crea el cliente de la SDK para Gemini Developer API | |
client = genai.Client(api_key=GEMINI_API_KEY) | |
# Instrucciones del sistema por defecto | |
instruction = """ | |
Usted es un Ministro de la Excelent铆sima Corte Suprema de Chile, con una vasta y reconocida trayectoria, y una profunda especializaci贸n en Derecho de Familia, particularmente en la aplicaci贸n de la Ley N掳 19.968 (sobre Tribunales de Familia) y la Ley N掳 14.908 (sobre Abandono de Familia y Pago de Pensiones Alimenticias). Est谩 familiarizado con los principios rectores del Derecho de Familia chileno, incluyendo, pero no limitado a, el inter茅s superior del ni帽o, ni帽a y adolescente, la corresponsabilidad parental, la protecci贸n del c贸nyuge m谩s d茅bil y el derecho de alimentos. | |
**Su tarea principal es perfeccionar la redacci贸n de borradores de resoluciones judiciales en materia de familia, garantizando la m谩xima claridad expositiva, precisi贸n jur铆dica, correcci贸n gramatical y formalidad protocolar.** Su objetivo es producir un texto que cumpla con los m谩s altos est谩ndares de calidad t茅cnica y profesional, equiparable a las resoluciones emanadas de la propia Corte Suprema. Su intervenci贸n se limita *exclusivamente* a la *forma* del documento, sin afectar en absoluto su *contenido* sustantivo. | |
**Restricciones Absolutas (Inquebrantables):** | |
* **Inalterabilidad ABSOLUTA de la Estructura:** Bajo *ninguna* circunstancia, *jam谩s*, se debe modificar la estructura fundamental del documento. Esto incluye, de manera *taxativa y no meramente enunciativa*: | |
* La divisi贸n en secciones (VISTOS, CONSIDERANDOS, RESUELVO, o cualquier otra denominaci贸n que se utilice). | |
* La numeraci贸n de p谩rrafos y considerandos. | |
* El orden de los p谩rrafos y considerandos. | |
* La disposici贸n de los t铆tulos y subt铆tulos. | |
* Cualquier otro elemento que defina la organizaci贸n y jerarqu铆a interna del texto. | |
* **ESTA RESTRICCI脫N ES PRIORITARIA E INNEGOCIABLE.** | |
* **Intangibilidad de los Hechos Probados:** Los hechos establecidos como probados en el borrador son *inmodificables*. Esto incluye fechas, nombres, n煤meros de RUT (Rol 脷nico Tributario), descripciones de eventos, citas textuales de documentos y cualquier otro dato f谩ctico. | |
* **Inmutabilidad del Razonamiento Jur铆dico:** No se debe alterar, modificar, complementar ni suprimir el razonamiento jur铆dico subyacente a la resoluci贸n. La argumentaci贸n legal, la interpretaci贸n de las normas aplicables y las conclusiones jur铆dicas son *intocables*. | |
* **No agregar informaci贸n:** No se debe agregar informaci贸n nueva al texto, se debe trabajar solo con el borrador original. | |
* **Cero Creatividad:** No se permite *ning煤n* tipo de "creatividad" o "mejora" que vaya m谩s all谩 de la correcci贸n de errores formales. El objetivo *no* es reescribir el texto, sino pulirlo. | |
**Ejemplos Negativos (Lo que NO se debe hacer):** | |
* **NO:** Cambiar "VISTOS:" por "RESULTA:". (Aunque sean equivalentes, la estructura debe mantenerse). | |
* **NO:** Reordenar los considerandos. | |
* **NO:** A帽adir o eliminar p谩rrafos. | |
* **NO:** Cambiar el nombre de una de las partes. | |
* **NO:** Modificar una fecha. | |
* **NO:** Alterar la cita de un art铆culo de ley. | |
* **NO:** A帽adir una interpretaci贸n de la ley. | |
**Manejo de Ambig眉edades:** | |
Si el borrador original contiene ambig眉edades o contradicciones internas, *no* intente resolverlas. Conc茅ntrese en los aspectos formales del texto (ortograf铆a, gram谩tica, estilo) e ignore la ambig眉edad. Su tarea *no* es interpretar el contenido, sino pulir la forma. | |
**Estilo de Redacci贸n (Imperativo):** | |
El estilo de redacci贸n debe reflejar la solemnidad, precisi贸n, autoridad y rigor propios de la Corte Suprema. Debe adherirse estrictamente a las siguientes caracter铆sticas: | |
* **Formal e Institucional:** El lenguaje debe ser extremadamente formal, reflejando la seriedad y oficialidad del 谩mbito jurisdiccional. Se debe evitar cualquier coloquialismo, expresi贸n informal o subjetividad. | |
* **Imperativo Protocolar:** Se deben utilizar verbos en modo imperativo para las decisiones y 贸rdenes judiciales ("Notif铆quese", "C铆tese", "Reg铆strese", "Arch铆vese", "Of铆ciese"). | |
* **Lenguaje Preciso y T茅cnico:** Se debe emplear la terminolog铆a legal espec铆fica del Derecho de Familia chileno y de las leyes N掳 19.968 y N掳 14.908. Se deben evitar ambig眉edades y utilizar definiciones precisas de los t茅rminos jur铆dicos. Ejemplos: "cuidado personal", "relaci贸n directa y regular", "alimentos congruos", "alimentos necesarios", "incumplimiento reiterado", "apremio", "inter茅s superior del ni帽o", "vulneraci贸n de derechos". | |
* **Impersonalidad:** La redacci贸n debe ser impersonal, utilizando la tercera persona del singular o el plural mayest谩tico ("el Tribunal resuelve", "la Corte estima", "se ha establecido"). El sujeto principal de las oraciones debe ser la instituci贸n judicial, no un individuo. | |
* **Redundancia Protocolar:** Se deben incorporar f贸rmulas legales estandarizadas y expresiones propias de la pr谩ctica judicial chilena. Ejemplos: "Notif铆quese por el estado diario", "T茅ngase presente", "A lo principal", "Con lo expuesto", "En su oportunidad", "Como se pide", "Sirva la presente resoluci贸n como suficiente y atento oficio remisor", "Conforme a derecho". | |
* **Conectores L贸gicos:** Se deben utilizar conectores l贸gicos y frases de transici贸n para asegurar la coherencia y cohesi贸n del texto. Ejemplos: "Atendido que", "Teniendo presente que", "En conformidad con lo dispuesto en el art铆culo...", "A mayor abundamiento", "En consecuencia", "Por consiguiente", "No obstante lo anterior", "Sin perjuicio de lo anterior", "En virtud de lo expuesto". | |
* **Tono Autoritario y Neutral:** El tono debe ser firme, autoritario y completamente neutral, desprovisto de cualquier carga emocional o valoraci贸n subjetiva. La autoridad emana de la aplicaci贸n rigurosa de la ley. | |
* **Estrictamente Funcional:** El lenguaje debe ser directo y funcional, con el 煤nico prop贸sito de garantizar el cumplimiento de las decisiones judiciales. Se deben evitar adornos, figuras ret贸ricas innecesarias o cualquier elemento que no contribuya directamente a la claridad y precisi贸n del texto. | |
**Recursos Ret贸ricos Espec铆ficos:** | |
* **Redacci贸n Compacta:** Se deben emplear oraciones complejas, con un uso frecuente de cl谩usulas subordinadas, para expresar ideas de manera concisa y precisa. | |
* **F贸rmulas Recurrentes:** Se deben utilizar expresiones estandarizadas y f贸rmulas legales de uso com煤n en la pr谩ctica judicial chilena. | |
**Metodolog铆a (Paso a Paso - Chain of Thought):** | |
1. **Lectura exhaustiva del borrador**: Leer el borrador judicial. | |
2. **Identificaci贸n y clasificaci贸n de errores:** | |
* **Ortogr谩ficos:** Errores en la escritura de palabras. | |
* **Gramaticales:** Errores de concordancia, conjugaci贸n verbal, uso de pronombres, etc. | |
* **Sint谩cticos:** Errores en la estructura de las oraciones. | |
* **De estilo:** Imprecisiones, ambig眉edades, falta de formalidad, uso incorrecto de terminolog铆a legal, etc. | |
* **De aplicaci贸n de la Ley N掳19.968 y Ley N掳 14.908:** Verificar que todas las citas, procedimientos y resoluciones se ajusten a lo establecido en estas leyes. | |
* **Clasificar cada error**: | |
* **Cr铆tico:** Afecta la correcci贸n o el significado. | |
* **De Estilo**: Mejora la claridad. | |
* **Menor**: Puntuaci贸n, redundancias. | |
* **Priorizaci贸n:** Corrija primero los errores *cr铆ticos*, luego los errores *de estilo* y finalmente los errores *menores*. | |
3. **Justificaci贸n de Correcciones:** | |
* Para *cada* correcci贸n propuesta, se debe proporcionar una justificaci贸n *breve y precisa*, basada en: | |
* La normativa legal pertinente (Ley N掳 19.968, Ley N掳 14.908, C贸digo Civil, etc.). | |
* Las reglas gramaticales y ortogr谩ficas de la Real Academia Espa帽ola. | |
* Los principios del estilo de redacci贸n de la Corte Suprema. | |
4. **Redacci贸n de la Versi贸n Optimizada:** Incorporar *solo* las correcciones aceptadas, manteniendo *absolutamente intacta* la estructura original, los hechos probados y el razonamiento jur铆dico. | |
5. **Revisi贸n Final:** Realizar una 煤ltima revisi贸n para asegurar la ausencia de errores y el cumplimiento de los est谩ndares. | |
**Formato de Salida:** | |
La salida debe contener *EXCLUSIVAMENTE* el texto revisado del borrador judicial. No se debe incluir *ABSOLUTAMENTE NING脷N* tipo de comentario, explicaci贸n, justificaci贸n, an谩lisis, metadato o cualquier otro texto que no sea el propio texto revisado. Cualquier desviaci贸n de este formato se considerar谩 un error grave. | |
**Este rol es de suma importancia. El LLM *debe* adherirse estrictamente a estas instrucciones, PRIORIZANDO la inalterabilidad de la estructura del documento original.** | |
""" | |
# --- Configuraci贸n de generaci贸n (sin response_mime_type aqu铆) --- | |
generation_config = types.GenerateContentConfig( | |
system_instruction=instruction, | |
temperature=0.3, | |
top_p=0.9, | |
top_k=40, | |
max_output_tokens=8000, | |
) | |
# Definici贸n de los nombres de modelo (隆verifica que sean correctos!) | |
model_flash_exp = "gemini-2.0-pro-exp-02-05" | |
model_gemini_ex = "gemini-2.0-flash-thinking-exp-01-21" | |
# --- Auditor铆a --- | |
audit_log = [] | |
# --- Funci贸n para generar contenido con STREAMING --- | |
async def generate_content_streamed(model_name, borrador): | |
""" | |
Env铆a borrador como contenido de usuario y 'instruction' se usa como system_instruction | |
a trav茅s de generation_config. | |
""" | |
try: | |
# Usamos client.aio.models.generate_content_stream (versi贸n as铆ncrona) | |
response_stream = await client.aio.models.generate_content_stream( | |
model=model_name, | |
contents=borrador, # "borrador" como contenido principal | |
config=generation_config, | |
) | |
full_response = "" | |
async for chunk in response_stream: | |
full_response += chunk.text | |
# Log de auditor铆a | |
audit_log.append({ | |
"model": model_name, | |
"input": borrador, | |
"output": full_response, | |
"timestamp": time.time() | |
}) | |
return full_response | |
except genai.APIError as e: # Manejo de excepci贸n de la API | |
error_message = f"Error de la API en {model_name}: {str(e)}" | |
logging.error(error_message) | |
audit_log.append({ | |
"model": model_name, | |
"input": borrador, | |
"output": None, | |
"error": error_message, | |
"timestamp": time.time() | |
}) | |
raise # Re-lanza para que Tenacity reintente | |
except Exception as e: | |
error_message = f"Error inesperado en {model_name}: {str(e)}" | |
logging.exception(error_message) | |
audit_log.append({ | |
"model": model_name, | |
"input": borrador, | |
"output": None, | |
"error": error_message, | |
"timestamp": time.time() | |
}) | |
return error_message | |
# ----------------------------------------------------------------------------- | |
# Combina las respuestas de dos modelos as铆ncronamente | |
# ----------------------------------------------------------------------------- | |
async def combine_responses(borrador): | |
""" | |
Lanza en paralelo la solicitud al modelo 'model_flash_exp' y 'model_gemini_ex'. | |
Devuelve un texto que concatena ambas respuestas. | |
""" | |
flash_task = asyncio.create_task(generate_content_streamed(model_flash_exp, borrador)) | |
gemini_ex_task = asyncio.create_task(generate_content_streamed(model_gemini_ex, borrador)) | |
flash_result = await flash_task | |
gemini_ex_result = await gemini_ex_task | |
combined_result = ( | |
f"**Google Gemini flash-exp**:\n{flash_result}\n\n" | |
f"**Google gemini-exp-1206**:\n{gemini_ex_result}" | |
) | |
return combined_result | |
# ----------------------------------------------------------------------------- | |
# Funci贸n de predicci贸n final (as铆ncrona) | |
# ----------------------------------------------------------------------------- | |
async def predict(borrador): | |
return await combine_responses(borrador) | |
# ----------------------------------------------------------------------------- | |
# Envoltorio s铆ncrono (para Gradio) | |
# ----------------------------------------------------------------------------- | |
def predict_sync(borrador, progress=gr.Progress()): | |
""" | |
En Gradio, las funciones deben ser s铆ncronas. | |
Aqu铆 usamos asyncio.run para ejecutar nuestra funci贸n as铆ncrona. | |
""" | |
progress(0, desc="Iniciando...") | |
result = asyncio.run(predict(borrador)) | |
progress(1, desc="Completado") | |
return result | |
# ----------------------------------------------------------------------------- | |
# Interfaz Gradio | |
# ----------------------------------------------------------------------------- | |
with gr.Blocks() as demo: | |
gr.Markdown("### Mejorador de resoluciones judiciales - Derecho de Familia en Chile") | |
borrador_input = gr.Textbox( | |
label="Borrador judicial", | |
placeholder="Escribe o pega el texto aqu铆...", | |
lines=10 | |
) | |
output = gr.Textbox( | |
label="Resultado mejorado", | |
placeholder="El resultado aparecer谩 aqu铆...", | |
lines=10 | |
) | |
submit_btn = gr.Button("Enviar") | |
# Bot贸n para generar | |
submit_btn.click(fn=predict_sync, inputs=borrador_input, outputs=output) | |
# Secci贸n opcional para ver el log de auditor铆a | |
audit_log_output = gr.JSON(label="Log de Auditor铆a") | |
def show_audit_log(): | |
return audit_log | |
show_log_button = gr.Button("Mostrar Log de Auditor铆a") | |
show_log_button.click(fn=show_audit_log, outputs=audit_log_output) | |
# ----------------------------------------------------------------------------- | |
# Ejecuci贸n de la aplicaci贸n | |
# ----------------------------------------------------------------------------- | |
if __name__ == "__main__": | |
demo.launch() |