GabrielGD commited on
Commit
6be2aad
·
verified ·
1 Parent(s): a66420b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -153
app.py CHANGED
@@ -2,7 +2,6 @@ import gradio as gr
2
  import requests
3
  import os
4
  import json
5
- import tempfile
6
  import PyPDF2
7
  import docx
8
  import io
@@ -17,13 +16,12 @@ from datetime import datetime
17
  from ratelimiter import RateLimiter
18
  import difflib
19
  from html import escape
20
- from weasyprint import HTML # Para gerar PDF com cores
21
 
22
  load_dotenv()
23
 
24
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
25
  if not GEMINI_API_KEY:
26
- raise ValueError("❌ A chave GEMINI_API_KEY não foi encontrada. Configure-a como Secret no Hugging Face Spaces.")
27
 
28
  GEMINI_API_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={GEMINI_API_KEY}"
29
 
@@ -32,22 +30,22 @@ CONFIG = {
32
  "retry_delay": 5,
33
  "timeout": 60,
34
  "temperatura": 0.2,
35
- "max_tokens": 12882 # Mantido em 8000, mas dividido em duas chamadas
36
  }
37
 
38
  rate_limiter = RateLimiter(max_calls=60, period=60)
39
 
40
  DICAS_OAB_MELHORADO = {
41
  "Endereçamento": "Em relações de consumo, prefira o foro do domicílio do autor (Art. 101, I, CDC). Exemplo: 'Excelentíssimo Senhor Juiz de Direito da Vara Cível da Comarca de [Cidade do Autor]'.",
42
- "Qualificação": "Mencione nome, estado civil (se informado), endereço (use 'Rua XXX' se não fornecido). Dica: Sempre verifique se todos os dados das partes estão corretos e completos.",
43
- "Fatos": "Descreva os fatos cronologicamente, sem inventar informações. Exemplo: 'Em [data], o autor celebrou contrato com o réu para a prestação de serviços de [descrição]'.",
44
- "Pedidos": "Seja específico nos pedidos (ex.: 'condenação ao pagamento de R$ X'). Dica: Inclua pedidos de danos morais e materiais, se aplicável, com base em precedentes.",
45
- "Custas": "Inclua 'Requer a juntada da guia de custas devidamente recolhida'. Dica: Nunca se esqueça de mencionar o recolhimento das custas para evitar a extinção do processo.",
46
- "Fundamentação": "Baseie-se em artigos do CPC ou CDC e, se possível, em súmulas do STJ (ex.: Súmula 387 para danos morais). Exemplo: 'Conforme o artigo 186 do Código Civil, a responsabilidade civil pode ser caracterizada'.",
47
- "Fechamento": "Finalize com 'Nestes termos pede deferimento', sem vírgula. Dica: Evite erros de pontuação que podem comprometer a formalidade do documento.",
48
- "Estratégia Jurídica": "Utilize precedentes e súmulas para fortalecer sua argumentação. Exemplo: 'Conforme a Súmula 387 do STJ, os danos morais devem ser comprovados e quantificados'.",
49
- "Provas": "Especifique as provas que pretende produzir. Dica: Inclua testemunhas, documentos e perícias, se necessário, para comprovar os fatos alegados.",
50
- "Contra-argumentação": "Antecipe possíveis defesas da parte contrária e prepare respostas. Dica: Considere os argumentos que a outra parte pode usar e esteja preparado para refutá-los."
51
  }
52
 
53
  HISTORICO = []
@@ -172,9 +170,8 @@ def process_file(file_obj):
172
  return f"❌ Erro ao processar o arquivo: {str(e)}"
173
 
174
  def estruturar_prompt_analise(caso, peticao, modo_treinamento=False):
