DHEIVER commited on
Commit
bd07d48
·
verified ·
1 Parent(s): 1489a92

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +167 -32
app.py CHANGED
@@ -8,59 +8,60 @@ from pathlib import Path
8
  import json
9
  import dotenv
10
 
11
- # Carrega variáveis de ambiente do arquivo .env se existir
12
  dotenv.load_dotenv()
13
 
14
  # Configuração do logging
15
  logging.basicConfig(
16
  level=logging.INFO,
17
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
 
 
 
 
18
  )
19
  logger = logging.getLogger(__name__)
20
 
21
  def load_token() -> str:
22
  """Carrega o token HF de várias fontes possíveis"""
23
- # Prioridade: 1. Variável de ambiente, 2. Arquivo .env, 3. arquivo config.json
24
-
25
- # Verifica variável de ambiente
26
  token = os.getenv('HF_TOKEN')
27
  if token:
28
  return token
29
 
30
- # Verifica arquivo config.json
31
  config_file = Path('config.json')
32
  if config_file.exists():
33
  try:
34
  with open(config_file, 'r') as f:
35
  config = json.load(f)
36
- return config.get('hf_token', '')
 
37
  except Exception as e:
38
  logger.error(f"Erro ao ler config.json: {e}")
39
 
40
  return ''
41
 
42
- # Carrega o token
43
- HF_API_TOKEN = load_token()
44
-
45
  class DocumentGenerator:
46
  """Gerencia a geração de documentos usando HF Inference API"""
47
 
48
  def __init__(self, api_key: str):
49
  if not api_key:
50
- raise ValueError("API Key não encontrada. Configure HF_TOKEN nas variáveis de ambiente ou no arquivo config.json")
51
-
52
  self.client = InferenceClient(api_key=api_key)
53
  self.model = "mistralai/Mistral-7B-Instruct-v0.2"
54
 
55
  def generate(self, doc_type: str, context: Dict[str, str]) -> str:
56
  """Gera o documento usando o modelo"""
57
  try:
