GabrielGD commited on
Commit
bad0b7b
·
verified ·
1 Parent(s): 60c5c48

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +28 -35
app.py CHANGED
@@ -16,30 +16,24 @@ import numpy as np
16
  from datetime import datetime
17
  from ratelimiter import RateLimiter
18
 
19
- # Carrega variáveis de ambiente de um arquivo .env (opcional para dev local)
20
  load_dotenv()
21
 
22
- # Obtém a chave da API do ambiente (no Hugging Face, configure como Secret)
23
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
24
  if not GEMINI_API_KEY:
25
  raise ValueError("❌ A chave GEMINI_API_KEY não foi encontrada. Configure-a como Secret no Hugging Face Spaces.")
26
 
27
- # URL da API Gemini
28
  GEMINI_API_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={GEMINI_API_KEY}"
29
 
30
- # Configurações da aplicação
31
  CONFIG = {
32
  "max_retry_attempts": 3,
33
- "retry_delay": 10, # Aumentado para 10 segundos para respeitar limites
34
  "timeout": 60,
35
  "temperatura": 0.2,
36
  "max_tokens": 4096
37
  }
38
 
39
- # Limite de 60 requisições por minuto (ajuste conforme seu limite real)
40
  rate_limiter = RateLimiter(max_calls=60, period=60)
41
 