175
- """Estrutura o prompt apenas para a análise da petição."""
176
  base_prompt = f"""
177
- ## Correção Avançada de Petição Inicial Cível (Critérios Realistas da OAB com Análise Especializada)
178
  **Caso Fornecido:**
179
  {caso}
180
  **Petição do Aluno:**
@@ -184,126 +181,87 @@ def estruturar_prompt_analise(caso, peticao, modo_treinamento=False):
184
  1. Análise Geral (Visão geral sobre a petição - máximo 3 linhas, destacando adequação ao caso e consistência jurídica)
185
  2. Nota Final (0 a 10 com uma casa decimal, justificando brevemente a pontuação total)
186
  3. Pontos Positivos (Liste pelo menos 3 aspectos bem executados com justificativa legal detalhada, incluindo artigos, súmulas ou precedentes aplicáveis)
187
- 4. Pontos a Melhorar (Liste todos os problemas encontrados em ordem de gravidade, com explicação detalhada, base legal e impacto na nota; não omita erros menores)
188
  5. Análise Específica dos Requisitos:
189
- - Endereçamento e qualificação do juízo (Art. 319, I, CPC; Art. 101, I, CDC se aplicável): Verifique a competência territorial e material com precisão.
190
- - Qualificação das partes (Art. 319, II, CPC): Avalie nomes, estado civil, endereço e consistência com o caso.
191
- - Fatos e fundamentos jurídicos (Art. 319, III, CPC; Art. 186, CC): Compare os fatos narrados com o caso e analise a pertinência dos fundamentos legais.
192
- - Pedidos com especificações (Art. 319, IV, CPC): Examine clareza, especificidade e adequação dos pedidos ao caso.
193
- - Valor da causa (Art. 319, V, CPC): Confirme se o valor é realista e compatível com os danos alegados.
194
- - Provas com que o autor pretende demonstrar a verdade dos fatos (Art. 319, VI, CPC): Avalie a suficiência e relevância das provas indicadas.
195
- - Opção pela realização ou não de audiência de conciliação (Art. 319, VII, CPC): Verifique a menção explícita e sua coerência com o caso.
196
- - Pedido de citação do réu: Analise se está claro e conforme os meios legais (ex.: Art. 246, CPC).
197
- - Juntada da guia de custas: Confirme a presença literal do pedido e sua redação formal.
198
- - Fechamento formal da petição: Certifique-se da estrutura exata "Local e data.\nADVOGADO.\nOAB." sem variações ou identificação indevida.
199
 
200
  **Critérios Fundamentais:**
201
- 1. Identificação do candidato (nome, CPF, RG ou número real na seção final) resulta em nota máxima de 3,0; forneça exemplo do trecho problemático.
202
- 2. Invenção de fatos não constantes no caso resulta em penalização grave (-5,0 pontos); identifique cada fato inventado e compare com o caso.
203
- 3. Falta de pedido de juntada de custas resulta em perda de 1,0 ponto; verifique a ausência ou redação inadequada.
204
- 4. Use marcadores para dados não fornecidos (ex.: "Rua XXX", "CPF XXX"); penalize invenção de dados específicos (-0,5 por ocorrência).
205
- 5. Não penalize por informações ausentes no caso original, mas alerte se a omissão compromete a petição.
206
- 6. A frase "Nestes termos, pede deferimento" com vírgula é incorreta; corrija para "Nestes termos pede deferimento" e penalize com -0,2 ponto, destacando o erro formal.
207
- 7. A petição deve finalizar com "Local e data.\nADVOGADO.\nOAB." sem identificação do aluno (nome, número ou estado na OAB); se houver identificação específica (ex.: "OAB/SP" ou "12345"), zere a nota (0,0) e explique o motivo.
208
-
209
- **Instruções Especiais para Análise Avançada:**
210
- - **Competência**: Avalie o foro indicado com base no Art. 46 do CPC (domicílio do réu) ou Art. 101, I do CDC (domicílio do autor em relações de consumo); penalize erros com -0,10 ponto e justifique com jurisprudência (ex.: STJ, REsp 1.234.567).
211
- - **Consistência Fática**: Compare cada fato narrado na petição com o caso; destaque omissões ou distorções com base no Art. 319, III, CPC.
212
- - **Fundamentação Jurídica**: Exija citação de pelo menos um artigo específico (ex.: Art. 186, CC para responsabilidade civil) e avalie a pertinência; penalize generalidades com -0,15 ponto por item vago.
213
- - **Danos Morais e Materiais**: Se o caso sugerir danos, verifique se os pedidos estão quantificados e fundamentados (ex.: Súmula 387/STJ para danos morais); penalize omissões com -0,20 ponto.
214
- - **Linguagem Técnica**: Avalie a formalidade e precisão do vocabulário jurídico; penalize informalidades ou erros gramaticais (ex.: "vossa excelência" em minúsculas) com -0,05 ponto por ocorrência.
215
- - **Precedentes**: Inclua referências a súmulas ou decisões relevantes (ex.: Súmula 297/STJ para CDC) quando aplicável no caso.
216
-
217
- **Pontuação Detalhada:**
218
- Inclua uma tabela com:
219
- | ITEM | PONTUAÇÃO | JUSTIFICATIVA |
220
- |-------------------------------------------|-----------|---------------|
221
- **Endereçamento** | | |
222
- 1. Correto endereçamento ao juízo competente (0,10) | / 0,10 | [Explique erro ou acerto] |
223
- 2. Qualificação das partes conforme Art. 319, II, CPC (0,20) | / 0,20 | [Explique erro ou acerto] |
224
- **Fundamentos** | | |
225
- 3. Exposição clara dos fatos (0,20) | / 0,20 | [Explique erro ou acerto] |
226
- 4. Fundamentação jurídica adequada (0,25) | / 0,25 | [Explique erro ou acerto] |
227
- 5. Demonstração de ilícito e dano (0,25) | / 0,25 | [Explique erro ou acerto] |
228
- **Pedidos** | | |
229
- 6. Pedidos claros e específicos (0,30) | / 0,30 | [Explique erro ou acerto] |
230
- 7. Valor da causa indicado (0,10) | / 0,10 | [Explique erro ou acerto] |
231
- 8. Provas pretendidas especificadas (0,10)| / 0,10 | [Explique erro ou acerto] |
232
- 9. Opção sobre audiência de conciliação (0,10) | / 0,10 | [Explique erro ou acerto] |
233
- 10. Pedido de citação do réu (0,10) | / 0,10 | [Explique erro ou acerto] |
234
- 11. Juntada da guia de custas (0,10) | / 0,10 | [Explique erro ou acerto] |
235
- **Fechamento** | | |
236
- 12. Fechamento formal adequado (0,10) | / 0,10 | [Explique erro ou acerto] |
237
- **Nota Final:** Calcule a soma dos pontos, aplicando penalizações cumulativas conforme os critérios fundamentais; justifique qualquer desconto adicional.
238
  """
239
  if modo_treinamento:
240
  base_prompt += f"""
241
- **Modo de Treinamento Interativo Avançado:**
242
- - Para cada item com pontuação inferior ao máximo, forneça:
243
- a) Explicação detalhada (máximo 2 frases curtas) com base legal (ex.: Art. 319, CPC) e impacto processual.
244
- b) Sugestão de redação corrigida baseada no caso, com linguagem técnica.
245
- c) Exemplo prático em outro contexto (máximo 1 frase).
246
- d) Dica prática do banco ({json.dumps(DICAS_OAB_MELHORADO, ensure_ascii=False)}) ou personalizada, curta.
247
- e) Estratégia jurídica avançada (máximo 1 frase).
248
- - Verifique a coerência entre os fatos do caso e a petição, listando inconsistências com trechos específicos.
249
- - Sugira estratégias adicionais baseadas no caso (ex.: cumulação de pedidos, Art. 327, CPC).
250
  """
