File size: 10,384 Bytes
f03a8aa
86019ac
554f4ad
08d0f2d
b11aa41
554f4ad
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b7c3ab
04a4aae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
641bac1
127deef
554f4ad
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df7a3d1
554f4ad
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e7f4934
137edac
554f4ad
 
 
 
 
 
 
 
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import os
import asyncio
import requests # Necesario para interactuar con la API de NVIDIA
import gradio as gr

# --- CONFIGURACIÓN DE LA API DE NVIDIA ---
# 1. Obtener la Clave API de NVIDIA de forma segura desde los Secrets del Space
NVIDIA_API_KEY = os.getenv("NVIDIA_API_KEY")
if not NVIDIA_API_KEY:
    # En un Space, si la clave no está configurada, la app puede fallar al inicio
    # o puedes manejarlo mostrando un mensaje de error en la UI.
    # Aquí, simplemente imprimiremos un aviso y la función de API fallará.
    print("ADVERTENCIA: La variable de entorno NVIDIA_API_KEY no está configurada en los Secrets del Space.")
    # Podrías lanzar un error aquí si prefieres que la app no inicie sin la clave:
    # raise ValueError("La clave NVIDIA_API_KEY no está configurada en los Secrets del Space.")

NVIDIA_API_URL = "https://integrate.api.nvidia.com/v1/chat/completions"
NVIDIA_MODEL_NAME = "qwen/qwen3-235b-a22b" # El modelo que especificaste

# --- DIRECTIVA DE INSTRUCCIÓN (Rol del Agente) ---
instruction = """
Actúa como un Ministro experto de la Excelentísima Corte Suprema de Chile, con profunda especialización en Derecho de Familia y dominio absoluto de las Leyes N° 19.968 y N° 14.908, la jurisprudencia relevante y los principios rectores (interés superior del niño/a/adolescente, corresponsabilidad, etc.).
Tu tarea es perfeccionar exclusivamente la **forma** (redacción, estilo, sintaxis, gramática) de un borrador de resolución judicial en materia de familia que se te proporcionará, sin alterar su contenido sustantivo. El objetivo es que el texto final refleje la máxima claridad expositiva, precisión jurídica y formalidad protocolar, emulando los más altos estándares de las resoluciones de la Corte Suprema.
**PRINCIPIO FUNDAMENTAL:** Tu intervención se limita estrictamente a la **forma** del documento. El **fondo** (contenido sustantivo) es intocable.
**RESTRICCIONES INALTERABLES:**
1.  **Estructura Intacta:** NO modifiques la estructura del documento (secciones como VISTOS, CONSIDERANDOS, RESUELVO; numeración; orden de párrafos; títulos). Esta restricción es absoluta.
2.  **Hechos Inmodificables:** NO alteres los hechos establecidos como probados (fechas, nombres, RUTs, descripciones, citas).
3.  **Razonamiento Jurídico Intocable:** NO modifiques, complementes ni suprimas la argumentación legal, la interpretación normativa o las conclusiones jurídicas del borrador original.
4.  **Sin Añadidos:** NO agregues información nueva de ningún tipo (incluida jurisprudencia no presente en el original). Trabaja únicamente con el texto proporcionado.
**GUÍA DE ESTILO IMPERATIVA (Estilo Corte Suprema):**
*   **Formalidad Extrema:** Lenguaje rigurosamente formal, institucional y protocolar. Absolutamente impersonal (tercera persona o plural mayestático). Cero coloquialismos o subjetividad.
*   **Precisión Técnica:** Utiliza terminología jurídica específica e inequívoca del Derecho de Familia chileno y las leyes mencionadas.
*   **Tono y Sintaxis:** Tono autoritario, neutral y solemne. Sintaxis elaborada, precisa, con uso adecuado de conectores lógicos ("Atendido que", "Teniendo presente que", "En consecuencia") y construcciones propias del lenguaje judicial chileno.
*   **Fórmulas y Términos Jurídicos:** Emplea con naturalidad y pertinencia, donde el contexto lo requiera para mayor precisión y autenticidad, fórmulas protocolares ("Notifíquese por el estado diario", "Téngase presente", "A lo principal") y términos jurídicos específicos como "A sus antecedentes", "Ha lugar" / "No ha lugar", "Estese a lo resuelto", "Previo a proveer", "En mérito de autos", "Solicítese lo que en derecho corresponda", "Venga en forma", entre otros relevantes.
*   **Verbos Imperativos:** Usa el modo imperativo formal para decisiones y órdenes ("Notifíquese", "Cítese", "Regístrese", "Archívese", "Ofíciese", "Cúmplase").
**FORMATO DE SALIDA:**
Proporciona únicamente el texto completo del borrador de la resolución judicial, revisado y perfeccionado según todas las instrucciones anteriores. No incluyas comentarios, explicaciones ni encabezados adicionales.
"""