58
- # Prepara as mensagens para o chat
59
  messages = [
60
  {
61
  "role": "system",
62
- "content": """Você é um advogado criminalista brasileiro experiente.
63
- Gere documentos jurídicos formais no formato do direito brasileiro."""
 
64
  },
65
  {
66
  "role": "user",
@@ -78,11 +79,17 @@ class DocumentGenerator:
78
  FUNDAMENTOS JURÍDICOS:
79
  {context.get('legal_basis')}
80
 
81
- Use formato jurídico adequado, com todas as partes necessárias."""
 
 
 
 
 
 
82
  }
83
  ]
84
 
85
- # Faz a chamada à API
86
  completion = self.client.chat.completions.create(
87
  model=self.model,
88
  messages=messages,
@@ -101,13 +108,23 @@ class DocumentGenerator:
101
  """Formata o texto gerado"""
102
  if not text:
103
  return "Erro: Nenhum texto gerado"
104
- return text.strip()
 
 
 
 
 
105
 
106
  class WebInterface:
107
  """Interface Gradio para o gerador de documentos"""
108
 
109
  def __init__(self):
110
- self.generator = DocumentGenerator(api_key=HF_API_TOKEN)
 
 
 
 
 
111
  self.create_interface()
112
 
113
  def create_interface(self):
@@ -115,12 +132,13 @@ class WebInterface:
115
 
116
  with gr.Blocks(theme=gr.themes.Soft()) as self.app:
117
  gr.Markdown("""
118
- # Criminal.ai - Gerador de Documentos Jurídicos
119
- Sistema de geração de peças processuais criminais
120
  """)
121
 
122
  with gr.Row():
123
  with gr.Column():
 
124
  doc_type = gr.Dropdown(
125
  choices=[
126
  "Habeas Corpus",
@@ -131,48 +149,123 @@ class WebInterface:
131
  "Apelação Criminal"
132
  ],
133
  label="Tipo de Documento",
134
- value="Habeas Corpus"
 
135
  )
136
 
 
137
  with gr.Group():
138
  gr.Markdown("### Informações do Processo")
 
139
  client_name = gr.Textbox(
140
  label="Nome do Cliente",
141
- placeholder="Nome completo"
 
142
  )
 
143
  process_number = gr.Textbox(
144
  label="Número do Processo",
145
- placeholder="NNNNNNN-NN.NNNN.N.NN.NNNN"
 
146
  )
 
147
  court = gr.Textbox(
148
  label="Tribunal",
149
- value="TRIBUNAL DE JUSTIÇA DO ESTADO"
 
150
  )
 
151
  jurisdiction = gr.Textbox(
152
- label="Comarca"
 
 
153
  )
154
 
 
155
  with gr.Group():
156
  gr.Markdown("### Detalhes do Caso")
 
157
  facts = gr.Textbox(
158
  label="Fatos",
159
  lines=5,
160
- placeholder="Descreva os fatos..."
 
161
  )
 
162
  legal_basis = gr.Textbox(
163
  label="Fundamentos Jurídicos",
164
- lines=3
 
 
165
  )
166
 
167
- generate_btn = gr.Button("Gerar Documento", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
 
169
  with gr.Column():
170
  output = gr.Textbox(
171
  label="Documento Gerado",
172
  lines=30,
173
  show_copy_button=True
174
  )
175
- status = gr.Textbox(label="Status")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
  # Eventos
178
  generate_btn.click(
@@ -183,6 +276,41 @@ class WebInterface:
183
  ],
184
  outputs=[output, status]
185
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
 
187
  def _generate_document(
188
  self, doc_type: str, client_name: str,
@@ -191,9 +319,11 @@ class WebInterface:
191
  legal_basis: str
192
  ) -> tuple:
193
  """Gera o documento com os parâmetros fornecidos"""
 
194
  try:
 
195
  if not all([client_name, process_number, facts, legal_basis]):
196
- return "Erro: Preencha todos os campos obrigatórios", "⚠️ Campos incompletos"
197
 
198
  context = {
199
  "client_name": client_name,
@@ -204,8 +334,13 @@ class WebInterface:
204
  "legal_basis": legal_basis
205
  }
206
 
 
 
 
 
207
  result = self.generator.generate(doc_type, context)
208
- return result, "✅ Documento gerado com sucesso"
 
209
 
210
  except Exception as e:
211
  logger.error(f"Erro: {str(e)}")
 
8
  import json
9
  import dotenv
10
 
11
+ # Carrega variáveis de ambiente
12
  dotenv.load_dotenv()
13
 
14
  # Configuração do logging
15
  logging.basicConfig(
16
  level=logging.INFO,
17
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
18
+ handlers=[
19
+ logging.FileHandler("app.log"),
20
+ logging.StreamHandler()
21
+ ]
22
  )
23
  logger = logging.getLogger(__name__)
24
 
25
  def load_token() -> str:
26
  """Carrega o token HF de várias fontes possíveis"""
27
+ # Tenta carregar do ambiente
 
 
28
  token = os.getenv('HF_TOKEN')
29
  if token:
30
  return token
31
 
32
+ # Tenta carregar do arquivo de configuração
33
  config_file = Path('config.json')
34
  if config_file.exists():
35
  try:
36
  with open(config_file, 'r') as f:
37
  config = json.load(f)
38
+ if token := config.get('hf_token'):
39
+ return token
40
  except Exception as e:
41
  logger.error(f"Erro ao ler config.json: {e}")
42
 
43
  return ''
44
 
 
 
 
45
  class DocumentGenerator:
46
  """Gerencia a geração de documentos usando HF Inference API"""
47
 
48
  def __init__(self, api_key: str):
49
  if not api_key:
50
+ raise ValueError("Token HF não configurado!")
51
+
52
  self.client = InferenceClient(api_key=api_key)
53
  self.model = "mistralai/Mistral-7B-Instruct-v0.2"
54
 
55
  def generate(self, doc_type: str, context: Dict[str, str]) -> str:
56
  """Gera o documento usando o modelo"""
57
  try:
58
+ # Prepara as mensagens
59
  messages = [
60
  {
61
  "role": "system",
62
+ "content": """Você é um advogado criminalista brasileiro altamente experiente,
63
+ especializado em redigir peças processuais. Gere documentos jurídicos formais,
64
+ tecnicamente precisos e no formato do direito brasileiro."""
65
  },
66
  {
67
  "role": "user",
 
79
  FUNDAMENTOS JURÍDICOS:
80
  {context.get('legal_basis')}
81
 
82
+ O documento deve seguir a formatação jurídica padrão brasileira, incluindo:
83
+ 1. Cabeçalho com endereçamento correto
84
+ 2. Qualificação completa das partes
85
+ 3. Exposição clara dos fatos
86
+ 4. Fundamentação jurídica sólida
87
+ 5. Pedidos específicos
88
+ 6. Fechamento formal com local, data e espaço para assinatura"""
89
  }
90
  ]