251
  return base_prompt
252
 
253
  def estruturar_prompt_peticao_corrigida(caso, peticao):
254
- """Estrutura o prompt para a petição corrigida com instruções mais enfáticas."""
255
  return f"""
256
  **Caso Fornecido:**
257
  {caso}
258
  **Petição do Aluno:**
259
  {peticao}
260
  ### Petição Corrigida
261
- Gere a petição corrigida abaixo desta seção, intitulada exatamente como '### Petição Corrigida'. Você DEVE seguir TODOS os critérios abaixo rigorosamente, sem exceção, aplicando cada correção necessária com base no caso e na petição do aluno. Não ignore nenhum item, pois todos são obrigatórios:
262
-
263
- 1. **Endereçamento correto**: Corrija o foro com base no Art. 46 do CPC (domicílio do réu) ou Art. 101, I do CDC (domicílio do autor em relações de consumo, se aplicável). Exemplo: "Excelentíssimo Senhor Juiz de Direito da Vara Cível da Comarca de [Cidade correta]".
264
- 2. **Qualificação completa**: Inclua nome, estado civil, endereço (use "XXX" para dados ausentes), conforme Art. 319, II, CPC. Não invente dados específicos.
265
- 3. **Fatos claros e fiéis ao caso**: Narre os fatos do caso em ordem cronológica, sem adicionar informações não fornecidas, conforme Art. 319, III, CPC.
266
- 4. **Fundamentação jurídica robusta**: Cite pelo menos um artigo específico do CPC, CDC ou CC (ex.: Art. 186, CC para responsabilidade civil) e, se aplicável, súmulas (ex.: Súmula 387/STJ para danos morais).
267
- 5. **Pedidos específicos e quantificados**: Detalhe todos os pedidos com clareza e valores exatos (ex.: "R$ 50.000,00 por danos morais"), conforme Art. 319, IV, CPC.
268
- 6. **Valor da causa realista**: Inclua o valor total do benefício econômico pretendido, conforme Art. 319, V, CPC (ex.: soma de danos + valor do contrato, se aplicável).
269
- 7. **Provas detalhadas**: Especifique provas como "prova documental e testemunhal", conforme Art. 319, VI, CPC.
270
- 8. **Opção por audiência explícita**: Inclua "Requer a designação de audiência de conciliação" ou "Dispensa a audiência de conciliação", conforme Art. 319, VII, CPC.
271
- 9. **Pedido de citação formal**: Use "via postal, nos termos do Art. 246, I, CPC" ou outro meio legal aplicável.
272
- 10. **Juntada da guia de custas**: Adicione "Requer a juntada da guia de custas devidamente recolhida" em todas as petições corrigidas, sem exceção.
273
- 11. **Fechamento formal**: Finalize EXATAMENTE com "Local e data.\nADVOGADO.\nOAB." sem identificação específica (ex.: "OAB/SP" ou "12345" resultam em nota zero). A frase "Nestes termos, pede deferimento" com vírgula DEVE SER corrigida para "Nestes termos pede deferimento" (sem vírgula), conforme exigência formal da OAB.
274
-
275
- **Instruções Obrigatórias**:
276
- - Não omita nenhum dos 11 itens acima. Cada um é essencial e deve ser verificado e corrigido se necessário.
277
- - Siga estritamente as regras formais da OAB, especialmente a correção da vírgula em "Nestes termos pede deferimento".
278
- - Baseie-se exclusivamente no caso fornecido e na petição do aluno, sem inventar fatos ou dados.
279
- - Gere a petição completa, incluindo todas as seções (endereçamento, qualificação, fatos, direito, pedidos, valor da causa, provas, fechamento).
280
  """
281
 
282
  def pos_corrigir_peticao(peticao_corrigida):
283
- """Pós-processamento para garantir que todas as regras sejam aplicadas."""
284
- # Garantir a correção da vírgula
285
  if "Nestes termos, pede deferimento" in peticao_corrigida:
286
  peticao_corrigida = peticao_corrigida.replace("Nestes termos, pede deferimento", "Nestes termos pede deferimento")
287
-
288
- # Garantir o pedido de juntada da guia de custas
289
  if "juntada da guia de custas" not in peticao_corrigida.lower():
290
  peticao_corrigida = peticao_corrigida.replace("Nestes termos pede deferimento", "Requer a juntada da guia de custas devidamente recolhida.\nNestes termos pede deferimento")
291
-
292
- # Garantir o fechamento formal correto
293
  if not peticao_corrigida.strip().endswith("Local e data.\nADVOGADO.\nOAB."):
294
  linhas = peticao_corrigida.split('\n')
295
- while linhas and not linhas[-1].strip(): # Remove linhas em branco no final
296
  linhas.pop()
297
  if len(linhas) >= 3:
298
  linhas[-3:] = ["Local e data.", "ADVOGADO.", "OAB."]
299
  else:
300
  linhas.extend(["Local e data.", "ADVOGADO.", "OAB."])
301
  peticao_corrigida = "\n".join(linhas)
302
-
303
- # Garantir opção por audiência explícita
304
  if "audiência de conciliação" not in peticao_corrigida.lower():
305
- peticao_corrigida = peticao_corrigida.replace("Nestes termos pede deferimento", "Requer a designação de audiência de conciliação, nos termos do Art. 319, VII, CPC.\nNestes termos pede deferimento")
306
-
307
  return peticao_corrigida
308
 
309
  def chamar_api(prompt):
