Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,87 +1,66 @@
|
|
1 |
import os
|
2 |
import gradio as gr
|
3 |
-
from huggingface_hub import
|
4 |
from datetime import datetime
|
5 |
import logging
|
6 |
-
from typing import Dict, List
|
7 |
|
8 |
# Configuração do logging
|
9 |
logging.basicConfig(level=logging.INFO)
|
10 |
logger = logging.getLogger(__name__)
|
11 |
|
12 |
-
# Token já definido no ambiente HF Spaces
|
13 |
-
HF_TOKEN = os.environ.get("HF_TOKEN")
|
14 |
-
|
15 |
class DocumentGenerator:
|
16 |
-
"""Gerencia a geração de documentos usando
|
17 |
|
18 |
def __init__(self):
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
22 |
|
23 |
def generate(self, doc_type: str, context: Dict[str, str]) -> str:
|
24 |
-
"""Gera o documento usando
|
25 |
try:
|
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 |
-
3. Exposição clara e objetiva dos fatos
|
53 |
-
4. Fundamentação jurídica
|
54 |
-
5. Pedidos específicos
|
55 |
-
6. Fechamento formal com data e assinatura
|
56 |
-
|
57 |
-
Utilize linguagem jurídica formal e técnica."""
|
58 |
-
}
|
59 |
-
]
|
60 |
|
61 |
-
#
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
temperature=0.
|
67 |
-
top_p=0.
|
68 |
-
repetition_penalty=1.
|
69 |
-
do_sample=True
|
70 |
-
return_full_text=True
|
71 |
)
|
72 |
|
73 |
-
|
74 |
-
output = self._format_output(result[0]['generated_text'])
|
75 |
|
76 |
-
# Adiciona data atual
|
77 |
-
current_date = datetime.now().strftime('%d de %B de %Y').replace('May', 'Maio').replace('April', 'Abril')
|
78 |
-
if '[DATA]' in output:
|
79 |
-
output = output.replace('[DATA]', current_date)
|
80 |
-
else:
|
81 |
-
output = f"{output}\n\n{context.get('jurisdiction')}, {current_date}"
|
82 |
-
|
83 |
-
return output
|
84 |
-
|
85 |
except Exception as e:
|
86 |
logger.error(f"Erro na geração: {str(e)}")
|
87 |
return f"Erro na geração do documento: {str(e)}"
|
@@ -90,12 +69,20 @@ Utilize linguagem jurídica formal e técnica."""
|
|
90 |
"""Formata o texto gerado"""
|
91 |
if not text:
|
92 |
return "Erro: Nenhum texto gerado"
|
|
|
|
|
|
|
93 |
|
94 |
-
#
|
95 |
lines = [line.strip() for line in text.split('\n') if line.strip()]
|
96 |
formatted_text = '\n\n'.join(lines)
|
97 |
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
99 |
|
100 |
class WebInterface:
|
101 |
"""Interface Gradio para o gerador de documentos"""
|
@@ -115,7 +102,6 @@ class WebInterface:
|
|
115 |
|
116 |
with gr.Row():
|
117 |
with gr.Column():
|
118 |
-
# Seleção do tipo de documento
|
119 |
doc_type = gr.Dropdown(
|
120 |
choices=[
|
121 |
"Habeas Corpus",
|
@@ -129,12 +115,11 @@ class WebInterface:
|
|
129 |
value="Habeas Corpus"
|
130 |
)
|
131 |
|
132 |
-
# Dados do processo
|
133 |
with gr.Group():
|
134 |
gr.Markdown("### Informações do Processo")
|
135 |
client_name = gr.Textbox(
|
136 |
label="Nome do Cliente",
|
137 |
-
placeholder="Nome completo
|
138 |
)
|
139 |
process_number = gr.Textbox(
|
140 |
label="Número do Processo",
|
@@ -149,7 +134,6 @@ class WebInterface:
|
|
149 |
placeholder="Nome da comarca"
|
150 |
)
|
151 |
|
152 |
-
# Detalhes do caso
|
153 |
with gr.Group():
|
154 |
gr.Markdown("### Detalhes do Caso")
|
155 |
facts = gr.Textbox(
|
@@ -160,12 +144,10 @@ class WebInterface:
|
|
160 |
legal_basis = gr.Textbox(
|
161 |
label="Fundamentos Jurídicos",
|
162 |
lines=3,
|
163 |
-
placeholder="
|
164 |
)
|
165 |
|
166 |
-
|
167 |
-
generate_btn = gr.Button("Gerar Documento", variant="primary")
|
168 |
-
clear_btn = gr.Button("Limpar", variant="secondary")
|
169 |
|
170 |
with gr.Column():
|
171 |
output = gr.Textbox(
|
@@ -173,10 +155,8 @@ class WebInterface:
|
|
173 |
lines=30,
|
174 |
show_copy_button=True
|
175 |
)
|
176 |
-
|
177 |
-
status = gr.Textbox(label="Status")
|
178 |
|
179 |
-
# Exemplos
|
180 |
gr.Examples(
|
181 |
examples=[
|
182 |
[
|
@@ -187,24 +167,6 @@ class WebInterface:
|
|
187 |
"São Paulo",
|
188 |
"Paciente preso em flagrante no dia 25/12/2024 por suposto furto simples (art. 155, caput, CP). O paciente é primário, possui residência fixa no distrito da culpa e ocupação lícita comprovada. Não estão presentes os requisitos autorizadores da prisão preventiva.",
|
189 |
"Art. 5º, LXVIII, CF/88; Art. 647 do CPP; Ausência dos requisitos do Art. 312 do CPP. Súmula 308 STJ."
|
190 |
-
],
|
191 |
-
[
|
192 |
-
"Denúncia Criminal",
|
193 |
-
"Pedro Oliveira Lima",
|
194 |
-
"0000456-78.2024.8.26.0000",
|
195 |
-
"TRIBUNAL DE JUSTIÇA DO ESTADO DE SÃO PAULO",
|
196 |
-
"São Paulo",
|
197 |
-
"No dia 20/12/2024, por volta das 14h, na Rua ABC, o denunciado subtraiu para si uma carteira contendo R$ 500,00, mediante grave ameaça exercida com simulacro de arma de fogo.",
|
198 |
-
"Art. 157, caput, do Código Penal. Circunstâncias do Art. 59 do CP desfavoráveis."
|
199 |
-
],
|
200 |
-
[
|
201 |
-
"Alegações Finais",
|
202 |
-
"Maria Santos Costa",
|
203 |
-
"0000789-10.2024.8.26.0000",
|
204 |
-
"TRIBUNAL DE JUSTIÇA DO ESTADO DE SÃO PAULO",
|
205 |
-
"São Paulo",
|
206 |
-
"A ré foi denunciada por suposto furto (art. 155, CP). As provas produzidas nos autos não confirmam a autoria. As testemunhas não reconheceram a acusada e não há registros de câmeras.",
|
207 |
-
"Insuficiência probatória. Art. 386, VII do CPP. Princípio in dubio pro reo."
|
208 |
]
|
209 |
],
|
210 |
inputs=[
|
@@ -220,19 +182,7 @@ class WebInterface:
|
|
220 |
doc_type, client_name, process_number,
|
221 |
court, jurisdiction, facts, legal_basis
|
222 |
],
|
223 |
-
outputs=
|
224 |
-
)
|
225 |
-
|
226 |
-
def clear_fields():
|
227 |
-
return [gr.update(value="") for _ in range(6)] + ["Campos limpos"]
|
228 |
-
|
229 |
-
clear_btn.click(
|
230 |
-
fn=clear_fields,
|
231 |
-
inputs=[],
|
232 |
-
outputs=[
|
233 |
-
client_name, process_number, court,
|
234 |
-
jurisdiction, facts, legal_basis, status
|
235 |
-
]
|
236 |
)
|
237 |
|
238 |
def _generate_document(
|
@@ -240,12 +190,12 @@ class WebInterface:
|
|
240 |
process_number: str, court: str,
|
241 |
jurisdiction: str, facts: str,
|
242 |
legal_basis: str
|
243 |
-
) ->
|
244 |
"""Gera o documento com os parâmetros fornecidos"""
|
|
|
245 |
try:
|
246 |
-
# Validação
|
247 |
if not all([client_name, process_number, facts, legal_basis]):
|
248 |
-
return "Erro: Todos os campos obrigatórios devem ser preenchidos"
|
249 |
|
250 |
context = {
|
251 |
"client_name": client_name,
|
@@ -256,18 +206,15 @@ class WebInterface:
|
|
256 |
"legal_basis": legal_basis
|
257 |
}
|
258 |
|
259 |
-
|
260 |
-
result = self.generator.generate(doc_type, context)
|
261 |
-
|
262 |
-
return result, "✅ Documento gerado com sucesso!"
|
263 |
|
264 |
except Exception as e:
|
265 |
logger.error(f"Erro: {str(e)}")
|
266 |
-
return
|
267 |
|
268 |
def launch(self):
|
269 |
"""Inicia a interface web"""
|
270 |
-
self.app.launch()
|
271 |
|
272 |
if __name__ == "__main__":
|
273 |
interface = WebInterface()
|
|
|
1 |
import os
|
2 |
import gradio as gr
|
3 |
+
from huggingface_hub import HfApi, InferenceApi
|
4 |
from datetime import datetime
|
5 |
import logging
|
6 |
+
from typing import Dict, List
|
7 |
|
8 |
# Configuração do logging
|
9 |
logging.basicConfig(level=logging.INFO)
|
10 |
logger = logging.getLogger(__name__)
|
11 |
|
|
|
|
|
|
|
12 |
class DocumentGenerator:
|
13 |
+
"""Gerencia a geração de documentos usando LLM"""
|
14 |
|
15 |
def __init__(self):
|
16 |
+
# Usa a API key do ambiente
|
17 |
+
self.api = HfApi(token=os.environ.get("HF_TOKEN"))
|
18 |
+
# Usa modelo otimizado para português
|
19 |
+
self.model = "NeuralBeagle14-7B"
|
20 |
|
21 |
def generate(self, doc_type: str, context: Dict[str, str]) -> str:
|
22 |
+
"""Gera o documento usando LLM"""
|
23 |
try:
|
24 |
+
base_prompt = f"""Atue como um advogado criminalista brasileiro experiente.
|
25 |
+
Você deve gerar uma peça processual do tipo {doc_type} em português, formato jurídico brasileiro.
|
26 |
+
|
27 |
+
DADOS:
|
28 |
+
- Cliente: {context.get('client_name')}
|
29 |
+
- Processo: {context.get('process_number')}
|
30 |
+
- Tribunal: {context.get('court')}
|
31 |
+
- Comarca: {context.get('jurisdiction')}
|
32 |
+
|
33 |
+
FATOS:
|
34 |
+
{context.get('facts')}
|
35 |
+
|
36 |
+
FUNDAMENTOS JURÍDICOS:
|
37 |
+
{context.get('legal_basis')}
|
38 |
+
|
39 |
+
INSTRUÇÕES ESPECÍFICAS:
|
40 |
+
1. Use linguagem jurídica formal
|
41 |
+
2. Siga estritamente o formato de peças processuais brasileiras
|
42 |
+
3. Mantenha a estrutura com endereçamento, qualificação, fatos, direito e pedidos
|
43 |
+
4. Inclua local e data ao final
|
44 |
+
5. Use apenas os dados fornecidos
|
45 |
+
6. Evite repetições desnecessárias
|
46 |
+
7. Cite corretamente artigos e jurisprudência
|
47 |
+
8. Use formatação profissional
|
48 |
+
|
49 |
+
COMECE A GERAR O DOCUMENTO AGORA:"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
+
# Faz a chamada à API
|
52 |
+
inference = InferenceApi(repo_id=f"meta-llama/{self.model}", token=os.environ.get("HF_TOKEN"))
|
53 |
+
response = inference(
|
54 |
+
base_prompt,
|
55 |
+
max_length=4096,
|
56 |
+
temperature=0.3,
|
57 |
+
top_p=0.95,
|
58 |
+
repetition_penalty=1.15,
|
59 |
+
do_sample=True
|
|
|
60 |
)
|
61 |
|
62 |
+
return self._format_output(response[0]['generated_text'])
|
|
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
except Exception as e:
|
65 |
logger.error(f"Erro na geração: {str(e)}")
|
66 |
return f"Erro na geração do documento: {str(e)}"
|
|
|
69 |
"""Formata o texto gerado"""
|
70 |
if not text:
|
71 |
return "Erro: Nenhum texto gerado"
|
72 |
+
|
73 |
+
# Remove o prompt da resposta
|
74 |
+
text = text.split("COMECE A GERAR O DOCUMENTO AGORA:")[-1].strip()
|
75 |
|
76 |
+
# Ajusta formatação
|
77 |
lines = [line.strip() for line in text.split('\n') if line.strip()]
|
78 |
formatted_text = '\n\n'.join(lines)
|
79 |
|
80 |
+
# Adiciona data se não existir
|
81 |
+
if "[DATA]" in formatted_text:
|
82 |
+
current_date = datetime.now().strftime('%d de %B de %Y')
|
83 |
+
formatted_text = formatted_text.replace("[DATA]", current_date)
|
84 |
+
|
85 |
+
return formatted_text
|
86 |
|
87 |
class WebInterface:
|
88 |
"""Interface Gradio para o gerador de documentos"""
|
|
|
102 |
|
103 |
with gr.Row():
|
104 |
with gr.Column():
|
|
|
105 |
doc_type = gr.Dropdown(
|
106 |
choices=[
|
107 |
"Habeas Corpus",
|
|
|
115 |
value="Habeas Corpus"
|
116 |
)
|
117 |
|
|
|
118 |
with gr.Group():
|
119 |
gr.Markdown("### Informações do Processo")
|
120 |
client_name = gr.Textbox(
|
121 |
label="Nome do Cliente",
|
122 |
+
placeholder="Nome completo"
|
123 |
)
|
124 |
process_number = gr.Textbox(
|
125 |
label="Número do Processo",
|
|
|
134 |
placeholder="Nome da comarca"
|
135 |
)
|
136 |
|
|
|
137 |
with gr.Group():
|
138 |
gr.Markdown("### Detalhes do Caso")
|
139 |
facts = gr.Textbox(
|
|
|
144 |
legal_basis = gr.Textbox(
|
145 |
label="Fundamentos Jurídicos",
|
146 |
lines=3,
|
147 |
+
placeholder="Fundamentos legais..."
|
148 |
)
|
149 |
|
150 |
+
generate_btn = gr.Button("📝 Gerar Documento", variant="primary")
|
|
|
|
|
151 |
|
152 |
with gr.Column():
|
153 |
output = gr.Textbox(
|
|
|
155 |
lines=30,
|
156 |
show_copy_button=True
|
157 |
)
|
|
|
|
|
158 |
|
159 |
+
# Exemplos
|
160 |
gr.Examples(
|
161 |
examples=[
|
162 |
[
|
|
|
167 |
"São Paulo",
|
168 |
"Paciente preso em flagrante no dia 25/12/2024 por suposto furto simples (art. 155, caput, CP). O paciente é primário, possui residência fixa no distrito da culpa e ocupação lícita comprovada. Não estão presentes os requisitos autorizadores da prisão preventiva.",
|
169 |
"Art. 5º, LXVIII, CF/88; Art. 647 do CPP; Ausência dos requisitos do Art. 312 do CPP. Súmula 308 STJ."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
]
|
171 |
],
|
172 |
inputs=[
|
|
|
182 |
doc_type, client_name, process_number,
|
183 |
court, jurisdiction, facts, legal_basis
|
184 |
],
|
185 |
+
outputs=output
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
)
|
187 |
|
188 |
def _generate_document(
|
|
|
190 |
process_number: str, court: str,
|
191 |
jurisdiction: str, facts: str,
|
192 |
legal_basis: str
|
193 |
+
) -> str:
|
194 |
"""Gera o documento com os parâmetros fornecidos"""
|
195 |
+
|
196 |
try:
|
|
|
197 |
if not all([client_name, process_number, facts, legal_basis]):
|
198 |
+
return "Erro: Todos os campos obrigatórios devem ser preenchidos"
|
199 |
|
200 |
context = {
|
201 |
"client_name": client_name,
|
|
|
206 |
"legal_basis": legal_basis
|
207 |
}
|
208 |
|
209 |
+
return self.generator.generate(doc_type, context)
|
|
|
|
|
|
|
210 |
|
211 |
except Exception as e:
|
212 |
logger.error(f"Erro: {str(e)}")
|
213 |
+
return f"Erro na geração: {str(e)}"
|
214 |
|
215 |
def launch(self):
|
216 |
"""Inicia a interface web"""
|
217 |
+
self.app.launch(share=True)
|
218 |
|
219 |
if __name__ == "__main__":
|
220 |
interface = WebInterface()
|