91
 
92
+ # Gera o documento
93
  completion = self.client.chat.completions.create(
94
  model=self.model,
95
  messages=messages,
 
108
  """Formata o texto gerado"""
109
  if not text:
110
  return "Erro: Nenhum texto gerado"
111
+
112
+ # Remove linhas vazias extras
113
+ lines = [line.strip() for line in text.split('\n') if line.strip()]
114
+ formatted_text = '\n\n'.join(lines)
115
+
116
+ return formatted_text.strip()
117
 
118
  class WebInterface:
119
  """Interface Gradio para o gerador de documentos"""
120
 
121
  def __init__(self):
122
+ # Carrega o token
123
+ token = load_token()
124
+ if not token:
125
+ raise ValueError("Token HF não encontrado!")
126
+
127
+ self.generator = DocumentGenerator(api_key=token)
128
  self.create_interface()
129
 
130
  def create_interface(self):
 
132
 
133
  with gr.Blocks(theme=gr.themes.Soft()) as self.app:
134
  gr.Markdown("""
135
+ # Criminal.ai - Gerador de Peças Processuais
136
+ ### Sistema Inteligente para Geração de Documentos Jurídicos
137
  """)
138
 
139
  with gr.Row():
140
  with gr.Column():
141
+ # Tipo de documento
142
  doc_type = gr.Dropdown(
143
  choices=[
144
  "Habeas Corpus",
 
149
  "Apelação Criminal"
150
  ],
151
  label="Tipo de Documento",
152
+ value="Habeas Corpus",
153
+ info="Selecione o tipo de peça processual"
154
  )
155
 
156
+ # Informações do processo
157
  with gr.Group():
158
  gr.Markdown("### Informações do Processo")
159
+
160
  client_name = gr.Textbox(
161
  label="Nome do Cliente",
162
+ placeholder="Nome completo do cliente/paciente",
163
+ info="Digite o nome completo"
164
  )
165
+
166
  process_number = gr.Textbox(
167
  label="Número do Processo",
168
+ placeholder="NNNNNNN-NN.NNNN.N.NN.NNNN",
169
+ info="Número CNJ do processo"
170
  )
171
+
172
  court = gr.Textbox(
173
  label="Tribunal",
174
+ value="TRIBUNAL DE JUSTIÇA DO ESTADO",
175
+ info="Nome completo do tribunal"
176
  )
177
+
178
  jurisdiction = gr.Textbox(
179
+ label="Comarca",
180
+ placeholder="Nome da comarca",
181
+ info="Comarca onde tramita o processo"
182
  )
183
 
184
+ # Detalhes do caso
185
  with gr.Group():
186
  gr.Markdown("### Detalhes do Caso")
187
+
188
  facts = gr.Textbox(
189
  label="Fatos",
190
  lines=5,
191
+ placeholder="Descreva os fatos relevantes do caso...",
192
+ info="Descreva os fatos de forma clara e objetiva"
193
  )
194
+
195
  legal_basis = gr.Textbox(
196
  label="Fundamentos Jurídicos",
197
+ lines=3,
198
+ placeholder="Fundamentos legais, jurisprudência...",
199
+ info="Artigos, jurisprudência e doutrina aplicáveis"
200
  )
201
 
202
+ # Botões
203
+ with gr.Row():
204
+ generate_btn = gr.Button(
205
+ "📝 Gerar Documento",
206
+ variant="primary",
207
+ scale=2
208
+ )
209
+
210
+ clear_btn = gr.Button(
211
+ "🗑️ Limpar Campos",
212
+ variant="secondary",
213
+ scale=1
214
+ )
215
+
216
+ status = gr.Textbox(
217
+ label="Status",
218
+ interactive=False
219
+ )
220
 
221
+ # Coluna do documento gerado
222
  with gr.Column():
223
  output = gr.Textbox(
224
  label="Documento Gerado",
225
  lines=30,
226
  show_copy_button=True
227
  )
228
+
229
+ with gr.Row():
230
+ save_btn = gr.Button("💾 Salvar como TXT")
231
+ copy_btn = gr.Button("📋 Copiar")
232
+
233
+ # Exemplos de uso
234
+ gr.Examples(
235
+ examples=[
236
+ [
237
+ "Habeas Corpus",
238
+ "João da Silva Santos",
239
+ "0000123-45.2024.8.26.0000",
240
+ "TRIBUNAL DE JUSTIÇA DO ESTADO DE SÃO PAULO",
241
+ "São Paulo",
242
+ "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.",
243
+ "Art. 5º, LXVIII, CF/88; Art. 647 do CPP; Ausência dos requisitos do Art. 312 do CPP. Súmula 308 STJ."
244
+ ],
245
+ [
246
+ "Denúncia Criminal",
247
+ "Pedro Oliveira Lima",
248
+ "0000456-78.2024.8.26.0000",
249
+ "TRIBUNAL DE JUSTIÇA DO ESTADO DE SÃO PAULO",
250
+ "São Paulo",
251
+ "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.",
252
+ "Art. 157, caput, do Código Penal. Circunstâncias do Art. 59 do CP desfavoráveis."
253
+ ],
254
+ [
255
+ "Alegações Finais",
256
+ "Maria Santos Costa",
257
+ "0000789-10.2024.8.26.0000",
258
+ "TRIBUNAL DE JUSTIÇA DO ESTADO DE SÃO PAULO",
259
+ "São Paulo",
260
+ "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.",
261
+ "Insuficiência probatória. Art. 386, VII do CPP. Princípio in dubio pro reo."
262
+ ]
263
+ ],
264
+ inputs=[
265
+ doc_type, client_name, process_number,
266
+ court, jurisdiction, facts, legal_basis
267
+ ]
268
+ )
269
 
270
  # Eventos
271
  generate_btn.click(
 
276
  ],
277
  outputs=[output, status]
278
  )