@@ -317,29 +275,28 @@ def chamar_api(prompt):
317
  with rate_limiter:
318
  response = requests.post(GEMINI_API_URL, headers=headers, data=json.dumps(payload), timeout=CONFIG["timeout"])
319
  if response.status_code != 200:
320
- response_data = response.json()
321
- error_msg = response_data.get("error", {}).get("message", "Erro desconhecido")
322
  if tentativa < CONFIG["max_retry_attempts"] - 1:
323
  time.sleep(CONFIG["retry_delay"] * (tentativa + 1))
324
  continue
325
- return f"❌ Erro da API (Tentativa {tentativa+1}/{CONFIG['max_retry_attempts']}): {error_msg}"
326
  response_data = response.json()
327
  if "candidates" not in response_data or not response_data["candidates"]:
328
  if tentativa < CONFIG["max_retry_attempts"] - 1:
329
  time.sleep(CONFIG["retry_delay"] * (tentativa + 1))
330
  continue
331
- return "❌ A API retornou uma resposta vazia. Tente novamente."
332
  return response_data["candidates"][0]["content"]["parts"][0]["text"].strip()
333
  except requests.Timeout:
334
  if tentativa < CONFIG["max_retry_attempts"] - 1:
335
  time.sleep(CONFIG["retry_delay"] * (tentativa + 1))
336
  continue
337
- return "⏱️ A resposta demorou muito. Tente novamente mais tarde."
338
  except requests.RequestException as e:
339
  if tentativa < CONFIG["max_retry_attempts"] - 1:
340
  time.sleep(CONFIG["retry_delay"] * (tentativa + 1))
341
  continue
342
- return f"❌ Erro ao chamar a API: {e}"
343
  except Exception as e:
344
  return f"❌ Erro inesperado: {str(e)}"
345
 