42
- # Banco de dicas contextuais
43
  DICAS_OAB = {
44
  "Endereçamento": "Em relações de consumo, prefira o foro do domicílio do autor (art. 101, I, CDC).",
45
  "Qualificação": "Mencione nome, estado civil (se informado), endereço (use 'Rua XXX' se não fornecido).",
@@ -48,7 +42,6 @@ DICAS_OAB = {
48
  "Custas": "Inclua 'Requer a juntada da guia de custas devidamente recolhida'."
49
  }
50
 
51
- # Histórico de correções e cache
52
  HISTORICO = []
53
  CORRECAO_CACHE = {}
54
 
@@ -223,6 +216,7 @@ def estruturar_prompt_correcao(caso, peticao, modo_treinamento=False):
223
  3. Falta de pedido de juntada de custas resulta em perda de 1,0 ponto
224
  4. Use marcadores para dados não fornecidos (ex: "Rua XXX", "CPF XXX")
225
  5. Não penalize por informações ausentes no caso original
 
226
  **Instruções Especiais para Endereçamento:**
227
  - CPC (art. 46): foro competente é o domicílio do réu; CDC (art. 101, I): em relação de consumo, foro do autor é correto.
228
  - Avalie o contexto: priorize o foro do autor em casos consumeristas.
@@ -267,17 +261,18 @@ def estruturar_prompt_correcao(caso, peticao, modo_treinamento=False):
267
  if modo_treinamento:
268
  base_prompt += f"""
269
  **Modo de Treinamento Interativo Ativado:**
270
- - Para cada item com pontuação abaixo do máximo, forneça:
271
- a) Uma explicação detalhada do erro.
272
- b) Uma sugestão de redação corrigida baseada no caso.
273
- c) Uma dica prática para evitar o erro no futuro (use este banco de dicas: {json.dumps(DICAS_OAB)}).
 
274
  """
275
  return base_prompt
276
 
277
  def estruturar_prompt_geracao_caso():
278
  return """
279
  Crie um caso fictício detalhado para uma petição inicial cível, similar ao exemplo:
280
- "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."
281
  O caso deve:
282
  1. Conter uma situação clara de violação de direitos que justifique uma ação cível
283
  2. Incluir valores específicos de danos materiais e/ou morais
@@ -346,7 +341,6 @@ def corrigir_peticao(caso, peticao_texto=None, peticao_arquivo=None, modo_treina
346
  if not peticao_conteudo.strip():
347
  return "⚠️ Forneça uma petição."
348
 
349
- # Chave única para o cache
350
  cache_key = f"{caso[:50]}|{peticao_conteudo[:50]}|{modo_treinamento}"
351
  if cache_key in CORRECAO_CACHE:
352
  return CORRECAO_CACHE[cache_key]
@@ -382,12 +376,12 @@ def corrigir_peticao(caso, peticao_texto=None, peticao_arquivo=None, modo_treina
382
  analise = correção_completa.strip()
383
  correção_formatada = formatar_correção(analise)
384
  HISTORICO.append({
385
- "data": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
386
  "caso": caso,
387
  "peticao": peticao_conteudo,
388
  "correcao_completa": correção_completa
389
  })
390
- CORRECAO_CACHE[cache_key] = correção_formatada # Armazena no cache
391
  return correção_formatada
392
  except requests.Timeout:
393
  if tentativa < CONFIG["max_retry_attempts"] - 1:
@@ -427,11 +421,10 @@ def extrair_peticao_corrigida(correcao_completa):
427
  try:
428
  if "### Petição Corrigida" in correcao_completa:
429
  inicio = correcao_completa.index("### Petição Corrigida") + len("### Petição Corrigida")
430
- peticao_texto = ""
431
- for line in correcao_completa[inicio:].split('\n'):
432
- if line.strip() and not line.strip().startswith('#') and not line.strip().startswith('*') and not any(prefix in line for prefix in ["Análise", "Nota Final", "Pontos Positivos", "Pontos a Melhorar"]):
433
- peticao_texto += line + '\n'
434
- return peticao_texto.strip()
435
  return "⚠️ Petição corrigida não encontrada na resposta da API."
436
  except Exception as e:
437
  return f"❌ Erro ao extrair petição corrigida: {str(e)}"
@@ -525,32 +518,32 @@ def comparar_peticao_melhorada(caso, peticao_texto, correcao):
525
  elif linha.startswith('? '):
526
  continue
527
 
 
 
 
528
  resumo_alteracoes = []
529
  for secao, alteracoes in secoes.items():
530
  if alteracoes:
531
- resumo_alteracoes.append(f"### {secao}:")
532
  for alt in alteracoes[:5]:
533
- resumo_alteracoes.append(f"- {alt}")
534
  if len(alteracoes) > 5:
535
- resumo_alteracoes.append(f"- ... e mais {len(alteracoes) - 5} alterações")
536
-
537
- total_removidas = len([linha for linha in resultado_diff if "linha-removida" in linha])
538
- total_adicionadas = len([linha for linha in resultado_diff if "linha-adicionada" in linha])
539
 
540
  resumo_estatistico = f"""
541
  ## 📊 Resumo das Alterações
542
- - Total de linhas removidas: {total_removidas}
543
- - Total de linhas adicionadas: {total_adicionadas}
544
- - Diferença líquida: {total_adicionadas - total_removidas} linhas
545
 
546
  ## 🔍 Alterações por Seção
547
- {chr(10).join(resumo_alteracoes)}
548
 
549
  ## 📝 Visualização Detalhada
550
  <style>
551
- .linha-igual {{ color: #000000; }}
552
- .linha-removida {{ color: #ffffff; background-color: #b30000; }}
553
- .linha-adicionada {{ color: #ffffff; background-color: #006600; }}
554
  </style>
555
  {"".join(resultado_diff)}
556
  """
@@ -599,7 +592,7 @@ def interface_gradio():
599
  with gr.Row():
600
  gr.Markdown("### 🧩 Gerar Caso Fictício")
601
  caso_btn = gr.Button("🔄 Gerar Novo Caso Fictício", variant="secondary")
602
- caso_input = gr.Textbox(label="📋 Caso Fornecido pela Banca", lines=8, placeholder="Insira o texto COMPLETO do caso...")
603
  with gr.Tabs():
604
  with gr.TabItem("✏️ Inserir Texto"):
605
  peticao_texto = gr.Textbox(label="Texto da Petição do Aluno", lines=15, placeholder="Insira a petição completa...")
 
16
  from datetime import datetime
17
  from ratelimiter import RateLimiter
18
 
 
19
  load_dotenv()
20
 
 
21
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
22
  if not GEMINI_API_KEY:
23
  raise ValueError("❌ A chave GEMINI_API_KEY não foi encontrada. Configure-a como Secret no Hugging Face Spaces.")
24
 
 
25
  GEMINI_API_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={GEMINI_API_KEY}"
26
 
 
27
  CONFIG = {
28
  "max_retry_attempts": 3,
29
+ "retry_delay": 10,
30
  "timeout": 60,
31
  "temperatura": 0.2,
32
  "max_tokens": 4096
33
  }
34
 
 
35
  rate_limiter = RateLimiter(max_calls=60, period=60)
36
 
 
37
  DICAS_OAB = {
38
  "Endereçamento": "Em relações de consumo, prefira o foro do domicílio do autor (art. 101, I, CDC).",
39
  "Qualificação": "Mencione nome, estado civil (se informado), endereço (use 'Rua XXX' se não fornecido).",
 
42
  "Custas": "Inclua 'Requer a juntada da guia de custas devidamente recolhida'."
43
  }
44
 
 
45
  HISTORICO = []
46
  CORRECAO_CACHE = {}
47
 
 
216
  3. Falta de pedido de juntada de custas resulta em perda de 1,0 ponto
217
  4. Use marcadores para dados não fornecidos (ex: "Rua XXX", "CPF XXX")
218
  5. Não penalize por informações ausentes no caso original
219
+ 6. A frase "Nestes termos, pede deferimento" com vírgula é incorreta; corrija para "Nestes termos pede deferimento" e destaque o erro na análise.
220
  **Instruções Especiais para Endereçamento:**
221
  - CPC (art. 46): foro competente é o domicílio do réu; CDC (art. 101, I): em relação de consumo, foro do autor é correto.
222
  - Avalie o contexto: priorize o foro do autor em casos consumeristas.
 
261
  if modo_treinamento:
262
  base_prompt += f"""
263
  **Modo de Treinamento Interativo Ativado:**
264
+ - Para cada item com pontuação inferior ao máximo, forneça:
265
+ a) Uma explicação detalhada (mínimo 2 frases) descrevendo o erro e por que ele está errado conforme o CPC ou CDC.
266
+ b) Uma sugestão de redação corrigida baseada exclusivamente no caso fornecido.
267
+ c) Uma dica prática extraída do banco de dicas ({json.dumps(DICAS_OAB)}) ou uma dica personalizada se o banco não se aplicar.
268
+ - Não resuma; detalhe cada erro de forma pedagógica e clara.
269
  """
270
  return base_prompt
271
 
272
  def estruturar_prompt_geracao_caso():
273
  return """
274
  Crie um caso fictício detalhado para uma petição inicial cível, similar ao exemplo:
275
+ "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."
276
  O caso deve:
277
  1. Conter uma situação clara de violação de direitos que justifique uma ação cível
278
  2. Incluir valores específicos de danos materiais e/ou morais
 
341
  if not peticao_conteudo.strip():
342
  return "⚠️ Forneça uma petição."
343
 
 
344
  cache_key = f"{caso[:50]}|{peticao_conteudo[:50]}|{modo_treinamento}"
345
  if cache_key in CORRECAO_CACHE:
346
  return CORRECAO_CACHE[cache_key]
 
376
  analise = correção_completa.strip()
377
  correção_formatada = formatar_correção(analise)
378
  HISTORICO.append({
379
+ "data": datetime.now().strftime("%Y-%-m-%d %H:%M:%S"),
380
  "caso": caso,
381
  "peticao": peticao_conteudo,
382
  "correcao_completa": correção_completa
383
  })
384
+ CORRECAO_CACHE[cache_key] = correção_formatada
385
  return correção_formatada
386
  except requests.Timeout:
387
  if tentativa < CONFIG["max_retry_attempts"] - 1:
 
421
  try:
422
  if "### Petição Corrigida" in correcao_completa:
423
  inicio = correcao_completa.index("### Petição Corrigida") + len("### Petição Corrigida")
424
+ peticao_texto = correcao_completa[inicio:].strip()
425
+ fim = peticao_texto.find("###") if "###" in peticao_texto else len(peticao_texto)
426
+ peticao_texto = peticao_texto[:fim].strip()
427
+ return peticao_texto
 
428
  return "⚠️ Petição corrigida não encontrada na resposta da API."
429
  except Exception as e:
430
  return f"❌ Erro ao extrair petição corrigida: {str(e)}"
 
518
  elif linha.startswith('? '):
519
  continue
520
 
521
+ total_removidas = len([linha for linha in resultado_diff if "linha-removida" in linha])
522
+ total_adicionadas = len([linha for linha in resultado_diff if "linha-adicionada" in linha])
523
+
524
  resumo_alteracoes = []
525
  for secao, alteracoes in secoes.items():
526
  if alteracoes:
527
+ resumo_alteracoes.append(f"### {secao}\n")
528
  for alt in alteracoes[:5]:
529
+ resumo_alteracoes.append(f" {alt}")
530
  if len(alteracoes) > 5:
531
+ resumo_alteracoes.append(f" - ... e mais {len(alteracoes) - 5} alterações\n")
 
 
 
532
 
533
  resumo_estatistico = f"""
534
  ## 📊 Resumo das Alterações
535
+ - **Linhas Removidas:** {total_removidas}
536
+ - **Linhas Adicionadas:** {total_adicionadas}
537
+ - **Diferença Líquida:** {total_adicionadas - total_removidas} linhas
538
 
539
  ## 🔍 Alterações por Seção
540
+ {''.join(resumo_alteracoes)}
541
 
542
  ## 📝 Visualização Detalhada
543
  <style>
544
+ .linha-igual {{ color: #000000; margin: 2px 0; }}
545
+ .linha-removida {{ color: #ffffff; background-color: #b30000; margin: 2px 0; padding: 2px; }}
546
+ .linha-adicionada {{ color: #ffffff; background-color: #006600; margin: 2px 0; padding: 2px; }}
547
  </style>
548
  {"".join(resultado_diff)}
549
  """
 
592
  with gr.Row():
593
  gr.Markdown("### 🧩 Gerar Caso Fictício")
594
  caso_btn = gr.Button("🔄 Gerar Novo Caso Fictício", variant="secondary")
595
+ caso_input = gr.Textbox(label="� - 📋 Caso Fornecido pela Banca", lines=8, placeholder="Insira o texto COMPLETO do caso...")
596
  with gr.Tabs():
597
  with gr.TabItem("✏️ Inserir Texto"):
598
  peticao_texto = gr.Textbox(label="Texto da Petição do Aluno", lines=15, placeholder="Insira a petição completa...")