279
+
280
+ def clear_fields():
281
+ return [gr.update(value="") for _ in range(6)] + ["Campos limpos"]
282
+
283
+ clear_btn.click(
284
+ fn=clear_fields,
285
+ inputs=[],
286
+ outputs=[
287
+ client_name, process_number, court,
288
+ jurisdiction, facts, legal_basis, status
289
+ ]
290
+ )
291
+
292
+ def save_to_file(text):
293
+ if not text:
294
+ return "Nenhum documento para salvar"
295
+ filename = f"documento_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
296
+ try:
297
+ with open(filename, 'w', encoding='utf-8') as f:
298
+ f.write(text)
299
+ return f"✅ Documento salvo como {filename}"
300
+ except Exception as e:
301
+ return f"❌ Erro ao salvar: {str(e)}"
302
+
303
+ save_btn.click(
304
+ fn=save_to_file,
305
+ inputs=[output],
306
+ outputs=[status]
307
+ )
308
+
309
+ copy_btn.click(
310
+ fn=lambda x: x,
311
+ inputs=[output],
312
+ outputs=[output]
313
+ )
314
 
315
  def _generate_document(
316
  self, doc_type: str, client_name: str,
 
319
  legal_basis: str
320
  ) -> tuple:
321
  """Gera o documento com os parâmetros fornecidos"""
322
+
323
  try:
324
+ # Validação
325
  if not all([client_name, process_number, facts, legal_basis]):
326
+ return "Erro: Todos os campos obrigatórios devem ser preenchidos", "⚠️ Campos incompletos"
327
 
328
  context = {
329
  "client_name": client_name,
 
334
  "legal_basis": legal_basis
335
  }
336
 
337
+ # Atualiza status
338
+ yield "", "⏳ Gerando documento..."
339
+
340
+ # Gera documento
341
  result = self.generator.generate(doc_type, context)
342
+
343
+ return result, "✅ Documento gerado com sucesso!"
344
 
345
  except Exception as e:
346
  logger.error(f"Erro: {str(e)}")