@@ -362,22 +319,18 @@ def corrigir_peticao(caso, peticao_texto=None, peticao_arquivo=None, modo_treina
362
  if cache_key in CORRECAO_CACHE:
363
  return aviso_validacao + CORRECAO_CACHE[cache_key]
364
 
365
- # Primeira chamada: análise
366
  prompt_analise = estruturar_prompt_analise(caso, peticao_conteudo, modo_treinamento)
367
  analise = chamar_api(prompt_analise)
368
  if "❌" in analise or "⏱️" in analise:
369
  return aviso_validacao + analise
370
  analise_formatada = formatar_correcao(analise)
371
 
372
- # Segunda chamada: petição corrigida
373
  prompt_peticao = estruturar_prompt_peticao_corrigida(caso, peticao_conteudo)
374
  peticao_corrigida = chamar_api(prompt_peticao)
375
  if "❌" in peticao_corrigida or "⏱️" in peticao_corrigida:
376
  return aviso_validacao + analise_formatada + "\n\n" + peticao_corrigida
377
 
378
- # Pós-correção para garantir conformidade
379
  peticao_corrigida = pos_corrigir_peticao(peticao_corrigida)
380
- print("Debug: Petição corrigida após pós-processamento:\n", peticao_corrigida[:1000]) # Debug para verificar a saída
381
 
382
  correcao_completa = analise + "\n\n" + peticao_corrigida
383
  HISTORICO.append({
@@ -405,7 +358,7 @@ def formatar_correcao(texto):
405
  texto_formatado += f"### ⚠️ {linha.strip()}\n\n"
406
  elif "- Invenção de fatos" in linha:
407
  texto_formatado += f"**🔴 {linha.strip()} (-5,0 pontos)**\n"
408
- elif linha.strip().startswith('-') and len(linha) > 2 and any(termo in linha for termo in ["Endereçamento", "Qualificação", "Fatos", "Pedidos", "Valor", "Provas"]):
409
  texto_formatado += f"**{linha.strip()}**\n"
410
  elif "Explicação" in linha or "Sugestão" in linha or "Dica" in linha or "Exemplo" in linha:
411
  texto_formatado += f"*{linha.strip()}*\n"
@@ -426,21 +379,10 @@ def extrair_peticao_corrigida(correcao_completa):
426
  inicio = correcao_completa.index("### Petição Corrigida") + len("### Petição Corrigida")
427
  peticao_texto = correcao_completa[inicio:].strip()
428
  fim = peticao_texto.find("###") if "###" in peticao_texto else len(peticao_texto)
429
- peticao_texto = peticao_texto[:fim].strip()
430
- return peticao_texto
431
- else:
432
- linhas = correcao_completa.split('\n')
433
- inicio_peticao = -1
434
- for i, linha in enumerate(linhas):
435
- if "EXCELENTÍSSIMO" in linha.upper() and i > len(linhas) // 2:
436
- inicio_peticao = i
437
- break
438
- if inicio_peticao != -1:
439
- peticao_texto = "\n".join(linhas[inicio_peticao:]).strip()
440
- return peticao_texto
441
- return "⚠️ A seção '### Petição Corrigida' não foi encontrada na resposta da API. Verifique a resposta e tente novamente."
442
  except Exception as e:
443
- return f"❌ Erro ao extrair petição corrigida: {str(e)}"
444
 
445
  def fornecer_dica_contextual(texto):
446
  dicas = [f"💡 {chave}: {dica}" for chave, dica in DICAS_OAB_MELHORADO.items() if chave.lower() in texto.lower()]
@@ -530,6 +472,7 @@ Diferença Líquida: {total_adicionadas - total_removidas} linhas
530
 
531
  def exportar_diferencas_html(caso, peticao_texto, correcao):
532
  _, _, resumo_estatistico, criticas_texto, visualizacao_detalhada = comparar_peticao_melhorada(caso, peticao_texto, correcao)
 
533
  html_content = f"""
534
  <html>
535
  <head>
@@ -553,21 +496,16 @@ def exportar_diferencas_html(caso, peticao_texto, correcao):
553
  </body>
554
  </html>
555
  """
556
- try:
557
- with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
558
- temp_path = tmp.name
559
- HTML(string=html_content).write_pdf(temp_path)
560
- return temp_path
561
- except Exception as e:
562
- return f"❌ Erro ao gerar PDF: {str(e)}"
563
- finally:
564
- if 'temp_path' in locals() and os.path.exists(temp_path):
565
- os.unlink(temp_path)
566
 
567
  def interface_gradio():
568
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
569
  gr.Markdown("# 📝 Corretor Avançado de Petições Iniciais (Critérios OAB)")
570
- gr.Markdown("⚠️ Nota: Devido a limites de cota da API, pode haver atrasos ou erros se muitas requisições forem feitas rapidamente.")
571
  with gr.Row():
572
  with gr.Column(scale=1):
573
  gr.Markdown("""
@@ -640,7 +578,7 @@ def interface_gradio():
640
  visualizacao_detalhada_output = gr.HTML(label="📝 Alterações Detalhadas")
641
 
642
  with gr.Row():
643
- download_btn = gr.Button("📥 Baixar Diferenças em PDF", visible=False)
644
  download_file = gr.File(label="Download", visible=False)
645
 
646
  with gr.Accordion("📜 Histórico de Correções", open=False):
@@ -683,7 +621,7 @@ def interface_gradio():
683
  inputs=[caso_input, peticao_texto, resultado_output],
684
  outputs=[download_file]
685
  ).then(
686
- fn=lambda x: [gr.update(visible=True, value=x) if isinstance(x, str) and not x.startswith("❌") else gr.update(visible=True, value=None, label=f"Erro: {x}" if x else "Erro desconhecido"), gr.update(visible=True)],
687
  outputs=[download_file, download_btn]
688
  )
689
 
@@ -706,7 +644,7 @@ def interface_gradio():
706
  """)
707
  gr.Markdown("""
708
  ### ℹ️ Modo de Treinamento Interativo
709
- Ative para explicações detalhadas com exemplos práticos e sugestões.
710
  ### 📋 Como usar
711
  1. Gere ou cole o caso
712
  2. Insira a petição
@@ -728,19 +666,13 @@ def estruturar_prompt_geracao_caso():
728
  Crie um caso fictício detalhado para uma petição inicial cível, similar ao exemplo:
729
  "Ana, modelo profissional, residente em Manaus, viajou para São Paulo, para o casamento de sua filha. Para lavar, pintar seus cabelos e realizar um penteado para o casamento, Ana procurou os serviços de João Macedo, cabeleireiro e dono do salão de beleza 'Hair', sediado na cidade de São Paulo, que lhe cobrou R$500,00 (quinhentos reais) pela prestação do serviço. Após lavar os cabelos de Ana, João aplicou-lhe uma tintura da marca francesa ABC, importada pela empresa Brasil Connection Ltda, sediada na cidade de Curitiba (PR). Meia hora após a aplicação da tintura, Ana sofreu uma reação alérgica, que demandou atendimento médico-hospitalar, no valor de R$1.000,00 (um mil reais), bem como dois dias de absoluto repouso que impossibilitou sua presença no casamento de sua filha. Além disso, perdeu grande parte de seu cabelo, tendo permanecido com manchas em seu rosto por dois meses, perdendo um ensaio fotográfico, para o qual já havia sido contratada, pelo valor de R$50.000,00 (cinquenta mil reais). Posteriormente constatou-se que a tintura utilizada continha substâncias químicas extremamente perigosas à vida e à saúde das pessoas e a fabricante ABC já havia sido condenada pela justiça francesa a encerrar a fabricação e comercialização do produto. Indignada com os danos sofridos, Ana procura um advogado para pleitear o devido ressarcimento."
730
  O caso deve:
731
- 1. Conter uma situação clara de violação de direitos que justifique uma ação cível
732
  2. Incluir valores específicos de danos materiais e/ou morais
733
- 3. Mencionar nomes completos, cidades e informações suficientes para identificar as partes
734
- 4. Estabelecer relação entre as partes (contratual, extracontratual, consumo, etc.)
735
  5. Ter complexidade adequada para uma petição inicial de nível OAB
736
- 6. Ter entre 15-25 linhas de texto
737
- 7. Focar em um dos seguintes temas (escolha APENAS UM aleatoriamente):
738
- - Responsabilidade civil por acidente de consumo
739
- - Inadimplemento contratual com danos
740
- - Responsabilidade civil por dano ambiental
741
- - Violação de direitos da personalidade
742
- - Relação de consumo com vício de produto/serviço
743
- - Reparação por danos patrimoniais
744
  Termine com: "Situação problema: Como advogado(a) de [NOME DO CLIENTE], promova a demanda cabível."
745
  """
746
 
 
2
  import requests
3
  import os
4
  import json
 
5
  import PyPDF2
6
  import docx
7
  import io
 
16
  from ratelimiter import RateLimiter
17
  import difflib
18
  from html import escape
 
19
 
20
  load_dotenv()
21
 
22
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
23
  if not GEMINI_API_KEY:
24
+ raise ValueError("❌ A chave GEMINI_API_KEY não foi encontrada. Configure-a no arquivo .env ou como Secret.")
25
 
26
  GEMINI_API_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={GEMINI_API_KEY}"
27
 
 
30
  "retry_delay": 5,
31
  "timeout": 60,
32
  "temperatura": 0.2,
33
+ "max_tokens": 12882
34
  }
35
 
36
  rate_limiter = RateLimiter(max_calls=60, period=60)
37
 
38
  DICAS_OAB_MELHORADO = {
39
  "Endereçamento": "Em relações de consumo, prefira o foro do domicílio do autor (Art. 101, I, CDC). Exemplo: 'Excelentíssimo Senhor Juiz de Direito da Vara Cível da Comarca de [Cidade do Autor]'.",
40
+ "Qualificação": "Mencione nome, estado civil (se informado), endereço (use 'Rua XXX' se não fornecido). Dica: Verifique se todos os dados estão corretos.",
41
+ "Fatos": "Descreva os fatos cronologicamente, sem inventar informações. Exemplo: 'Em [data], o autor celebrou contrato com o réu para [descrição]'.",
42
+ "Pedidos": "Seja específico nos pedidos (ex.: 'condenação ao pagamento de R$ X'). Inclua danos morais e materiais, se aplicável.",
43
+ "Custas": "Inclua 'Requer a juntada da guia de custas devidamente recolhida'. Nunca omita para evitar extinção do processo.",
44
+ "Fundamentação": "Baseie-se em artigos do CPC ou CDC e súmulas do STJ (ex.: Súmula 387 para danos morais).",
45
+ "Fechamento": "Finalize com 'Nestes termos pede deferimento', sem vírgula. Evite erros de pontuação.",
46
+ "Estratégia Jurídica": "Utilize precedentes e súmulas para fortalecer a argumentação.",
47
+ "Provas": "Especifique as provas a produzir. Inclua testemunhas, documentos e perícias, se necessário.",
48
+ "Contra-argumentação": "Antecipe defesas da parte contrária e prepare respostas."
49
  }
50
 
51
  HISTORICO = []
 
170
  return f"❌ Erro ao processar o arquivo: {str(e)}"
171
 
172
  def estruturar_prompt_analise(caso, peticao, modo_treinamento=False):
 
173
  base_prompt = f"""
174
+ ## Correção Avançada de Petição Inicial Cível (Critérios Realistas da OAB)
175
  **Caso Fornecido:**
176
  {caso}
177
  **Petição do Aluno:**
 
181
  1. Análise Geral (Visão geral sobre a petição - máximo 3 linhas, destacando adequação ao caso e consistência jurídica)
182
  2. Nota Final (0 a 10 com uma casa decimal, justificando brevemente a pontuação total)
183
  3. Pontos Positivos (Liste pelo menos 3 aspectos bem executados com justificativa legal detalhada, incluindo artigos, súmulas ou precedentes aplicáveis)
184
+ 4. Pontos a Melhorar (Liste todos os problemas encontrados em ordem de gravidade, com explicação detalhada, base legal e impacto na nota)
185
  5. Análise Específica dos Requisitos:
186
+ - Endereçamento e qualificação do juízo (Art. 319, I, CPC; Art. 101, I, CDC se aplicável)
187
+ - Qualificação das partes (Art. 319, II, CPC)
188
+ - Fatos e fundamentos jurídicos (Art. 319, III, CPC; Art. 186, CC)
189
+ - Pedidos com especificações (Art. 319, IV, CPC)
190
+ - Valor da causa (Art. 319, V, CPC)
191
+ - Provas com que o autor pretende demonstrar os fatos (Art. 319, VI, CPC)
192
+ - Opção pela realização ou não de audiência de conciliação (Art. 319, VII, CPC)
193
+ - Pedido de citação do réu
194
+ - Juntada da guia de custas
195
+ - Fechamento formal da petição
196
 
197
  **Critérios Fundamentais:**
198
+ 1. Identificação do candidato (nome, CPF, RG ou número real na seção final): nota máxima 3,0
199
+ 2. Invenção de fatos não constantes no caso: -5,0 pontos
200
+ 3. Falta de pedido de juntada de custas: -1,0 ponto
201
+ 4. Use marcadores para dados não fornecidos (ex.: "Rua XXX"): penalize invenção de dados (-0,5 por ocorrência)
202
+ 5. Não penalize por informações ausentes no caso original, mas alerte se a omissão compromete a petição
203
+ 6. "Nestes termos, pede deferimento" com vírgula é incorreto: corrija e penalize com -0,2 ponto
204
+ 7. Fechamento deve ser "Local e data.\nADVOGADO.\nOAB." sem identificação específica (ex.: "OAB/SP" ou "12345"): zere a nota (0,0) se houver
205
+
206
+ **Instruções Especiais:**
207
+ - Avalie o foro com base no Art. 46 do CPC ou Art. 101, I do CDC
208
+ - Compare fatos narrados com o caso
209
+ - Exija citação de pelo menos um artigo específico
210
+ - Verifique pedidos quantificados e fundamentados para danos
211
+ - Avalie formalidade e precisão da linguagem
212
+ - Inclua precedentes quando aplicável
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  """
214
  if modo_treinamento:
215
  base_prompt += f"""
216
+ **Modo de Treinamento:**
217
+ - Para cada item com problemas, forneça:
218
+ a) Explicação detalhada com base legal
219
+ b) Sugestão de redação corrigida
220
+ c) Exemplo prático
221
+ d) Dica prática do banco ({json.dumps(DICAS_OAB_MELHORADO, ensure_ascii=False)})
222
+ e) Estratégia jurídica avançada
223
+ - Liste inconsistências com trechos específicos
224
+ - Sugira estratégias adicionais (ex.: cumulação de pedidos, Art. 327, CPC)
225
  """
226
  return base_prompt
227
 
228
  def estruturar_prompt_peticao_corrigida(caso, peticao):
 
229
  return f"""
230
  **Caso Fornecido:**
231
  {caso}
232
  **Petição do Aluno:**
233
  {peticao}
234
  ### Petição Corrigida
235
+ Gere a petição corrigida abaixo desta seção, intitulada '### Petição Corrigida'. Siga TODOS os critérios abaixo:
236
+ 1. Endereçamento correto: Art. 46 do CPC ou Art. 101, I do CDC
237
+ 2. Qualificação completa: Nome, estado civil, endereço (use "XXX" para dados ausentes), Art. 319, II, CPC
238
+ 3. Fatos fiéis ao caso: Ordem cronológica, sem invenção, Art. 319, III, CPC
239
+ 4. Fundamentação jurídica: Cite pelo menos um artigo (ex.: Art. 186, CC) e súmulas, se aplicável
240
+ 5. Pedidos específicos: Detalhe valores (ex.: "R$ 50.000,00 por danos morais"), Art. 319, IV, CPC
241
+ 6. Valor da causa realista: Soma do benefício econômico, Art. 319, V, CPC
242
+ 7. Provas detalhadas: "Prova documental e testemunhal", Art. 319, VI, CPC
243
+ 8. Opção por audiência: "Requer a designação" ou "Dispensa", Art. 319, VII, CPC
244
+ 9. Pedido de citação: "Via postal, Art. 246, I, CPC"
245
+ 10. Juntada da guia: "Requer a juntada da guia de custas devidamente recolhida"
246
+ 11. Fechamento: "Local e data.\nADVOGADO.\nOAB." sem identificação específica; corrija "Nestes termos, pede deferimento" para "Nestes termos pede deferimento"
 
 
 
 
 
 
 
247
  """
248
 
249
  def pos_corrigir_peticao(peticao_corrigida):
 
 
250
  if "Nestes termos, pede deferimento" in peticao_corrigida:
251
  peticao_corrigida = peticao_corrigida.replace("Nestes termos, pede deferimento", "Nestes termos pede deferimento")
 
 
252
  if "juntada da guia de custas" not in peticao_corrigida.lower():
253
  peticao_corrigida = peticao_corrigida.replace("Nestes termos pede deferimento", "Requer a juntada da guia de custas devidamente recolhida.\nNestes termos pede deferimento")
 
 
254
  if not peticao_corrigida.strip().endswith("Local e data.\nADVOGADO.\nOAB."):
255
  linhas = peticao_corrigida.split('\n')
256
+ while linhas and not linhas[-1].strip():
257
  linhas.pop()
258
  if len(linhas) >= 3:
259
  linhas[-3:] = ["Local e data.", "ADVOGADO.", "OAB."]
260
  else:
261
  linhas.extend(["Local e data.", "ADVOGADO.", "OAB."])
262
  peticao_corrigida = "\n".join(linhas)
 
 
263
  if "audiência de conciliação" not in peticao_corrigida.lower():
264
+ peticao_corrigida = peticao_corrigida.replace("Nestes termos pede deferimento", "Requer a designação de audiência de conciliação, Art. 319, VII, CPC.\nNestes termos pede deferimento")
 
265
  return peticao_corrigida
266
 
267
  def chamar_api(prompt):
 
275
  with rate_limiter:
276
  response = requests.post(GEMINI_API_URL, headers=headers, data=json.dumps(payload), timeout=CONFIG["timeout"])
277
  if response.status_code != 200:
278
+ error_msg = response.json().get("error", {}).get("message", "Erro desconhecido")
 
279
  if tentativa < CONFIG["max_retry_attempts"] - 1:
280
  time.sleep(CONFIG["retry_delay"] * (tentativa + 1))
281
  continue
282
+ return f"❌ Erro da API: {error_msg}"
283
  response_data = response.json()
284
  if "candidates" not in response_data or not response_data["candidates"]:
285
  if tentativa < CONFIG["max_retry_attempts"] - 1:
286
  time.sleep(CONFIG["retry_delay"] * (tentativa + 1))
287
  continue
288
+ return "❌ Resposta vazia da API."
289
  return response_data["candidates"][0]["content"]["parts"][0]["text"].strip()
290
  except requests.Timeout:
291
  if tentativa < CONFIG["max_retry_attempts"] - 1:
292
  time.sleep(CONFIG["retry_delay"] * (tentativa + 1))
293
  continue
294
+ return "⏱️ Tempo esgotado."
295
  except requests.RequestException as e:
296
  if tentativa < CONFIG["max_retry_attempts"] - 1:
297
  time.sleep(CONFIG["retry_delay"] * (tentativa + 1))
298
  continue
299
+ return f"❌ Erro na requisição: {e}"
300
  except Exception as e:
301
  return f"❌ Erro inesperado: {str(e)}"
302
 
 
319
  if cache_key in CORRECAO_CACHE:
320
  return aviso_validacao + CORRECAO_CACHE[cache_key]
321
 
 
322
  prompt_analise = estruturar_prompt_analise(caso, peticao_conteudo, modo_treinamento)
323
  analise = chamar_api(prompt_analise)
324
  if "❌" in analise or "⏱️" in analise:
325
  return aviso_validacao + analise
326
  analise_formatada = formatar_correcao(analise)
327
 
 
328
  prompt_peticao = estruturar_prompt_peticao_corrigida(caso, peticao_conteudo)
329
  peticao_corrigida = chamar_api(prompt_peticao)
330
  if "❌" in peticao_corrigida or "⏱️" in peticao_corrigida:
331
  return aviso_validacao + analise_formatada + "\n\n" + peticao_corrigida
332
 
 
333
  peticao_corrigida = pos_corrigir_peticao(peticao_corrigida)
 
334
 
335
  correcao_completa = analise + "\n\n" + peticao_corrigida
336
  HISTORICO.append({
 
358
  texto_formatado += f"### ⚠️ {linha.strip()}\n\n"
359
  elif "- Invenção de fatos" in linha:
360
  texto_formatado += f"**🔴 {linha.strip()} (-5,0 pontos)**\n"
361
+ elif linha.strip().startswith('-') and any(termo in linha for termo in ["Endereçamento", "Qualificação", "Fatos", "Pedidos", "Valor", "Provas"]):
362
  texto_formatado += f"**{linha.strip()}**\n"
363
  elif "Explicação" in linha or "Sugestão" in linha or "Dica" in linha or "Exemplo" in linha:
364
  texto_formatado += f"*{linha.strip()}*\n"
 
379
  inicio = correcao_completa.index("### Petição Corrigida") + len("### Petição Corrigida")
380
  peticao_texto = correcao_completa[inicio:].strip()
381
  fim = peticao_texto.find("###") if "###" in peticao_texto else len(peticao_texto)
382
+ return peticao_texto[:fim].strip()
383
+ return "⚠️ Seção '### Petição Corrigida' não encontrada."
 
 
 
 
 
 
 
 
 
 
 
384
  except Exception as e:
385
+ return f"❌ Erro ao extrair petição: {str(e)}"
386
 
387
  def fornecer_dica_contextual(texto):
388
  dicas = [f"💡 {chave}: {dica}" for chave, dica in DICAS_OAB_MELHORADO.items() if chave.lower() in texto.lower()]
 
472
 
473
  def exportar_diferencas_html(caso, peticao_texto, correcao):
474
  _, _, resumo_estatistico, criticas_texto, visualizacao_detalhada = comparar_peticao_melhorada(caso, peticao_texto, correcao)
475
+
476
  html_content = f"""
477
  <html>
478
  <head>
 
496
  </body>
497
  </html>
498
  """
499
+
500
+ nome_arquivo = f"diferencas_peticao_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html"
501
+ with open(nome_arquivo, 'w', encoding='utf-8') as f:
502
+ f.write(html_content)
503
+ return nome_arquivo
 
 
 
 
 
504
 
505
  def interface_gradio():
506
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
507
  gr.Markdown("# 📝 Corretor Avançado de Petições Iniciais (Critérios OAB)")
508
+ gr.Markdown("⚠️ Nota: Devido a limites da API, pode haver atrasos ou erros em muitas requisições rápidas.")
509
  with gr.Row():
510
  with gr.Column(scale=1):
511
  gr.Markdown("""
 
578
  visualizacao_detalhada_output = gr.HTML(label="📝 Alterações Detalhadas")
579
 
580
  with gr.Row():
581
+ download_btn = gr.Button("📥 Baixar Diferenças em HTML", visible=False)
582
  download_file = gr.File(label="Download", visible=False)
583
 
584
  with gr.Accordion("📜 Histórico de Correções", open=False):
 
621
  inputs=[caso_input, peticao_texto, resultado_output],
622
  outputs=[download_file]
623
  ).then(
624
+ fn=lambda x: [gr.update(visible=True, value=x), gr.update(visible=True)],
625
  outputs=[download_file, download_btn]
626
  )
627
 
 
644
  """)
645
  gr.Markdown("""
646
  ### ℹ️ Modo de Treinamento Interativo
647
+ Ative para explicações detalhadas com exemplos e sugestões.
648
  ### 📋 Como usar
649
  1. Gere ou cole o caso
650
  2. Insira a petição
 
666
  Crie um caso fictício detalhado para uma petição inicial cível, similar ao exemplo:
667
  "Ana, modelo profissional, residente em Manaus, viajou para São Paulo, para o casamento de sua filha. Para lavar, pintar seus cabelos e realizar um penteado para o casamento, Ana procurou os serviços de João Macedo, cabeleireiro e dono do salão de beleza 'Hair', sediado na cidade de São Paulo, que lhe cobrou R$500,00 (quinhentos reais) pela prestação do serviço. Após lavar os cabelos de Ana, João aplicou-lhe uma tintura da marca francesa ABC, importada pela empresa Brasil Connection Ltda, sediada na cidade de Curitiba (PR). Meia hora após a aplicação da tintura, Ana sofreu uma reação alérgica, que demandou atendimento médico-hospitalar, no valor de R$1.000,00 (um mil reais), bem como dois dias de absoluto repouso que impossibilitou sua presença no casamento de sua filha. Além disso, perdeu grande parte de seu cabelo, tendo permanecido com manchas em seu rosto por dois meses, perdendo um ensaio fotográfico, para o qual já havia sido contratada, pelo valor de R$50.000,00 (cinquenta mil reais). Posteriormente constatou-se que a tintura utilizada continha substâncias químicas extremamente perigosas à vida e à saúde das pessoas e a fabricante ABC já havia sido condenada pela justiça francesa a encerrar a fabricação e comercialização do produto. Indignada com os danos sofridos, Ana procura um advogado para pleitear o devido ressarcimento."
668
  O caso deve:
669
+ 1. Conter uma violação clara de direitos que justifique uma ação cível
670
  2. Incluir valores específicos de danos materiais e/ou morais
671
+ 3. Mencionar nomes completos, cidades e informações para identificar as partes
672
+ 4. Estabelecer relação entre as partes (contratual, consumo, etc.)
673
  5. Ter complexidade adequada para uma petição inicial de nível OAB
674
+ 6. Ter entre 15-25 linhas
675
+ 7. Focar em um tema aleatório: responsabilidade civil por acidente de consumo, inadimplemento contratual, dano ambiental, direitos da personalidade, vício de produto/serviço, ou danos patrimoniais
 
 
 
 
 
 
676
  Termine com: "Situação problema: Como advogado(a) de [NOME DO CLIENTE], promova a demanda cabível."
677
  """
678