# --- FUNCIÓN PARA LLAMAR A LA API DE NVIDIA ---
async def call_nvidia_api(user_prompt: str, system_instruction: str) -> str:
    """
    Realiza una solicitud a la API de NVIDIA para generar contenido.
    """
    if not NVIDIA_API_KEY:
        return "Error: La clave API de NVIDIA no está configurada. Por favor, añádela a los 'Secrets' de este Space."

    headers = {
        "accept": "application/json",
        "content-type": "application/json",
        "Authorization": f"Bearer {NVIDIA_API_KEY}"
    }

    payload = {
        "model": NVIDIA_MODEL_NAME,
        "temperature": 0.2,
        "top_p": 0.7,
        "max_tokens": 8192,
        "seed": None,
        "stream": False,
        "messages": [
            {"role": "system", "content": system_instruction},
            {"role": "user", "content": user_prompt}
        ]
    }

    try:
        # Ejecuta la solicitud síncrona en un hilo separado para no bloquear asyncio
        loop = asyncio.get_event_loop()
        response = await loop.run_in_executor(None, lambda: requests.post(NVIDIA_API_URL, json=payload, headers=headers, timeout=60)) # Añadido timeout
        response.raise_for_status()
        data = response.json()

        if data and 'choices' in data and len(data['choices']) > 0 and 'message' in data['choices'][0] and 'content' in data['choices'][0]['message']:
            return data['choices'][0]['message']['content']
        else:
            return f"Error: Formato de respuesta inesperado de la API de NVIDIA. Respuesta: {str(data)[:500]}" # Limita la longitud del error

    except requests.exceptions.HTTPError as errh:
        return f"Error HTTP de la API de NVIDIA: {errh}\nDetalle: {str(response.text)[:500]}"
    except requests.exceptions.ConnectionError as errc:
        return f"Error de conexión con la API de NVIDIA: {errc}"
    except requests.exceptions.Timeout as errt:
        return f"Tiempo de espera agotado con la API de NVIDIA: {errt}"
    except requests.exceptions.RequestException as err:
        return f"Error al realizar la solicitud a la API de NVIDIA: {err}"
    except Exception as e:
        return f"Error inesperado durante la llamada a la API: {e}"

# --- FUNCIÓN PRINCIPAL DE PREDICCIÓN PARA GRADIO ---
async def predict(borrador: str) -> str:
    """
    Función que recibe el borrador judicial y lo envía a la API de NVIDIA para su perfeccionamiento.
    """
    if not borrador.strip():
        return "Por favor, introduce un borrador judicial para perfeccionar."
    if not NVIDIA_API_KEY: # Comprobación adicional antes de llamar a la API
        return "Error: La clave API de NVIDIA no está configurada en los Secrets del Space. No se puede procesar la solicitud."

    improved_text = await call_nvidia_api(borrador, instruction)
    return improved_text

# --- INTERFAZ DE GRADIO ---
with gr.Blocks(theme=gr.themes.Soft()) as demo: # Puedes probar diferentes temas de Gradio
    gr.Markdown(
        """
        # ⚖️ Perfeccionador de Resoluciones Judiciales (Chile) ⚖️
        **Estilo Excelentísima Corte Suprema**

        Esta herramienta utiliza el modelo `qwen/qwen3-235b-a22b` de NVIDIA para refinar la forma de borradores de resoluciones judiciales en materia de familia.
        **Importante:** El contenido sustantivo (hechos, razonamiento, decisión) del borrador original **no será alterado**. La IA se enfoca exclusivamente en el lenguaje, la sintaxis y la formalidad protocolar.
        """
    )

    with gr.Row():
        with gr.Column(scale=2):
            borrador_input = gr.Textbox(
                label="📄 Borrador judicial (texto a perfeccionar)",
                placeholder="Pega aquí el borrador de la resolución judicial...",
                lines=20,
                interactive=True
            )
        with gr.Column(scale=3): # Damos más espacio a la salida
            output_text = gr.Textbox(
                label="✨ Resultado perfeccionado (estilo Corte Suprema)",
                placeholder="El texto corregido por el modelo aparecerá aquí...",
                lines=20,
                interactive=False,
                show_copy_button=True
            )

    submit_btn = gr.Button("Perfeccionar Borrador", variant="primary")

    gr.Examples(
        examples=[
            [
                """VISTOS:
Se presenta demanda de alimentos menores por Juan Perez contra Maria Soto. El demandante alega que no puede trabajar. La demandada dice que sí puede.
CONSIDERANDOS:
1. Que el niño necesita plata.
2. Que el papa tiene que pagar.
RESUELVO:
Pague $100.000. Notifiquese."""
            ],
            [
                """SENTENCIA:
Causa RIT F-123-2023.
En Santiago, a cinco de enero de dos mil veinticuatro.
VISTOS:
Que doña CARLA ANDREA MUÑOZ SOTO, RUT Nº 15.XXX.XXX-X, interpuso demanda de divorcio unilateral por cese de convivencia en contra de don PEDRO ANTONIO PAVEZ LILLO, RUT Nº 14.XXX.XXX-X. Funda su acción en que contrajeron matrimonio el 10 de marzo de 2010, y que el cese de convivencia se produjo en julio de 2018, sin que se haya reanudado la vida en común.
CONSIDERANDO:
PRIMERO: Que la parte demandante acompañó certificado de matrimonio y acta de cese de convivencia.
SEGUNDO: Que el demandado no contestó la demanda.
TERCERO: Que se cumplen los requisitos del art. 55 de la Ley de Matrimonio Civil.
POR TANTO, SE DECLARA:
Que se acoge la demanda y se declara el divorcio.
Ofíciese al Registro Civil.
Cúmplase."""
            ],
        ],
        inputs=borrador_input,
        outputs=output_text,
        fn=predict, # La función que se llamará con los ejemplos
        cache_examples=False, # Desactiva el cache si los resultados pueden variar o para asegurar la última versión del prompt
    )

    submit_btn.click(fn=predict, inputs=borrador_input, outputs=output_text, api_name="predict_sync") # api_name opcional

# --- LANZAR LA INTERFAZ DE GRADIO ---
# Cuando se ejecuta en Hugging Face Spaces, no necesitas if __name__ == "__main__":
# Gradio lo maneja automáticamente.
# demo.launch() sin argumentos es suficiente para Spaces.
# Si quisieras habilitar la cola para manejar múltiples usuarios: demo.launch(enable_queue=True)
demo.launch()