GabrielGD commited on
Commit
709a4e8
·
verified ·
1 Parent(s): c61583f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +175 -268
app.py CHANGED
@@ -8,7 +8,7 @@ import copy
8
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
9
  if not GEMINI_API_KEY:
10
  print("ALERTA: GEMINI_API_KEY não encontrada como Secret no Hugging Face Space. O app não funcionará.")
11
- # GEMINI_API_KEY = "SUA_CHAVE_AQUI_PARA_TESTE_LOCAL_APENAS" # Descomente para teste local
12
 
13
  MODEL_NAME = "gemini-1.5-flash-latest"
14
  API_URL_BASE = f"https://generativelanguage.googleapis.com/v1beta/models/{MODEL_NAME}:generateContent"
@@ -17,7 +17,6 @@ API_URL_BASE = f"https://generativelanguage.googleapis.com/v1beta/models/{MODEL_
17
  FASE_INICIAL_CONFIG = "CONFIGURACAO"
18
  FASE_ABERTURA_CONCILIACAO = "ABERTURA_E_CONCILIACAO"
19
  FASE_TESTEMUNHAS_AUTOR_INICIO = "TESTEMUNHAS_AUTOR_INICIO"
20
- # FASE_TESTEMUNHAS_AUTOR_PERGUNTAS_AUTOR = "TESTEMUNHAS_AUTOR_PERGUNTAS_AUTOR" # Not explicitly used for distinct logic yet
21
  FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU = "TESTEMUNHAS_AUTOR_CONTRADITA_REU"
22
  FASE_TESTEMUNHAS_REU_INICIO = "TESTEMUNHAS_REU_INICIO"
23
  FASE_TESTEMUNHAS_REU_PERGUNTAS_REU = "TESTEMUNHAS_REU_PERGUNTAS_REU"
@@ -55,7 +54,7 @@ ARGUMENTOS_AUTOR_PREDEFINIDOS = [
55
  ]
56
  PROVAS_AUTOR_SUPPOSTAS_TEXTO_PREDEFINIDO = "\n".join(ARGUMENTOS_AUTOR_PREDEFINIDOS)
57
 
58
- CONTRA_ARGUMENTOS_REU_PREDEFINIDOS_LIST = [ # Renamed to avoid confusion
59
  "Argumento: A liberdade de imprensa é um direito fundamental e a matéria é de interesse público histórico. Prova: Art. 5º, IX e XIV da CF/88; Doutrina sobre liberdade de imprensa.",
60
  "Argumento: A matéria baseia-se inteiramente em informações verídicas e de acesso público (processo judicial). Prova: Cópia da matéria original e da recente, certidão do processo.",
61
  "Argumento: O STF (RE 1.010.606) não reconheceu o direito ao esquecimento de forma absoluta, ponderando-o com a liberdade de informação. Prova: Inteiro teor do acórdão do RE 1.010.606.",
@@ -96,7 +95,7 @@ def estado_inicial_simulacao():
96
  "provas_autor_supostas_texto": "", "testemunhas_reu_defs": [],
97
  "testemunhas_autor_supostas_defs": [], "testemunha_autor_atual_idx": -1,
98
  "testemunha_reu_atual_idx": -1, "testemunha_em_depoimento": None,
99
- "transcricao_chat": [], "transcricao_logica": [],
100
  "feedback_para_usuario": "Aguardando início da simulação.",
101
  "instrucao_para_usuario": "Configure os detalhes do caso na aba 'Configuração' ou carregue o caso padrão."
102
  }
@@ -142,38 +141,22 @@ def chamar_gemini_api(prompt_text, temperature=0.7, max_output_tokens=800):
142
  def formatar_historico_para_prompt(transcricao_logica, max_turns=15):
143
  historico_formatado = "\nContexto da Audiência (últimas interações):\n"
144
  for ator, fala in transcricao_logica[-max_turns:]:
145
- fala_escaped = fala.replace('"', '\"') # Escape quotes in history
146
  historico_formatado += f"- {ator}: {fala_escaped}\n"
147
  return historico_formatado
148
 
149
  def gerar_caso_ficticio_com_ia():
150
  prompt_geracao_caso = """
151
- **Instrução de Persona:** Você é um roteirista jurídico criativo e experiente, especializado em criar casos simulados realistas para treinamento de advogados.
152
- **Tarefa:** Crie um caso fictício detalhado para uma simulação de Audiência de Instrução e Julgamento (AIJ) sobre o tema "Direito ao Esquecimento vs. Liberdade de Imprensa".
153
- **Elementos Obrigatórios a Serem Gerados:**
154
- 1. **Título do Caso Fictício:** (Ex: "O Caso da Notícia Ressurgida")
155
- 2. **Partes:** (Autor: Nome; Réu: Nome do veículo)
156
- 3. **Resumo Detalhado dos Fatos (Mínimo 250 palavras):** (Detalhes da publicação, lapso temporal, motivos do autor)
157
- 4. **Argumentos e "Provas" Hipotéticas da Parte AUTORA (mínimo 3):** (Formato: `Argumento: [Descrição]. Prova: [Descrição].`)
158
- 5. **Argumentos e "Provas" Hipotéticas da Parte RÉ (Jornal - mínimo 3):** (Formato: `Argumento: [Descrição]. Prova: [Descrição].`)
159
- 6. **Testemunhas Hipotéticas da Parte AUTORA (Pelo menos 1, idealmente 2):** (Formato: `[Nome]: [Pontos Chave]`)
160
- 7. **Testemunhas Hipotéticas da Parte RÉ (Pelo menos 1, idealmente 2):** (Formato: `[Nome]: [Pontos Chave]`)
161
- **Formato da Saída:** Use os seguintes marcadores exatos para cada seção (iniciando em nova linha):
162
- `## Título do Caso Fictício`
163
- `## Partes`
164
- `## Resumo Detalhado dos Fatos`
165
- `## Argumentos e "Provas" Hipotéticas da Parte AUTORA`
166
- `## Argumentos e "Provas" Hipotéticas da Parte RÉ (Jornal)`
167
- `## Testemunhas Hipotéticas da Parte AUTORA`
168
- `## Testemunhas Hipotéticas da Parte RÉ`
169
- O conteúdo de cada seção deve vir após o marcador. Para Argumentos/Provas e Testemunhas, liste cada item em uma nova linha.
170
- """
171
  texto_caso_completo = chamar_gemini_api(prompt_geracao_caso, temperature=0.75, max_output_tokens=2500)
172
  if "ERRO_" in texto_caso_completo:
173
  return {"fatos": f"Falha ao gerar caso com IA: {texto_caso_completo}", "provas_autor": "", "provas_reu": "", "testemunhas_autor": "", "testemunhas_reu": ""}
174
  return parse_caso_gerado(texto_caso_completo)
175
 
176
- def parse_caso_gerado(texto_completo_caso):
177
  dados_caso = {"fatos": "Falha parsing: Fatos", "provas_autor": "Falha parsing: Provas Autor", "provas_reu": "Falha parsing: Provas Réu", "testemunhas_autor": "Falha parsing: Testemunhas Autor", "testemunhas_reu": "Falha parsing: Testemunhas Réu"}
178
  secoes = {"fatos": "## Resumo Detalhado dos Fatos", "provas_autor": "## Argumentos e \"Provas\" Hipotéticas da Parte AUTORA", "provas_reu": "## Argumentos e \"Provas\" Hipotéticas da Parte RÉ (Jornal)", "testemunhas_autor": "## Testemunhas Hipotéticas da Parte AUTORA", "testemunhas_reu": "## Testemunhas Hipotéticas da Parte RÉ"}
179
  fatos_prefix = ""
@@ -214,12 +197,12 @@ def parse_caso_gerado(texto_completo_caso):
214
  dados_caso[key_testemunha] = "\n".join(linhas_formatadas)
215
  return dados_caso
216
 
217
- def acao_gerar_caso_ficticio_ui():
218
  gr.Info("Gerando caso fictício com IA... Isso pode levar um momento.")
219
  dados_gerados = gerar_caso_ficticio_com_ia()
220
  return [dados_gerados["fatos"], dados_gerados["provas_reu"], dados_gerados["provas_autor"], dados_gerados["testemunhas_reu"], dados_gerados["testemunhas_autor"], "Caso fictício gerado. Revise e salve."]
221
 
222
- def acao_carregar_caso_padrao_ui():
223
  gr.Info("Carregando caso padrão...")
224
  return [
225
  CASO_FATOS_COMPLETO_PREDEFINIDO,
@@ -230,9 +213,11 @@ def acao_carregar_caso_padrao_ui():
230
  "Caso padrão carregado. Revise e salve."
231
  ]
232
 
 
233
  def gerar_resposta_juiz_ia(estado_simulacao, acao_especifica=""):
234
  fase = estado_simulacao["fase_aij"]
235
  historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
 
236
  prompt_base = f"**Persona:** Juiz(a) experiente em AIJ (Direito Esquecimento vs Liberdade Imprensa).\n**Fatos:** {estado_simulacao['caso_fatos'] or 'Não detalhado.'}\n{historico}**Fase Atual:** {fase}\n"
237
 
238
  tarefa_especifica_str = ""
@@ -257,11 +242,12 @@ def gerar_resposta_advogado_autor_ia(estado_simulacao, fala_adv_reu=""):
257
  prompt_base = f"**Persona:** Advogado(a) do AUTOR em AIJ (Direito Esquecimento vs Liberdade Imprensa). Cliente busca esquecimento/reparação.\n**Réu:** Jornal.\n**Fatos:** {estado_simulacao['caso_fatos'] or 'Não detalhado.'}\n**Provas/Argumentos Autor:** {estado_simulacao['provas_autor_supostas_texto'] or 'Passagem tempo, desinteresse público, dano vida privada.'}\n{historico}**Fase Atual:** {fase}\n"
258
 
259
  tarefa_especifica_str = ""
260
- fala_adv_reu_escaped = fala_adv_reu.replace('"', '\"') # Escape double quotes from user input
261
 
262
  if fase == FASE_ABERTURA_CONCILIACAO:
263
  tarefa_especifica_str = f"**Tarefa:** Juiz perguntou sobre conciliação. Apresente proposta ou declare desinteresse. Se Réu já falou (\"{fala_adv_reu_escaped}\"), responda."
264
  elif fase == FASE_TESTEMUNHAS_AUTOR_INICIO:
 
265
  if estado_simulacao["testemunhas_autor_supostas_defs"]:
266
  proxima_testemunha_idx = estado_simulacao["testemunha_autor_atual_idx"] + 1
267
  if proxima_testemunha_idx < len(estado_simulacao["testemunhas_autor_supostas_defs"]):
@@ -286,25 +272,23 @@ def gerar_resposta_testemunha_autor_ia(estado_simulacao, pergunta_feita):
286
  testemunha_obj = estado_simulacao.get("testemunha_em_depoimento")
287
  if not testemunha_obj or testemunha_obj["parte"] != "AUTOR": return "Testemunha do Autor (IA): (Erro interno - Nenhuma testemunha do autor em depoimento)"
288
  historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
289
- pergunta_feita_escaped = pergunta_feita.replace('"', '\"')
290
  prompt_completo = f"**Persona:** Testemunha {testemunha_obj['nome']} (AUTOR).\n**Caso:** Direito Esquecimento vs Liberdade Imprensa.\n**Fatos:** {estado_simulacao['caso_fatos'] or 'Não detalhado.'}\n**Seus Pontos Chave:** {testemunha_obj['pontos_chave'] or 'Conhecimento geral sobre autor e impactos.'}\n{historico}**Pergunta Feita:** \"{pergunta_feita_escaped}\"\n**Tarefa:** Responda claro, conciso, baseado nos seus pontos. Se Adv. Réu, seja cauteloso(a).\n**Sua Resposta (Testemunha {testemunha_obj['nome']}):**"
291
  return chamar_gemini_api(prompt_completo, temperature=0.6, max_output_tokens=250)
292
 
293
  def analisar_atuacao_defesa_ia(estado_simulacao, ultima_fala_reu=""):
294
  historico_completo_dialogo = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"], max_turns=len(estado_simulacao["transcricao_logica"]))
295
- ultima_fala_reu_escaped = ultima_fala_reu.replace('"', '\"')
296
  prompt_analise = f"**Persona:** Professor(a) de Prática Jurídica experiente.\n**Tarefa:** Feedback construtivo para aluno (Adv. RÉU - Jornal) em AIJ (Direito Esquecimento vs Liberdade Imprensa).\n**Fatos:** {estado_simulacao['caso_fatos'] or 'Não detalhado.'}\n**Provas/Argumentos Réu:** {estado_simulacao['provas_reu_texto'] or 'Não detalhado.'}\n**Transcrição AIJ:** {historico_completo_dialogo}\n**Última Intervenção Réu:** \"{ultima_fala_reu_escaped}\"\n**Feedback Detalhado (Pontos Fortes, Melhorias, Sugestões, Fundamentação, Estratégia):**"
297
  return chamar_gemini_api(prompt_analise, temperature=0.65, max_output_tokens=1200)
298
 
299
- def avaliar_argumentos_defesa_ia(fatos_caso, provas_reu_texto_arg, tipo_argumento, argumento_usuario): # Renamed provas_reu to avoid conflict
300
  if not argumento_usuario.strip():
301
  return "Por favor, insira seus argumentos para avaliação."
302
 
303
  fatos_formatado = fatos_caso if fatos_caso else CASO_DESCRICAO_PREDEFINIDO
304
  provas_reu_formatado = provas_reu_texto_arg if provas_reu_texto_arg else PROVAS_REU_TEXTO_PREDEFINIDO
305
 
306
- # Now, build contexto_caso without an f-string for the main structure,
307
- # only using f-strings for simple variable insertions if necessary, or direct concatenation.
308
  contexto_caso_parts = [
309
  "Você está avaliando argumentos no contexto de um caso jurídico no Brasil sobre direito ao esquecimento vs. liberdade de imprensa.\n",
310
  "O usuário representa a defesa (jornal).\n",
@@ -312,60 +296,44 @@ def avaliar_argumentos_defesa_ia(fatos_caso, provas_reu_texto_arg, tipo_argument
312
  f"**Principais Argumentos/Provas da Defesa (Jornal):** {provas_reu_formatado}\n"
313
  ]
314
  contexto_caso = "".join(contexto_caso_parts)
315
-
316
- argumento_usuario_escaped = argumento_usuario.replace('"', '\"')
317
 
318
  prompt_parts = [
319
  contexto_caso,
320
- "\n\n**Persona:** Você é um Juiz experiente em um tribunal brasileiro, com especialidade em casos de liberdade de imprensa e direitos da personalidade.\n",
321
- f"**Tarefa:** Avalie o seguinte argumento apresentado pelo advogado de defesa (jornal) para a peça/momento processual: \"{tipo_argumento}\".\n",
322
- "Forneça feedback detalhado e construtivo em português brasileiro, incluindo:\n",
323
- "1. **Pontos Fortes:** Destaque aspectos positivos (ex: fundamentação legal sólida, coerência lógica, clareza, persuasão, uso de fatos).\n",
324
- "2. **Pontos a Melhorar:** Identifique fraquezas (ex: falta de aprofundamento, generalizações, omissão de contrapontos importantes, linguagem inadequada, falta de nexo com os fatos/provas do réu).\n",
325
- "3. **Sugestões Específicas:** Ofereça conselhos práticos para aprimoramento (ex: citar precedentes específicos como o RE 1.010.606/STF, refutar explicitamente possíveis argumentos do autor, conectar melhor o argumento às provas do réu, sugerir redação alternativa).\n",
326
- "4. **Nota Geral (0 a 5):** Atribua uma nota considerando:\n",
327
- " * Fundamentação Legal/Jurisprudencial (Peso 3)\n",
328
- " * Coerência e Lógica (Peso 2)\n",
329
- " * Persuasão e Clareza (Peso 2)\n",
330
- " * Adequação ao tipo de peça/momento (Peso 1)\n",
331
- " * Conexão com os fatos/provas do caso (Peso 2)\n\n",
332
- "Formato da Resposta: Utilize linguagem formal e jurídica. Estruture a resposta rigorosamente com os títulos:\n",
333
- "`### Pontos Fortes`\n",
334
- "`### Pontos a Melhorar`\n",
335
- "`### Sugestões Específicas`\n",
336
- "`### Nota Geral`\n\n",
337
  f"**Argumento do Advogado de Defesa (Jornal):**\n\"{argumento_usuario_escaped}\"\n\n",
338
  "**Sua Avaliação:**\n"
339
  ]
340
  prompt = "".join(prompt_parts)
341
  return chamar_gemini_api(prompt, temperature=0.6, max_output_tokens=1000)
342
 
343
- def gerar_resposta_testemunha_defesa_para_treino_ia(fatos_caso, nome_testemunha, pontos_chave_testemunha, historico_perguntas_respostas, pergunta_atual_adv_defesa):
344
  fatos_formatado = fatos_caso if fatos_caso else CASO_DESCRICAO_PREDEFINIDO
345
  contexto_caso_parts = [
346
- "Você está simulando o depoimento de uma testemunha de DEFESA (Jornal) em uma Audiência de Instrução e Julgamento (AIJ) no Brasil.\n",
347
- "O caso envolve Direito ao Esquecimento vs. Liberdade de Imprensa. O jornal (réu) é processado por relembrar um crime antigo (com absolvição) do autor.\n",
348
  f"**Fatos do Caso:** {fatos_formatado}\n"
349
  ]
350
  contexto_caso = "".join(contexto_caso_parts)
351
 
352
  historico_formatado_str = "\nDepoimento até agora:\n"
353
- if historico_perguntas_respostas:
354
- for p, r in historico_perguntas_respostas:
355
  p_escaped = p.replace('"', '\"')
356
  r_escaped = r.replace('"', '\"')
357
  historico_formatado_str += f"- Advogado Defesa: {p_escaped}\n- {nome_testemunha}: {r_escaped}\n"
358
  else:
359
  historico_formatado_str = "Este é o início do seu depoimento."
360
-
361
  pergunta_atual_escaped = pergunta_atual_adv_defesa.replace('"', '\"')
362
 
363
  prompt_parts = [
364
  contexto_caso,
365
  f"\n\n**Persona:** Você é {nome_testemunha}, testemunha arrolada pela DEFESA (Jornal).\n",
366
  f"**Seus Pontos Chave a Defender/Explicar:** {pontos_chave_testemunha}\n",
367
- "Você deve responder às perguntas do advogado de defesa de forma consistente com esses pontos e com a tese da defesa (liberdade de imprensa, interesse público, veracidade, ausência de dolo/culpa, destaque à absolvição do autor no caso original).\n",
368
- "Use linguagem formal, mas acessível para uma testemunha. Seja objetivo e direto. Evite admitir qualquer falha ou negligência por parte do jornal.\n",
369
  historico_formatado_str,
370
  f"\n\n**Pergunta do Advogado de Defesa (Jornal):** \"{pergunta_atual_escaped}\"\n\n",
371
  f"**Sua Resposta ({nome_testemunha}):**\n"
@@ -373,17 +341,21 @@ def gerar_resposta_testemunha_defesa_para_treino_ia(fatos_caso, nome_testemunha,
373
  prompt = "".join(prompt_parts)
374
  return chamar_gemini_api(prompt, temperature=0.5, max_output_tokens=300)
375
 
376
-
377
  def adicionar_fala_transcricao(estado_simulacao, ator, fala):
378
- estado_simulacao["transcricao_logica"].append((ator, fala))
379
- if ator == "Advogado do Réu (Você)": estado_simulacao["transcricao_chat"].append((fala, None))
380
- else:
381
- if estado_simulacao["transcricao_chat"] and estado_simulacao["transcricao_chat"][-1][1] is None:
382
- estado_simulacao["transcricao_chat"][-1] = (estado_simulacao["transcricao_chat"][-1][0], fala)
383
- else: estado_simulacao["transcricao_chat"].append((None, fala))
 
 
 
 
384
  return estado_simulacao
385
 
386
- def mostrar_botoes_corretos(fase_atual):
387
  vis = {
388
  "btn_responder_conciliacao": fase_atual == FASE_ABERTURA_CONCILIACAO,
389
  "btn_chamar_testemunha_reu": fase_atual == FASE_TESTEMUNHAS_REU_INICIO,
@@ -402,16 +374,15 @@ def mostrar_botoes_corretos(fase_atual):
402
  ]
403
  return [gr.update(visible=vis.get(k, False)) for k in all_button_keys]
404
 
405
- def configurar_e_iniciar_simulacao(estado_s, fatos, p_reu, p_autor, t_reu_str, t_autor_str):
406
  novo_estado = estado_inicial_simulacao()
407
  if not fatos or not p_reu or not p_autor:
408
  gr.Warning("Por favor, preencha todos os campos de configuração do caso ou carregue o caso padrão.")
409
  initial_botoes_vis = mostrar_botoes_corretos(novo_estado["fase_aij"])
410
- # Ensure the length matches `outputs_config_list`
411
  return [novo_estado, novo_estado["transcricao_chat"], "Erro: Configuração incompleta.", "Preencha a configuração.", gr.Dropdown(choices=[], value=None, interactive=True)] + initial_botoes_vis
412
 
413
  novo_estado["caso_fatos"], novo_estado["provas_reu_texto"], novo_estado["provas_autor_supostas_texto"] = fatos, p_reu, p_autor
414
- def parse_testemunhas_local(t_str_local): # Renamed to avoid conflict
415
  defs = []
416
  if t_str_local and t_str_local.strip():
417
  for linha in t_str_local.strip().split('\n'):
@@ -440,33 +411,24 @@ def configurar_e_iniciar_simulacao(estado_s, fatos, p_reu, p_autor, t_reu_str, t
440
  gr.Info("Simulação iniciada.")
441
  return [novo_estado, novo_estado["transcricao_chat"], novo_estado["feedback_para_usuario"], novo_estado["instrucao_para_usuario"], gr.Dropdown(choices=nomes_testemunhas_reu, value=None, interactive=True)] + botoes_vis
442
 
443
- def lidar_com_fala_usuario(estado_s, fala_usuario_txt):
 
 
 
 
 
444
  # Allow empty fala_usuario_txt if a button implies an action phase
445
- # This initial check might need refinement if buttons are meant to pass "implicit" text
446
  if not fala_usuario_txt and estado_s["fase_aij"] not in [
447
- FASE_TESTEMUNHAS_REU_INICIO, # User selects witness from dropdown
448
- # Other phases where a button click without text might be primary action
449
- # e.g., some interpretations of "Juiz Avançar"
450
  ]:
451
- # Stricter check for phases truly needing text input
452
- is_text_input_phase = True # Assume true unless it's a pure button-driven phase
453
- if estado_s["fase_aij"] in [FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU, FASE_TESTEMUNHAS_REU_PERGUNTAS_REU, FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR]:
454
- # These might proceed via "Juiz Avançar" if no more questions
455
- pass # Allow empty text if user intends to click "Juiz Avançar"
456
- elif estado_s["fase_aij"] == FASE_ALEGACOES_FINAIS_REU:
457
- pass # User must type allegations
458
- # Add more specific phase checks if needed where empty text + button is valid
459
-
460
- if is_text_input_phase and not fala_usuario_txt: # Redundant check, simplified
461
- # Check if it's a phase where user is expected to type something for the action button
462
- if estado_s["fase_aij"] in [FASE_ABERTURA_CONCILIACAO, FASE_ALEGACOES_FINAIS_REU] or \
463
- (estado_s["fase_aij"] == FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU and not estado_s.get("juiz_avancando", False)) or \
464
- (estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_PERGUNTAS_REU and not estado_s.get("juiz_avancando", False) and estado_s.get("testemunha_em_depoimento")) or \
465
- (estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR and estado_s.get("testemunha_em_depoimento")):
466
-
467
- estado_s["instrucao_para_usuario"] = "Por favor, digite sua fala ou selecione uma ação que não exija texto."
468
  return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"], gr.Textbox(value="")] + mostrar_botoes_corretos(estado_s["fase_aij"])
469
-
470
 
471
  estado_s = copy.deepcopy(estado_s)
472
  ator_usuario = "Advogado do Réu (Você)"
@@ -504,20 +466,20 @@ def lidar_com_fala_usuario(estado_s, fala_usuario_txt):
504
  elif estado_s["testemunhas_reu_defs"]:
505
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
506
  estado_s["instrucao_para_usuario"] = "Selecione sua testemunha para chamar."
507
- else:
508
  estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
509
  estado_s["instrucao_para_usuario"] = "Aguarde Juiz iniciar Alegações Finais."
510
- fala_juiz_aleg = gerar_resposta_juiz_ia(estado_s)
511
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_aleg)
512
- fala_aleg_autor = gerar_resposta_advogado_autor_ia(estado_s)
513
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_aleg_autor)
514
- estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_REU
515
  estado_s["instrucao_para_usuario"] = "Apresente suas Alegações Finais."
516
- else:
517
  estado_s["instrucao_para_usuario"] = "Responda ao Juiz ou Adv. Autor sobre conciliação."
518
 
519
  elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU:
520
- if not fala_usuario_txt:
521
  estado_s["instrucao_para_usuario"] = "Faça uma pergunta à testemunha do Autor ou clique em 'Juiz (IA): Avançar Fase' para encerrar."
522
  else:
523
  fala_test_autor = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_usuario_txt)
@@ -525,31 +487,31 @@ def lidar_com_fala_usuario(estado_s, fala_usuario_txt):
525
  estado_s["instrucao_para_usuario"] = f"Faça outra pergunta à testemunha {estado_s['testemunha_em_depoimento']['nome']} (Autor) ou clique 'Juiz Avançar'."
526
 
527
  elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_PERGUNTAS_REU:
528
- if not fala_usuario_txt : # User must provide a question to their witness
529
  estado_s["instrucao_para_usuario"] = f"Por favor, faça uma pergunta à sua testemunha {estado_s['testemunha_em_depoimento']['nome']}."
530
  else:
531
- # Adv. Réu (usuário) fez uma pergunta à sua testemunha.
532
- # A RESPOSTA da testemunha do réu virá do usuário na PRÓXIMA interação (FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR, após o Adv. Autor perguntar).
533
- # Por agora, o Adv. Autor (IA) pode fazer perguntas à testemunha do Réu.
 
534
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR
535
- fala_adv_autor_ia = gerar_resposta_advogado_autor_ia(estado_s) # Adv. Autor IA pergunta à testemunha do Réu
536
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor_ia)
537
  estado_s["instrucao_para_usuario"] = f"Como testemunha {estado_s['testemunha_em_depoimento']['nome']}, responda à pergunta do Adv. Autor."
538
 
539
- elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR: # Usuário está respondendo como sua testemunha
540
  if not fala_usuario_txt:
541
  estado_s["instrucao_para_usuario"] = f"Como testemunha {estado_s['testemunha_em_depoimento']['nome']}, por favor, responda à pergunta do Adv. Autor."
542
  else:
543
- # fala_usuario_txt é a resposta da Testemunha do Réu (digitada pelo usuário) à pergunta do Adv. Autor.
544
- # Agora, o Advogado do Autor (IA) pode fazer mais perguntas ou encerrar.
545
- fala_adv_autor_ia = gerar_resposta_advogado_autor_ia(estado_s, fala_adv_reu=fala_usuario_txt) # Passa a resposta da testemunha do réu
546
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor_ia)
547
  if ("pergunta" in fala_adv_autor_ia.lower() or "?" in fala_adv_autor_ia) and not any(k in fala_adv_autor_ia.lower() for k in ["não tenho mais perguntas", "encerro", "nada mais"]):
548
  estado_s["instrucao_para_usuario"] = f"Como testemunha {estado_s['testemunha_em_depoimento']['nome']}, responda à nova pergunta do Adv. Autor."
549
- else: # Adv. Autor não tem mais perguntas
550
  fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica=f"Adv. Autor encerrou inquirição da testemunha {estado_s['testemunha_em_depoimento']['nome']}. Adv. Réu pode fazer mais perguntas ou dispensar.")
551
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
552
- estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_PERGUNTAS_REU # Volta para Adv. Réu perguntar à sua testemunha
553
  estado_s["instrucao_para_usuario"] = f"Faça mais perguntas à sua testemunha {estado_s['testemunha_em_depoimento']['nome']}, ou clique 'Juiz Avançar' para dispensá-la."
554
 
555
  elif estado_s["fase_aij"] == FASE_ALEGACOES_FINAIS_REU:
@@ -563,16 +525,16 @@ def lidar_com_fala_usuario(estado_s, fala_usuario_txt):
563
 
564
  estado_s["feedback_para_usuario"] = analisar_atuacao_defesa_ia(estado_s, ultima_fala_reu=fala_usuario_txt if ator_usuario == "Advogado do Réu (Você)" else "")
565
  gr.Info("Respostas da IA geradas.")
566
- return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"], gr.Textbox(value="")] + mostrar_botoes_corretos(estado_s["fase_aij"])
567
 
568
- def acao_botao_juiz_avancar(estado_s):
 
569
  estado_s = copy.deepcopy(estado_s)
570
  fase_atual = estado_s["fase_aij"]
571
  gr.Info(f"Avançando fase a partir de: {fase_atual}. Aguarde IA...")
572
 
573
  if fase_atual == FASE_ABERTURA_CONCILIACAO:
574
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", "Considerando frustrada a tentativa de conciliação ou por avanço solicitado, passaremos à instrução.")
575
- # ... (restante da lógica como antes)
576
  if estado_s["testemunhas_autor_supostas_defs"]:
577
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_AUTOR_INICIO
578
  fala_juiz = gerar_resposta_juiz_ia(estado_s)
@@ -589,35 +551,33 @@ def acao_botao_juiz_avancar(estado_s):
589
  estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {t_info['nome']} (Autor - IA)", fala_test_autor)
590
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU
591
  estado_s["instrucao_para_usuario"] = f"Contradite ou faça perguntas à testemunha {t_info['nome']} (Autor)."
592
- else: # Adv Autor não tem testemunhas
593
  if estado_s["testemunhas_reu_defs"]:
594
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
595
  estado_s["instrucao_para_usuario"] = "Selecione sua testemunha para chamar."
596
- # Juiz deve falar
597
  fala_juiz_trans = gerar_resposta_juiz_ia(estado_s)
598
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_trans)
599
 
600
- else: estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR # Pula para alegações finais
601
  elif estado_s["testemunhas_reu_defs"]:
602
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
603
  fala_juiz = gerar_resposta_juiz_ia(estado_s)
604
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
605
  estado_s["instrucao_para_usuario"] = "Selecione sua testemunha para chamar."
606
- else: # Sem testemunhas de nenhuma parte
607
  estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
608
- fala_juiz = gerar_resposta_juiz_ia(estado_s) # Juiz anuncia alegações
609
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
610
- fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv Autor faz alegações
611
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
612
  estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_REU
613
  estado_s["instrucao_para_usuario"] = "Apresente suas Alegações Finais."
614
 
615
- elif fase_atual == FASE_TESTEMUNHAS_AUTOR_INICIO: # Covers FASE_TESTEMUNHAS_AUTOR_PERGUNTAS_AUTOR implicitly
616
  fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Verificar se há mais testemunhas do Autor ou encerrar esta fase.")
617
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
618
  fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s)
619
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
620
-
621
  if "Não tenho mais testemunhas" in fala_adv_autor or "Não arrolei testemunhas" in fala_adv_autor or estado_s["testemunha_autor_atual_idx"] +1 >= len(estado_s["testemunhas_autor_supostas_defs"]):
622
  estado_s["testemunha_em_depoimento"] = None
623
  if estado_s["testemunhas_reu_defs"]:
@@ -644,7 +604,6 @@ def acao_botao_juiz_avancar(estado_s):
644
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU
645
  estado_s["instrucao_para_usuario"] = f"Contradite ou faça perguntas à testemunha {t_info['nome']} (Autor)."
646
 
647
-
648
  elif fase_atual == FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU:
649
  estado_s["testemunha_em_depoimento"] = None
650
  if estado_s["testemunha_autor_atual_idx"] + 1 < len(estado_s["testemunhas_autor_supostas_defs"]):
@@ -701,11 +660,9 @@ def acao_botao_juiz_avancar(estado_s):
701
  fala_juiz_dispensa = gerar_resposta_juiz_ia(estado_s, acao_especifica=f"Dispensar {nome_test_dispensada}. Verificar se Adv. Réu tem mais testemunhas ou se encerrou sua instrução probatória.")
702
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_dispensa)
703
 
704
- # Check if there are more witnesses for Réu AND if Juiz's speech doesn't imply moving to alegacoes
705
  more_reu_witnesses = estado_s["testemunha_reu_atual_idx"] + 1 < len(estado_s["testemunhas_reu_defs"])
706
  juiz_wants_to_continue_with_reu_witnesses = not any(k in fala_juiz_dispensa.lower() for k in ["alegações", "encerrada instrução", "sentença"])
707
 
708
-
709
  if more_reu_witnesses and juiz_wants_to_continue_with_reu_witnesses:
710
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
711
  estado_s["instrucao_para_usuario"] = "Selecione sua próxima testemunha para chamar ou clique 'Juiz Avançar' novamente para encerrar oitiva das suas testemunhas."
@@ -733,7 +690,8 @@ def acao_botao_juiz_avancar(estado_s):
733
  botoes_vis = mostrar_botoes_corretos(estado_s["fase_aij"])
734
  return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + botoes_vis
735
 
736
- def chamar_testemunha_reu_selecionada(estado_s, nome_testemunha_selecionada):
 
737
  estado_s = copy.deepcopy(estado_s)
738
  if not nome_testemunha_selecionada:
739
  estado_s["instrucao_para_usuario"] = "Nenhuma testemunha selecionada. Por favor, selecione uma testemunha da lista."
@@ -761,19 +719,20 @@ def chamar_testemunha_reu_selecionada(estado_s, nome_testemunha_selecionada):
761
  botoes_vis = mostrar_botoes_corretos(estado_s["fase_aij"])
762
  return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + botoes_vis
763
 
764
- _historico_treino_testemunha_atual = []
765
- def gerar_dialogo_testemunha_defesa_para_treino_ui(fatos_caso_atual, testemunhas_reu_defs_atual_str, testemunha_selecionada_nome, pergunta_adv_defesa_treino): # Renamed
766
- global _historico_treino_testemunha_atual
 
767
  if not GEMINI_API_KEY:
768
- _historico_treino_testemunha_atual.append( (None, "ERRO: API Key não configurada.") )
769
- return _historico_treino_testemunha_atual, ""
770
 
771
  if not testemunha_selecionada_nome:
772
- _historico_treino_testemunha_atual.append( (None, "Por favor, selecione uma testemunha da sua lista na aba 'Configuração'.") )
773
- return _historico_treino_testemunha_atual, ""
774
- if not pergunta_adv_defesa_treino: # Use new name
775
- _historico_treino_testemunha_atual.append( (None, "Por favor, digite sua pergunta para a testemunha.") )
776
- return _historico_treino_testemunha_atual, ""
777
 
778
  testemunhas_reu_defs_usar = []
779
  if testemunhas_reu_defs_atual_str:
@@ -793,49 +752,71 @@ def gerar_dialogo_testemunha_defesa_para_treino_ui(fatos_caso_atual, testemunhas
793
  testemunhas_reu_defs_usar = TESTEMUNHAS_REU_PREDEFINIDAS
794
 
795
  testemunha_obj = next((t for t in testemunhas_reu_defs_usar if t["nome"] == testemunha_selecionada_nome), None)
796
- if not testemunha_obj:
797
  testemunha_obj = next((t for t in TESTEMUNHAS_REU_PREDEFINIDAS if t["nome"] == testemunha_selecionada_nome), None)
798
  if not testemunha_obj:
799
- _historico_treino_testemunha_atual.append( (None, f"Testemunha '{testemunha_selecionada_nome}' não encontrada. Verifique a aba 'Configuração'.") )
800
- return _historico_treino_testemunha_atual, ""
801
 
802
  # Smart reset of history
803
- if not _historico_treino_testemunha_atual or \
804
- not _historico_treino_testemunha_atual[0][1] or \
805
- not _historico_treino_testemunha_atual[0][1].startswith(f"Iniciando inquirição de **{testemunha_obj['nome']}**"):
806
- _historico_treino_testemunha_atual = []
807
- _historico_treino_testemunha_atual.append( (None, f"Iniciando inquirição de **{testemunha_obj['nome']}**. Pontos chave: {testemunha_obj['pontos_chave']}") )
 
 
 
 
808
 
 
809
  gr.Info(f"Gerando resposta da testemunha {testemunha_obj['nome']}... Aguarde.")
810
- valid_history = [(q,r) for q,r in _historico_treino_testemunha_atual if q is not None]
 
 
 
 
 
 
 
 
 
 
 
 
811
 
812
  resposta_testemunha = gerar_resposta_testemunha_defesa_para_treino_ia(
813
  fatos_caso_atual if fatos_caso_atual else CASO_FATOS_COMPLETO_PREDEFINIDO,
814
  testemunha_obj['nome'],
815
  testemunha_obj['pontos_chave'],
816
- valid_history,
817
- pergunta_adv_defesa_treino # Use new name
818
  )
819
- _historico_treino_testemunha_atual.append( (pergunta_adv_defesa_treino, resposta_testemunha) ) # Use new name
820
  gr.Info("Resposta da testemunha gerada.")
821
- return _historico_treino_testemunha_atual, ""
822
 
 
 
 
 
823
 
824
  # --- Interface Gráfica (Gradio UI) ---
825
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"), title="Simulador AIJ Interativo") as demo:
826
  gr.Markdown("# ⚖️ Simulador Interativo de Audiência de Instrução e Julgamento (AIJ)")
 
827
  gr.Markdown("Tema: **Direito ao Esquecimento vs. Liberdade de Imprensa**. Você assume o papel de **Advogado(a) do Réu (Jornal)**.")
828
  if not GEMINI_API_KEY:
829
- gr.Warning("API Key do Gemini (GEMINI_API_KEY) não encontrada! O aplicativo pode não funcionar corretamente. Configure-a como Secret neste Space ou localmente como variável de ambiente.")
830
 
831
  sim_state = gr.State(value=estado_inicial_simulacao())
832
 
833
  with gr.Tabs() as abas_principais:
834
  with gr.TabItem("1. Configuração do Caso", id=0):
835
  gr.Markdown("## Detalhes do Caso para Simulação")
836
- # ... (UI elements as before) ...
837
- btn_gerar_caso_ia = gr.Button("✨ Gerar Novo Caso com IA", icon="🧠", scale=1)
838
- btn_carregar_caso_padrao = gr.Button("📄 Carregar Caso Padrão (Esquecimento)", icon="📜", scale=1)
839
  with gr.Row():
840
  with gr.Column(scale=2):
841
  fatos_input = gr.Textbox(lines=7, label="Resumo dos Fatos, Partes e Título:", placeholder="Descreva o caso ou gere/carregue.")
@@ -855,7 +836,13 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
855
  with gr.TabItem("2. Audiência Interativa", id=1):
856
  gr.Markdown("## Andamento da Audiência Simulada")
857
  instrucao_usuario_output = gr.Markdown("Instrução: Configure o caso na aba 'Configuração' e clique em 'Salvar e Iniciar' para começar.")
858
- chat_aij_output = gr.Chatbot(label="Transcrição da Audiência", height=500, bubble_full_width=False, show_copy_button=True, avatar_images=(None, "https://img.icons8.com/fluency/96/robot-2.png"))
 
 
 
 
 
 
859
  fala_usuario_input = gr.Textbox(show_label=False, placeholder="Digite sua fala aqui ou use os botões de ação abaixo...", scale=4, lines=3)
860
 
861
  btn_responder_conciliacao = gr.Button("Responder à Conciliação", visible=False)
@@ -868,9 +855,8 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
868
  btn_juiz_avancar_fase_action = gr.Button("⚖️ Juiz (IA): Concluir Etapa / Avançar Fase", visible=False, variant="secondary")
869
 
870
  with gr.Row():
871
- btn_enviar_fala_usuario = gr.Button("🎤 Enviar Fala / Ação", variant="stop", scale=2)
872
- gr.Space(scale=1)
873
- btn_juiz_avancar_fase_action_display = btn_juiz_avancar_fase_action # Assign to new var for display layout
874
 
875
  with gr.Accordion("Ações Contextuais do Advogado do Réu (Você)", open=True):
876
  with gr.Row():
@@ -883,7 +869,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
883
  btn_adv_reu_responde_pela_sua_testemunha_action_display = btn_adv_reu_responde_pela_sua_testemunha_action
884
  btn_apresentar_alegacoes_finais_reu_action_display = btn_apresentar_alegacoes_finais_reu_action
885
 
886
- lista_botoes_feedback = [ # This list defines the order for gr.update
887
  btn_responder_conciliacao, btn_chamar_testemunha_reu_action, dropdown_testemunhas_reu_select,
888
  btn_perguntar_testemunha_autor_action, btn_adv_reu_pergunta_sua_testemunha_action,
889
  btn_adv_reu_responde_pela_sua_testemunha_action, btn_apresentar_alegacoes_finais_reu_action,
@@ -892,13 +878,11 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
892
 
893
  with gr.TabItem("3. Feedback da Atuação (Professor IA)", id=2):
894
  gr.Markdown("## 💡 Análise da Sua Atuação na Audiência Interativa")
895
- # ... (UI elements as before) ...
896
  feedback_output = gr.Textbox(lines=20, label="Feedback Detalhado:", interactive=False, show_copy_button=True)
897
 
898
 
899
  with gr.TabItem("4. Treinamento de Argumentação (Defesa)", id=3):
900
  gr.Markdown("## 🗣️ Pratique e Avalie Seus Argumentos (Advogado de Defesa)")
901
- # ... (UI elements as before, ensure variable names for inputs are unique if needed) ...
902
  fatos_caso_treino_arg_display_tab4 = gr.Textbox(label="Fatos do Caso (da Configuração):", value=CASO_FATOS_COMPLETO_PREDEFINIDO, lines=5, interactive=False)
903
  provas_reu_treino_arg_display_tab4 = gr.Textbox(label="Provas do Réu (da Configuração):", value=PROVAS_REU_TEXTO_PREDEFINIDO, lines=5, interactive=False)
904
  tipo_argumento_treino_tab4 = gr.Radio(
@@ -920,7 +904,6 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
920
 
921
  with gr.TabItem("5. Preparar Testemunhas (Defesa)", id=4):
922
  gr.Markdown("## 🎙️ Simule a Inquirição das Suas Testemunhas (Defesa)")
923
- # ... (UI elements as before, ensure variable names are unique if needed) ...
924
  fatos_caso_treino_test_display_tab5 = gr.Textbox(label="Fatos do Caso (da Configuração):", value=CASO_FATOS_COMPLETO_PREDEFINIDO, lines=5, interactive=False)
925
  testemunhas_reu_config_treino_display_tab5 = gr.Textbox(label="Definição das Testemunhas do Réu (da Configuração):", value=TESTEMUNHAS_REU_TEXTO_PREDEFINIDO, lines=3, interactive=False)
926
 
@@ -939,17 +922,18 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
939
  return gr.Dropdown(choices=nomes if nomes else [t['nome'] for t in TESTEMUNHAS_REU_PREDEFINIDAS], value=nomes[0] if nomes else None, interactive=True)
940
  testemunhas_reu_input.change(update_dropdown_treino_choices_tab5, inputs=testemunhas_reu_input, outputs=dropdown_testemunhas_reu_treino_tab5)
941
 
942
- chat_treino_testemunha_tab5 = gr.Chatbot(label="Simulação de Depoimento (Treino)", height=300, show_copy_button=True, bubble_full_width=False, avatar_images=(None, "https://img.icons8.com/officel/80/person-male.png"))
 
 
 
 
 
 
943
  pergunta_testemunha_treino_input_tab5 = gr.Textbox(label="Sua Pergunta para a Testemunha:", placeholder="Ex: 'Senhor Silva, poderia descrever o procedimento editorial?'")
944
  btn_perguntar_testemunha_treino_tab5 = gr.Button("💬 Perguntar à Testemunha (IA)", variant="primary")
945
  btn_limpar_chat_treino_testemunha_tab5 = gr.Button("🗑️ Limpar Chat de Treino")
946
-
947
- def limpar_chat_treino_tab5():
948
- global _historico_treino_testemunha_atual
949
- _historico_treino_testemunha_atual = []
950
- return [], ""
951
  btn_limpar_chat_treino_testemunha_tab5.click(limpar_chat_treino_tab5, outputs=[chat_treino_testemunha_tab5, pergunta_testemunha_treino_input_tab5])
952
-
953
  btn_perguntar_testemunha_treino_tab5.click(
954
  gerar_dialogo_testemunha_defesa_para_treino_ui,
955
  inputs=[fatos_caso_treino_test_display_tab5, testemunhas_reu_config_treino_display_tab5, dropdown_testemunhas_reu_treino_tab5, pergunta_testemunha_treino_input_tab5],
@@ -957,12 +941,12 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
957
  )
958
 
959
  with gr.TabItem("ℹ️ Ajuda / Sobre o Caso Padrão", id=5):
 
960
  gr.Markdown("## Sobre o Caso Padrão: Direito ao Esquecimento vs. Liberdade de Imprensa")
961
- # ... (UI elements as before) ...
962
  gr.Markdown(f"**Título:** {CASO_TITULO_PREDEFINIDO}")
963
- md_partes = CASO_PARTES_PREDEFINIDO.replace("\n", "\n\n") # Ensure markdown newlines
964
  gr.Markdown(f"**Partes:**\n{md_partes}")
965
- gr.Markdown(f"**Resumo do Caso:**\n{CASO_DESCRICAO_PREDEFINIDO}") # This is already multiline
966
  with gr.Accordion("Argumentos Principais do Autor (Caso Padrão)", open=False):
967
  gr.Markdown("\n".join([f"- {arg}" for arg in ARGUMENTOS_AUTOR_PREDEFINIDOS]))
968
  with gr.Accordion("Argumentos Principais do Réu/Jornal (Caso Padrão)", open=False):
@@ -971,7 +955,6 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
971
  gr.Markdown("\n".join([f"- **{t['nome']}**: {t['pontos_chave']}" for t in TESTEMUNHAS_REU_PREDEFINIDAS]))
972
 
973
  gr.Markdown("### Legislação e Precedentes Relevantes (Geral)")
974
- # ... (rest of the help tab content) ...
975
  with gr.Row():
976
  with gr.Column():
977
  gr.Markdown("**Potencialmente Favoráveis ao Réu (Jornal):**")
@@ -980,63 +963,28 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
980
  gr.Markdown("**Potencialmente Favoráveis ao Autor:**")
981
  gr.Markdown("\n".join([f"- {lei}" for lei in LEGISLACAO_PRECEDENTES_PREDEFINIDO["favoraveis_ao_autor"]]))
982
  gr.Markdown("""
983
- ## Como utilizar este simulador:
984
- 1. **Configuração (Aba 1):**
985
- * **Gerar Novo Caso com IA:** Cria um caso fictício aleatório sobre o tema.
986
- * **Carregar Caso Padrão:** Preenche os campos com o "Caso da Reportagem Revisitada".
987
- * Ou preencha manualmente os detalhes do seu próprio caso.
988
- * **Salve e Inicie:** Fundamental para começar a simulação interativa.
989
- 2. **Audiência Interativa (Aba 2):**
990
- * O núcleo da simulação. Siga as instruções e interaja como Advogado(a) do Réu.
991
- * Use o campo de texto para suas falas ou os botões de ação contextual.
992
- * O "Juiz (IA): Avançar Fase" é usado para progredir quando você conclui sua parte em uma etapa ou quando a IA indica.
993
- 3. **Feedback da Atuação (Aba 3):**
994
- * Após interagir na Aba 2, verifique aqui a análise da IA sobre sua performance.
995
- 4. **Treinamento de Argumentação (Aba 4):**
996
- * Use para praticar a redação de argumentos específicos (ex: para contestação, alegações finais) e receber feedback da IA. Baseia-se nos fatos e provas configurados na Aba 1.
997
- 5. **Preparar Testemunhas (Aba 5):**
998
- * Treine a inquirição das suas testemunhas (do Réu). Você faz as perguntas, e a IA responde como se fosse a testemunha selecionada, baseando-se nos "pontos chave" definidos na Aba 1.
999
- ## Dicas para Atuação como Advogado(a) do Réu (Jornal):
1000
- * **Liberdade de Imprensa:** Seu principal argumento. Fundamente com a Constituição.
1001
- * **Interesse Público:** Demonstre a relevância da matéria.
1002
- * **Veracidade dos Fatos:** Crucial. A matéria deve ser factualmente correta.
1003
- * **Ausência de Dolo/Culpa:** Argumente que não houve intenção de prejudicar, apenas informar.
1004
- * **Menção à Absolvição:** Se o autor foi absolvido e a matéria menciona isso, é um ponto forte para a defesa.
1005
- * **Precedentes (STF):** Cite o RE 1.010.606, que ponderou o direito ao esquecimento com a liberdade de informação.
1006
- * **Contraditório:** Explore as perguntas às testemunhas do Autor para enfraquecer a tese dele.
1007
- * **Suas Testemunhas:** Prepare-as para reforçar a tese da defesa.
1008
  """)
1009
 
1010
-
1011
  # --- Event Handlers ---
1012
- # Outputs for config_iniciar and other main simulation actions
1013
- # Must exactly match the number of components in lista_botoes_feedback + 5 base outputs
1014
- main_sim_outputs = [
1015
- sim_state, chat_aij_output, feedback_output, instrucao_usuario_output,
1016
- fala_usuario_input, # For clearing the input
1017
- ] + lista_botoes_feedback # fala_usuario_input is one of the 5, dropdown is another one.
1018
-
1019
  outputs_config_list = [
1020
  sim_state, chat_aij_output, feedback_output, instrucao_usuario_output,
1021
- dropdown_testemunhas_reu_select # This is one of the outputs for config_iniciar
1022
  ] + lista_botoes_feedback
1023
 
1024
-
1025
  btn_config_iniciar.click(
1026
  configurar_e_iniciar_simulacao,
1027
  inputs=[sim_state, fatos_input, provas_reu_input, provas_autor_input, testemunhas_reu_input, testemunhas_autor_supostas_input],
1028
- outputs=outputs_config_list # Uses the specific list for this button
1029
  ).then(lambda: gr.Textbox(value=""), outputs=[fala_usuario_input]
1030
  ).then(lambda: gr.Tabs(selected=1), inputs=None, outputs=[abas_principais])
1031
 
1032
-
1033
- # Outputs for fala_usuario and general actions that update the main sim display
1034
  outputs_fala_usuario_and_actions_list = [
1035
  sim_state, chat_aij_output, feedback_output, instrucao_usuario_output,
1036
- fala_usuario_input # To clear it
1037
  ] + lista_botoes_feedback
1038
 
1039
-
1040
  btn_enviar_fala_usuario.click(lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list)
1041
  fala_usuario_input.submit(lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list)
1042
 
@@ -1044,10 +992,8 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
1044
  btn_chamar_testemunha_reu_action.click(chamar_testemunha_reu_selecionada, inputs=[sim_state, dropdown_testemunhas_reu_select], outputs=outputs_fala_usuario_and_actions_list).then(lambda: gr.Textbox(value=""), outputs=[fala_usuario_input])
1045
 
1046
  def create_button_click_handler_wrapper(info_message):
1047
- # This closure will ensure that info_message is fixed at definition time
1048
  def actual_handler_for_button(current_sim_state, current_fala_usuario_input_text):
1049
- gr.Info(info_message) # Show info message related to the button
1050
- # Then, proceed to call the main logic handler with the current state and text from the input box
1051
  return lidar_com_fala_usuario(current_sim_state, current_fala_usuario_input_text)
1052
  return actual_handler_for_button
1053
 
@@ -1055,6 +1001,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
1055
  create_button_click_handler_wrapper("Conciliação: Digite sua resposta no campo de fala e clique 'Enviar Fala / Ação'."),
1056
  inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list
1057
  )
 
1058
  btn_perguntar_testemunha_autor_action.click(
1059
  create_button_click_handler_wrapper("Perg. Test. Autor: Digite sua pergunta no campo de fala e clique 'Enviar Fala / Ação'."),
1060
  inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list
@@ -1072,76 +1019,36 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
1072
  inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list
1073
  )
1074
 
1075
- def setup_initial_ui_state_load_wrapper(s_val_load): # Renamed to avoid conflict
 
 
 
 
 
 
1076
  initial_fase = s_val_load["fase_aij"]
1077
  dropdown_choices_load = [t["nome"] for t in s_val_load.get("testemunhas_reu_defs", [])] if s_val_load.get("testemunhas_reu_defs") else []
1078
  updates_for_buttons_load = mostrar_botoes_corretos(initial_fase)
1079
 
1080
- # Ensure the order and number match outputs_on_load_list
1081
- # Base: sim_state, chat, feedback, instrucao, dropdown
1082
- # Then: buttons in order of lista_botoes_feedback
1083
- # lista_botoes_feedback has 8 items. dropdown is 1. base is 4. Total 13.
1084
- # dropdown_testemunhas_reu_select is the 3rd item in lista_botoes_feedback.
1085
- # The gr.update for dropdown_testemunhas_reu_select should be handled within updates_for_buttons_load.
1086
-
1087
- # Reconstruct the return tuple carefully
1088
- return_tuple_elements = [
1089
- s_val_load,
1090
- s_val_load["transcricao_chat"],
1091
- s_val_load["feedback_para_usuario"],
1092
- s_val_load["instrucao_para_usuario"],
1093
- gr.Dropdown(choices=dropdown_choices_load, value=None, interactive=True) # This targets dropdown_testemunhas_reu_select
1094
- ] + updates_for_buttons_load
1095
-
1096
- # The gr.Dropdown update specifically targets the dropdown_testemunhas_reu_select component.
1097
- # The updates_for_buttons_load list contains gr.update objects for *all* buttons in lista_botoes_feedback.
1098
- # We need to make sure the component targeted by gr.Dropdown is also covered by one of the gr.update calls in updates_for_buttons_load if its visibility changes.
1099
- # `mostrar_botoes_corretos` already handles the visibility for `dropdown_testemunhas_reu`.
1100
- # So, the `gr.Dropdown(...)` explicit update here is for choices and value.
1101
-
1102
- # Let's simplify: `mostrar_botoes_corretos` should return updates for all listed buttons.
1103
- # The specific update for dropdown (choices, value) is separate.
1104
-
1105
- # The `outputs` for demo.load are:
1106
- # [sim_state, chat_aij_output, feedback_output, instrucao_usuario_output, dropdown_testemunhas_reu_select] + lista_botoes_feedback
1107
- # Index 4 is dropdown_testemunhas_reu_select.
1108
- # The rest are the buttons from lista_botoes_feedback.
1109
-
1110
- # Correct return structure:
1111
  final_return_list = [
1112
  s_val_load,
1113
- s_val_load["transcricao_chat"],
1114
  s_val_load["feedback_para_usuario"],
1115
  s_val_load["instrucao_para_usuario"],
1116
- gr.Dropdown(choices=dropdown_choices_load, value=None, interactive=True) # For output index 4
1117
  ]
1118
- # Now add the updates for the buttons. `mostrar_botoes_corretos` provides these.
1119
- # Ensure the order in `lista_botoes_feedback` matches how `mostrar_botoes_corretos` generates them.
1120
- # `mostrar_botoes_corretos` sorts its internal `vis` dict by key before creating updates.
1121
- # `lista_botoes_feedback` must also be sorted by the same key logic if we want a direct match,
1122
- # OR `mostrar_botoes_corretos` should return a dict of updates keyed by component.
1123
- # For now, assuming `mostrar_botoes_corretos` returns updates in the order of `all_button_keys` it defines.
1124
- # And `lista_botoes_feedback` is the list of components in that order.
1125
-
1126
- final_return_list.extend(updates_for_buttons_load) # Add updates for all buttons
1127
  return tuple(final_return_list)
1128
 
1129
- # Define outputs_on_load_list to match the setup_initial_ui_state_load_wrapper's return structure
1130
- outputs_on_load_list = [
1131
- sim_state, chat_aij_output, feedback_output, instrucao_usuario_output,
1132
- dropdown_testemunhas_reu_select # This is the 5th output
1133
- ] + lista_botoes_feedback # These are the next 8 outputs
1134
-
1135
  demo.load(
1136
  setup_initial_ui_state_load_wrapper,
1137
  inputs=[sim_state],
1138
  outputs=outputs_on_load_list
1139
  )
1140
 
1141
-
1142
  if __name__ == "__main__":
1143
  if not GEMINI_API_KEY:
1144
  print("#####################################################################")
1145
- print("ATENÇÃO: GEMINI_API_KEY não configurada como variável de ambiente.")
1146
- # ... (rest of the message) ...
1147
  demo.queue(max_size=20).launch(debug=True)
 
8
  GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
9
  if not GEMINI_API_KEY:
10
  print("ALERTA: GEMINI_API_KEY não encontrada como Secret no Hugging Face Space. O app não funcionará.")
11
+ # GEMINI_API_KEY = "SUA_CHAVE_AQUI_PARA_TESTE_LOCAL_APENAS"
12
 
13
  MODEL_NAME = "gemini-1.5-flash-latest"
14
  API_URL_BASE = f"https://generativelanguage.googleapis.com/v1beta/models/{MODEL_NAME}:generateContent"
 
17
  FASE_INICIAL_CONFIG = "CONFIGURACAO"
18
  FASE_ABERTURA_CONCILIACAO = "ABERTURA_E_CONCILIACAO"
19
  FASE_TESTEMUNHAS_AUTOR_INICIO = "TESTEMUNHAS_AUTOR_INICIO"
 
20
  FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU = "TESTEMUNHAS_AUTOR_CONTRADITA_REU"
21
  FASE_TESTEMUNHAS_REU_INICIO = "TESTEMUNHAS_REU_INICIO"
22
  FASE_TESTEMUNHAS_REU_PERGUNTAS_REU = "TESTEMUNHAS_REU_PERGUNTAS_REU"
 
54
  ]
55
  PROVAS_AUTOR_SUPPOSTAS_TEXTO_PREDEFINIDO = "\n".join(ARGUMENTOS_AUTOR_PREDEFINIDOS)
56
 
57
+ CONTRA_ARGUMENTOS_REU_PREDEFINIDOS_LIST = [
58
  "Argumento: A liberdade de imprensa é um direito fundamental e a matéria é de interesse público histórico. Prova: Art. 5º, IX e XIV da CF/88; Doutrina sobre liberdade de imprensa.",
59
  "Argumento: A matéria baseia-se inteiramente em informações verídicas e de acesso público (processo judicial). Prova: Cópia da matéria original e da recente, certidão do processo.",
60
  "Argumento: O STF (RE 1.010.606) não reconheceu o direito ao esquecimento de forma absoluta, ponderando-o com a liberdade de informação. Prova: Inteiro teor do acórdão do RE 1.010.606.",
 
95
  "provas_autor_supostas_texto": "", "testemunhas_reu_defs": [],
96
  "testemunhas_autor_supostas_defs": [], "testemunha_autor_atual_idx": -1,
97
  "testemunha_reu_atual_idx": -1, "testemunha_em_depoimento": None,
98
+ "transcricao_chat": [], "transcricao_logica": [], # transcricao_chat will be list of dicts
99
  "feedback_para_usuario": "Aguardando início da simulação.",
100
  "instrucao_para_usuario": "Configure os detalhes do caso na aba 'Configuração' ou carregue o caso padrão."
101
  }
 
141
  def formatar_historico_para_prompt(transcricao_logica, max_turns=15):
142
  historico_formatado = "\nContexto da Audiência (últimas interações):\n"
143
  for ator, fala in transcricao_logica[-max_turns:]:
144
+ fala_escaped = fala.replace('"', '\"') # Escape quotes for safety in prompt
145
  historico_formatado += f"- {ator}: {fala_escaped}\n"
146
  return historico_formatado
147
 
148
  def gerar_caso_ficticio_com_ia():
149
  prompt_geracao_caso = """
150
+ **Instrução de Persona:** Você é um roteirista jurídico criativo e experiente...
151
+ (Conteúdo do prompt como antes)
152
+ ...## Testemunhas Hipotéticas da Parte RÉ`
153
+ """ # Mantido como antes
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  texto_caso_completo = chamar_gemini_api(prompt_geracao_caso, temperature=0.75, max_output_tokens=2500)
155
  if "ERRO_" in texto_caso_completo:
156
  return {"fatos": f"Falha ao gerar caso com IA: {texto_caso_completo}", "provas_autor": "", "provas_reu": "", "testemunhas_autor": "", "testemunhas_reu": ""}
157
  return parse_caso_gerado(texto_caso_completo)
158
 
159
+ def parse_caso_gerado(texto_completo_caso): # Mantido como antes
160
  dados_caso = {"fatos": "Falha parsing: Fatos", "provas_autor": "Falha parsing: Provas Autor", "provas_reu": "Falha parsing: Provas Réu", "testemunhas_autor": "Falha parsing: Testemunhas Autor", "testemunhas_reu": "Falha parsing: Testemunhas Réu"}
161
  secoes = {"fatos": "## Resumo Detalhado dos Fatos", "provas_autor": "## Argumentos e \"Provas\" Hipotéticas da Parte AUTORA", "provas_reu": "## Argumentos e \"Provas\" Hipotéticas da Parte RÉ (Jornal)", "testemunhas_autor": "## Testemunhas Hipotéticas da Parte AUTORA", "testemunhas_reu": "## Testemunhas Hipotéticas da Parte RÉ"}
162
  fatos_prefix = ""
 
197
  dados_caso[key_testemunha] = "\n".join(linhas_formatadas)
198
  return dados_caso
199
 
200
+ def acao_gerar_caso_ficticio_ui(): # Mantido como antes
201
  gr.Info("Gerando caso fictício com IA... Isso pode levar um momento.")
202
  dados_gerados = gerar_caso_ficticio_com_ia()
203
  return [dados_gerados["fatos"], dados_gerados["provas_reu"], dados_gerados["provas_autor"], dados_gerados["testemunhas_reu"], dados_gerados["testemunhas_autor"], "Caso fictício gerado. Revise e salve."]
204
 
205
+ def acao_carregar_caso_padrao_ui(): # Mantido como antes
206
  gr.Info("Carregando caso padrão...")
207
  return [
208
  CASO_FATOS_COMPLETO_PREDEFINIDO,
 
213
  "Caso padrão carregado. Revise e salve."
214
  ]
215
 
216
+ # --- Funções de Geração de Respostas da IA (Corrigidas) ---
217
  def gerar_resposta_juiz_ia(estado_simulacao, acao_especifica=""):
218
  fase = estado_simulacao["fase_aij"]
219
  historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
220
+ # Using simple string concatenation for complex parts to avoid f-string issues
221
  prompt_base = f"**Persona:** Juiz(a) experiente em AIJ (Direito Esquecimento vs Liberdade Imprensa).\n**Fatos:** {estado_simulacao['caso_fatos'] or 'Não detalhado.'}\n{historico}**Fase Atual:** {fase}\n"
222
 
223
  tarefa_especifica_str = ""
 
242
  prompt_base = f"**Persona:** Advogado(a) do AUTOR em AIJ (Direito Esquecimento vs Liberdade Imprensa). Cliente busca esquecimento/reparação.\n**Réu:** Jornal.\n**Fatos:** {estado_simulacao['caso_fatos'] or 'Não detalhado.'}\n**Provas/Argumentos Autor:** {estado_simulacao['provas_autor_supostas_texto'] or 'Passagem tempo, desinteresse público, dano vida privada.'}\n{historico}**Fase Atual:** {fase}\n"
243
 
244
  tarefa_especifica_str = ""
245
+ fala_adv_reu_escaped = fala_adv_reu.replace('"', '\"') # Correctly escape for embedding
246
 
247
  if fase == FASE_ABERTURA_CONCILIACAO:
248
  tarefa_especifica_str = f"**Tarefa:** Juiz perguntou sobre conciliação. Apresente proposta ou declare desinteresse. Se Réu já falou (\"{fala_adv_reu_escaped}\"), responda."
249
  elif fase == FASE_TESTEMUNHAS_AUTOR_INICIO:
250
+ # ... (logic as before)
251
  if estado_simulacao["testemunhas_autor_supostas_defs"]:
252
  proxima_testemunha_idx = estado_simulacao["testemunha_autor_atual_idx"] + 1
253
  if proxima_testemunha_idx < len(estado_simulacao["testemunhas_autor_supostas_defs"]):
 
272
  testemunha_obj = estado_simulacao.get("testemunha_em_depoimento")
273
  if not testemunha_obj or testemunha_obj["parte"] != "AUTOR": return "Testemunha do Autor (IA): (Erro interno - Nenhuma testemunha do autor em depoimento)"
274
  historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
275
+ pergunta_feita_escaped = pergunta_feita.replace('"', '\"') # Correctly escape
276
  prompt_completo = f"**Persona:** Testemunha {testemunha_obj['nome']} (AUTOR).\n**Caso:** Direito Esquecimento vs Liberdade Imprensa.\n**Fatos:** {estado_simulacao['caso_fatos'] or 'Não detalhado.'}\n**Seus Pontos Chave:** {testemunha_obj['pontos_chave'] or 'Conhecimento geral sobre autor e impactos.'}\n{historico}**Pergunta Feita:** \"{pergunta_feita_escaped}\"\n**Tarefa:** Responda claro, conciso, baseado nos seus pontos. Se Adv. Réu, seja cauteloso(a).\n**Sua Resposta (Testemunha {testemunha_obj['nome']}):**"
277
  return chamar_gemini_api(prompt_completo, temperature=0.6, max_output_tokens=250)
278
 
279
  def analisar_atuacao_defesa_ia(estado_simulacao, ultima_fala_reu=""):
280
  historico_completo_dialogo = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"], max_turns=len(estado_simulacao["transcricao_logica"]))
281
+ ultima_fala_reu_escaped = ultima_fala_reu.replace('"', '\"') # Correctly escape
282
  prompt_analise = f"**Persona:** Professor(a) de Prática Jurídica experiente.\n**Tarefa:** Feedback construtivo para aluno (Adv. RÉU - Jornal) em AIJ (Direito Esquecimento vs Liberdade Imprensa).\n**Fatos:** {estado_simulacao['caso_fatos'] or 'Não detalhado.'}\n**Provas/Argumentos Réu:** {estado_simulacao['provas_reu_texto'] or 'Não detalhado.'}\n**Transcrição AIJ:** {historico_completo_dialogo}\n**Última Intervenção Réu:** \"{ultima_fala_reu_escaped}\"\n**Feedback Detalhado (Pontos Fortes, Melhorias, Sugestões, Fundamentação, Estratégia):**"
283
  return chamar_gemini_api(prompt_analise, temperature=0.65, max_output_tokens=1200)
284
 
285
+ def avaliar_argumentos_defesa_ia(fatos_caso, provas_reu_texto_arg, tipo_argumento, argumento_usuario):
286
  if not argumento_usuario.strip():
287
  return "Por favor, insira seus argumentos para avaliação."
288
 
289
  fatos_formatado = fatos_caso if fatos_caso else CASO_DESCRICAO_PREDEFINIDO
290
  provas_reu_formatado = provas_reu_texto_arg if provas_reu_texto_arg else PROVAS_REU_TEXTO_PREDEFINIDO
291
 
 
 
292
  contexto_caso_parts = [
293
  "Você está avaliando argumentos no contexto de um caso jurídico no Brasil sobre direito ao esquecimento vs. liberdade de imprensa.\n",
294
  "O usuário representa a defesa (jornal).\n",
 
296
  f"**Principais Argumentos/Provas da Defesa (Jornal):** {provas_reu_formatado}\n"
297
  ]
298
  contexto_caso = "".join(contexto_caso_parts)
299
+ argumento_usuario_escaped = argumento_usuario.replace('"', '\"') # Correctly escape
300
+ tipo_argumento_escaped = tipo_argumento.replace('"', '\"')
301
 
302
  prompt_parts = [
303
  contexto_caso,
304
+ "\n\n**Persona:** Você é um Juiz experiente em um tribunal brasileiro...\n", # Shortened for brevity, full persona as before
305
+ f"**Tarefa:** Avalie o seguinte argumento apresentado pelo advogado de defesa (jornal) para a peça/momento processual: \"{tipo_argumento_escaped}\".\n",
306
+ # ... (rest of the detailed prompt structure as before) ...
307
+ "Formato da Resposta: Utilize linguagem formal e jurídica...\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  f"**Argumento do Advogado de Defesa (Jornal):**\n\"{argumento_usuario_escaped}\"\n\n",
309
  "**Sua Avaliação:**\n"
310
  ]
311
  prompt = "".join(prompt_parts)
312
  return chamar_gemini_api(prompt, temperature=0.6, max_output_tokens=1000)
313
 
314
+ def gerar_resposta_testemunha_defesa_para_treino_ia(fatos_caso, nome_testemunha, pontos_chave_testemunha, historico_perguntas_respostas_tuples, pergunta_atual_adv_defesa): # Renamed parameter
315
  fatos_formatado = fatos_caso if fatos_caso else CASO_DESCRICAO_PREDEFINIDO
316
  contexto_caso_parts = [
317
+ "Você está simulando o depoimento de uma testemunha de DEFESA (Jornal)...\n", # Shortened for brevity
 
318
  f"**Fatos do Caso:** {fatos_formatado}\n"
319
  ]
320
  contexto_caso = "".join(contexto_caso_parts)
321
 
322
  historico_formatado_str = "\nDepoimento até agora:\n"
323
+ if historico_perguntas_respostas_tuples:
324
+ for p, r in historico_perguntas_respostas_tuples: # Expecting (question, answer) tuples
325
  p_escaped = p.replace('"', '\"')
326
  r_escaped = r.replace('"', '\"')
327
  historico_formatado_str += f"- Advogado Defesa: {p_escaped}\n- {nome_testemunha}: {r_escaped}\n"
328
  else:
329
  historico_formatado_str = "Este é o início do seu depoimento."
 
330
  pergunta_atual_escaped = pergunta_atual_adv_defesa.replace('"', '\"')
331
 
332
  prompt_parts = [
333
  contexto_caso,
334
  f"\n\n**Persona:** Você é {nome_testemunha}, testemunha arrolada pela DEFESA (Jornal).\n",
335
  f"**Seus Pontos Chave a Defender/Explicar:** {pontos_chave_testemunha}\n",
336
+ # ... (rest of the prompt as before) ...
 
337
  historico_formatado_str,
338
  f"\n\n**Pergunta do Advogado de Defesa (Jornal):** \"{pergunta_atual_escaped}\"\n\n",
339
  f"**Sua Resposta ({nome_testemunha}):**\n"
 
341
  prompt = "".join(prompt_parts)
342
  return chamar_gemini_api(prompt, temperature=0.5, max_output_tokens=300)
343
 
344
+ # --- Funções de Lógica da Simulação e UI (Adaptadas para type="messages") ---
345
  def adicionar_fala_transcricao(estado_simulacao, ator, fala):
346
+ estado_simulacao["transcricao_logica"].append((ator, fala))
347
+
348
+ # Adapt for type="messages" for chat_aij_output
349
+ if ator == "Advogado do Réu (Você)":
350
+ estado_simulacao["transcricao_chat"].append({"role": "user", "content": fala})
351
+ elif ator == "Sistema": # System messages can be styled differently if needed, or just use assistant
352
+ estado_simulacao["transcricao_chat"].append({"role": "assistant", "content": f"*{fala}*"}) # Italic for system
353
+ else: # Juiz, Adv. Autor, Testemunha IA
354
+ # Add actor's name to the content for clarity
355
+ estado_simulacao["transcricao_chat"].append({"role": "assistant", "content": f"**{ator}:**\n{fala}"})
356
  return estado_simulacao
357
 
358
+ def mostrar_botoes_corretos(fase_atual): # Mantido como antes, logic is fine
359
  vis = {
360
  "btn_responder_conciliacao": fase_atual == FASE_ABERTURA_CONCILIACAO,
361
  "btn_chamar_testemunha_reu": fase_atual == FASE_TESTEMUNHAS_REU_INICIO,
 
374
  ]
375
  return [gr.update(visible=vis.get(k, False)) for k in all_button_keys]
376
 
377
+ def configurar_e_iniciar_simulacao(estado_s, fatos, p_reu, p_autor, t_reu_str, t_autor_str): # Mantido como antes, logic is fine
378
  novo_estado = estado_inicial_simulacao()
379
  if not fatos or not p_reu or not p_autor:
380
  gr.Warning("Por favor, preencha todos os campos de configuração do caso ou carregue o caso padrão.")
381
  initial_botoes_vis = mostrar_botoes_corretos(novo_estado["fase_aij"])
 
382
  return [novo_estado, novo_estado["transcricao_chat"], "Erro: Configuração incompleta.", "Preencha a configuração.", gr.Dropdown(choices=[], value=None, interactive=True)] + initial_botoes_vis
383
 
384
  novo_estado["caso_fatos"], novo_estado["provas_reu_texto"], novo_estado["provas_autor_supostas_texto"] = fatos, p_reu, p_autor
385
+ def parse_testemunhas_local(t_str_local):
386
  defs = []
387
  if t_str_local and t_str_local.strip():
388
  for linha in t_str_local.strip().split('\n'):
 
411
  gr.Info("Simulação iniciada.")
412
  return [novo_estado, novo_estado["transcricao_chat"], novo_estado["feedback_para_usuario"], novo_estado["instrucao_para_usuario"], gr.Dropdown(choices=nomes_testemunhas_reu, value=None, interactive=True)] + botoes_vis
413
 
414
+ def lidar_com_fala_usuario(estado_s, fala_usuario_txt): # Mantido como antes, logic fine
415
+ # ... (toda a lógica de lidar_com_fala_usuario como na versão anterior corrigida)
416
+ # This function is quite long, ensure it's copied correctly from the previous version
417
+ # Key points: deepcopy estado_s, determine ator_usuario, add to transcricao if fala_usuario_txt
418
+ # Then, all the conditional logic for different phases.
419
+
420
  # Allow empty fala_usuario_txt if a button implies an action phase
 
421
  if not fala_usuario_txt and estado_s["fase_aij"] not in [
422
+ FASE_TESTEMUNHAS_REU_INICIO,
 
 
423
  ]:
424
+ is_text_needed_phase = True
425
+ # Check phases where text input IS primary for the action
426
+ if estado_s["fase_aij"] in [FASE_ABERTURA_CONCILIACAO, FASE_ALEGACOES_FINAIS_REU, FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU, FASE_TESTEMUNHAS_REU_PERGUNTAS_REU, FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR] :
427
+ # For these, if user provides no text, it might be an error unless a specific button implies action without text
428
+ if not fala_usuario_txt : # and not a specific button click that implies action without text
429
+ estado_s["instrucao_para_usuario"] = "Por favor, digite sua fala."
 
 
 
 
 
 
 
 
 
 
 
430
  return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"], gr.Textbox(value="")] + mostrar_botoes_corretos(estado_s["fase_aij"])
431
+ # Else, if not a text-needed phase and text is empty, it might be a pure button click (like "Juiz Avançar" handled elsewhere)
432
 
433
  estado_s = copy.deepcopy(estado_s)
434
  ator_usuario = "Advogado do Réu (Você)"
 
466
  elif estado_s["testemunhas_reu_defs"]:
467
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
468
  estado_s["instrucao_para_usuario"] = "Selecione sua testemunha para chamar."
469
+ else: # No witnesses
470
  estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
471
  estado_s["instrucao_para_usuario"] = "Aguarde Juiz iniciar Alegações Finais."
472
+ fala_juiz_aleg = gerar_resposta_juiz_ia(estado_s) # Juiz calls for alegacoes
473
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_aleg)
474
+ fala_aleg_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv Autor makes alegacoes
475
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_aleg_autor)
476
+ estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_REU # Transition to Reu's turn
477
  estado_s["instrucao_para_usuario"] = "Apresente suas Alegações Finais."
478
+ else: # Conciliation might still be open
479
  estado_s["instrucao_para_usuario"] = "Responda ao Juiz ou Adv. Autor sobre conciliação."
480
 
481
  elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU:
482
+ if not fala_usuario_txt: # User might have clicked a button to advance (handled by acao_botao_juiz_avancar)
483
  estado_s["instrucao_para_usuario"] = "Faça uma pergunta à testemunha do Autor ou clique em 'Juiz (IA): Avançar Fase' para encerrar."
484
  else:
485
  fala_test_autor = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_usuario_txt)
 
487
  estado_s["instrucao_para_usuario"] = f"Faça outra pergunta à testemunha {estado_s['testemunha_em_depoimento']['nome']} (Autor) ou clique 'Juiz Avançar'."
488
 
489
  elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_PERGUNTAS_REU:
490
+ if not fala_usuario_txt :
491
  estado_s["instrucao_para_usuario"] = f"Por favor, faça uma pergunta à sua testemunha {estado_s['testemunha_em_depoimento']['nome']}."
492
  else:
493
+ # Adv. Réu (usuário) fez uma pergunta à sua testemunha (fala_usuario_txt).
494
+ # A resposta da testemunha do réu será simulada pelo Adv. Autor (IA) fazendo perguntas a ela,
495
+ # e o usuário respondendo como se fosse sua testemunha.
496
+ # So, after Adv. Réu asks, Adv. Autor (IA) gets to cross-examine.
497
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR
498
+ fala_adv_autor_ia = gerar_resposta_advogado_autor_ia(estado_s)
499
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor_ia)
500
  estado_s["instrucao_para_usuario"] = f"Como testemunha {estado_s['testemunha_em_depoimento']['nome']}, responda à pergunta do Adv. Autor."
501
 
502
+ elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR:
503
  if not fala_usuario_txt:
504
  estado_s["instrucao_para_usuario"] = f"Como testemunha {estado_s['testemunha_em_depoimento']['nome']}, por favor, responda à pergunta do Adv. Autor."
505
  else:
506
+ # fala_usuario_txt is the response of Reu's witness (typed by user) to Adv. Autor's question.
507
+ fala_adv_autor_ia = gerar_resposta_advogado_autor_ia(estado_s, fala_adv_reu=fala_usuario_txt)
 
508
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor_ia)
509
  if ("pergunta" in fala_adv_autor_ia.lower() or "?" in fala_adv_autor_ia) and not any(k in fala_adv_autor_ia.lower() for k in ["não tenho mais perguntas", "encerro", "nada mais"]):
510
  estado_s["instrucao_para_usuario"] = f"Como testemunha {estado_s['testemunha_em_depoimento']['nome']}, responda à nova pergunta do Adv. Autor."
511
+ else:
512
  fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica=f"Adv. Autor encerrou inquirição da testemunha {estado_s['testemunha_em_depoimento']['nome']}. Adv. Réu pode fazer mais perguntas ou dispensar.")
513
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
514
+ estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_PERGUNTAS_REU
515
  estado_s["instrucao_para_usuario"] = f"Faça mais perguntas à sua testemunha {estado_s['testemunha_em_depoimento']['nome']}, ou clique 'Juiz Avançar' para dispensá-la."
516
 
517
  elif estado_s["fase_aij"] == FASE_ALEGACOES_FINAIS_REU:
 
525
 
526
  estado_s["feedback_para_usuario"] = analisar_atuacao_defesa_ia(estado_s, ultima_fala_reu=fala_usuario_txt if ator_usuario == "Advogado do Réu (Você)" else "")
527
  gr.Info("Respostas da IA geradas.")
528
+ return [estado_s, estado_simulacao["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"], gr.Textbox(value="")] + mostrar_botoes_corretos(estado_s["fase_aij"])
529
 
530
+ def acao_botao_juiz_avancar(estado_s): # Mantido como antes, logic fine
531
+ # ... (toda a lógica de acao_botao_juiz_avancar como na versão anterior corrigida)
532
  estado_s = copy.deepcopy(estado_s)
533
  fase_atual = estado_s["fase_aij"]
534
  gr.Info(f"Avançando fase a partir de: {fase_atual}. Aguarde IA...")
535
 
536
  if fase_atual == FASE_ABERTURA_CONCILIACAO:
537
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", "Considerando frustrada a tentativa de conciliação ou por avanço solicitado, passaremos à instrução.")
 
538
  if estado_s["testemunhas_autor_supostas_defs"]:
539
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_AUTOR_INICIO
540
  fala_juiz = gerar_resposta_juiz_ia(estado_s)
 
551
  estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {t_info['nome']} (Autor - IA)", fala_test_autor)
552
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU
553
  estado_s["instrucao_para_usuario"] = f"Contradite ou faça perguntas à testemunha {t_info['nome']} (Autor)."
554
+ else:
555
  if estado_s["testemunhas_reu_defs"]:
556
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
557
  estado_s["instrucao_para_usuario"] = "Selecione sua testemunha para chamar."
 
558
  fala_juiz_trans = gerar_resposta_juiz_ia(estado_s)
559
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_trans)
560
 
561
+ else: estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
562
  elif estado_s["testemunhas_reu_defs"]:
563
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
564
  fala_juiz = gerar_resposta_juiz_ia(estado_s)
565
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
566
  estado_s["instrucao_para_usuario"] = "Selecione sua testemunha para chamar."
567
+ else:
568
  estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
569
+ fala_juiz = gerar_resposta_juiz_ia(estado_s)
570
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
571
+ fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s)
572
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
573
  estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_REU
574
  estado_s["instrucao_para_usuario"] = "Apresente suas Alegações Finais."
575
 
576
+ elif fase_atual == FASE_TESTEMUNHAS_AUTOR_INICIO:
577
  fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Verificar se há mais testemunhas do Autor ou encerrar esta fase.")
578
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
579
  fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s)
580
  estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
 
581
  if "Não tenho mais testemunhas" in fala_adv_autor or "Não arrolei testemunhas" in fala_adv_autor or estado_s["testemunha_autor_atual_idx"] +1 >= len(estado_s["testemunhas_autor_supostas_defs"]):
582
  estado_s["testemunha_em_depoimento"] = None
583
  if estado_s["testemunhas_reu_defs"]:
 
604
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU
605
  estado_s["instrucao_para_usuario"] = f"Contradite ou faça perguntas à testemunha {t_info['nome']} (Autor)."
606
 
 
607
  elif fase_atual == FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU:
608
  estado_s["testemunha_em_depoimento"] = None
609
  if estado_s["testemunha_autor_atual_idx"] + 1 < len(estado_s["testemunhas_autor_supostas_defs"]):
 
660
  fala_juiz_dispensa = gerar_resposta_juiz_ia(estado_s, acao_especifica=f"Dispensar {nome_test_dispensada}. Verificar se Adv. Réu tem mais testemunhas ou se encerrou sua instrução probatória.")
661
  estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_dispensa)
662
 
 
663
  more_reu_witnesses = estado_s["testemunha_reu_atual_idx"] + 1 < len(estado_s["testemunhas_reu_defs"])
664
  juiz_wants_to_continue_with_reu_witnesses = not any(k in fala_juiz_dispensa.lower() for k in ["alegações", "encerrada instrução", "sentença"])
665
 
 
666
  if more_reu_witnesses and juiz_wants_to_continue_with_reu_witnesses:
667
  estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
668
  estado_s["instrucao_para_usuario"] = "Selecione sua próxima testemunha para chamar ou clique 'Juiz Avançar' novamente para encerrar oitiva das suas testemunhas."
 
690
  botoes_vis = mostrar_botoes_corretos(estado_s["fase_aij"])
691
  return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + botoes_vis
692
 
693
+ def chamar_testemunha_reu_selecionada(estado_s, nome_testemunha_selecionada): # Mantido como antes, logic fine
694
+ # ... (toda a lógica de chamar_testemunha_reu_selecionada como na versão anterior corrigida)
695
  estado_s = copy.deepcopy(estado_s)
696
  if not nome_testemunha_selecionada:
697
  estado_s["instrucao_para_usuario"] = "Nenhuma testemunha selecionada. Por favor, selecione uma testemunha da lista."
 
719
  botoes_vis = mostrar_botoes_corretos(estado_s["fase_aij"])
720
  return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + botoes_vis
721
 
722
+ # Global for training chat history, adapted for type="messages"
723
+ _historico_treino_testemunha_atual_messages = []
724
+ def gerar_dialogo_testemunha_defesa_para_treino_ui(fatos_caso_atual, testemunhas_reu_defs_atual_str, testemunha_selecionada_nome, pergunta_adv_defesa_treino):
725
+ global _historico_treino_testemunha_atual_messages
726
  if not GEMINI_API_KEY:
727
+ _historico_treino_testemunha_atual_messages.append( {"role": "assistant", "content": "ERRO: API Key não configurada."} )
728
+ return _historico_treino_testemunha_atual_messages, ""
729
 
730
  if not testemunha_selecionada_nome:
731
+ _historico_treino_testemunha_atual_messages.append( {"role": "assistant", "content": "Por favor, selecione uma testemunha."} )
732
+ return _historico_treino_testemunha_atual_messages, ""
733
+ if not pergunta_adv_defesa_treino:
734
+ _historico_treino_testemunha_atual_messages.append( {"role": "assistant", "content": "Por favor, digite sua pergunta para a testemunha."} )
735
+ return _historico_treino_testemunha_atual_messages, ""
736
 
737
  testemunhas_reu_defs_usar = []
738
  if testemunhas_reu_defs_atual_str:
 
752
  testemunhas_reu_defs_usar = TESTEMUNHAS_REU_PREDEFINIDAS
753
 
754
  testemunha_obj = next((t for t in testemunhas_reu_defs_usar if t["nome"] == testemunha_selecionada_nome), None)
755
+ if not testemunha_obj: # Fallback to predefined if not found in dynamic list
756
  testemunha_obj = next((t for t in TESTEMUNHAS_REU_PREDEFINIDAS if t["nome"] == testemunha_selecionada_nome), None)
757
  if not testemunha_obj:
758
+ _historico_treino_testemunha_atual_messages.append( {"role": "assistant", "content": f"Testemunha '{testemunha_selecionada_nome}' não encontrada."} )
759
+ return _historico_treino_testemunha_atual_messages, ""
760
 
761
  # Smart reset of history
762
+ reset_history = True
763
+ if _historico_treino_testemunha_atual_messages:
764
+ first_message = _historico_treino_testemunha_atual_messages[0]
765
+ if first_message.get("role") == "assistant" and first_message.get("content", "").startswith(f"Iniciando inquirição de **{testemunha_obj['nome']}**"):
766
+ reset_history = False
767
+
768
+ if reset_history:
769
+ _historico_treino_testemunha_atual_messages = []
770
+ _historico_treino_testemunha_atual_messages.append( {"role": "assistant", "content": f"Iniciando inquirição de **{testemunha_obj['nome']}**. Pontos chave: {testemunha_obj['pontos_chave']}"} )
771
 
772
+ _historico_treino_testemunha_atual_messages.append({"role": "user", "content": pergunta_adv_defesa_treino})
773
  gr.Info(f"Gerando resposta da testemunha {testemunha_obj['nome']}... Aguarde.")
774
+
775
+ # Prepare history for LLM (list of (question, answer) tuples from user/assistant messages)
776
+ llm_prompt_history_tuples = []
777
+ # Iterate backwards to find the last Q/A pairs, or be simpler if the structure is always Q then A
778
+ temp_q = None
779
+ for msg in _historico_treino_testemunha_atual_messages: # Iterate through messages format
780
+ if msg["role"] == "user":
781
+ temp_q = msg["content"]
782
+ elif msg["role"] == "assistant" and temp_q is not None:
783
+ if not msg["content"].startswith("Iniciando inquirição"): # Exclude system intro
784
+ llm_prompt_history_tuples.append((temp_q, msg["content"]))
785
+ temp_q = None # Reset for next pair
786
+
787
 
788
  resposta_testemunha = gerar_resposta_testemunha_defesa_para_treino_ia(
789
  fatos_caso_atual if fatos_caso_atual else CASO_FATOS_COMPLETO_PREDEFINIDO,
790
  testemunha_obj['nome'],
791
  testemunha_obj['pontos_chave'],
792
+ llm_prompt_history_tuples,
793
+ pergunta_adv_defesa_treino
794
  )
795
+ _historico_treino_testemunha_atual_messages.append( {"role": "assistant", "content": resposta_testemunha} )
796
  gr.Info("Resposta da testemunha gerada.")
797
+ return _historico_treino_testemunha_atual_messages, ""
798
 
799
+ def limpar_chat_treino_tab5():
800
+ global _historico_treino_testemunha_atual_messages
801
+ _historico_treino_testemunha_atual_messages = []
802
+ return [], ""
803
 
804
  # --- Interface Gráfica (Gradio UI) ---
805
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"), title="Simulador AIJ Interativo") as demo:
806
  gr.Markdown("# ⚖️ Simulador Interativo de Audiência de Instrução e Julgamento (AIJ)")
807
+ # ... (rest of the UI as before, with Chatbot `type` and no `bubble_full_width`)
808
  gr.Markdown("Tema: **Direito ao Esquecimento vs. Liberdade de Imprensa**. Você assume o papel de **Advogado(a) do Réu (Jornal)**.")
809
  if not GEMINI_API_KEY:
810
+ gr.Warning("API Key do Gemini (GEMINI_API_KEY) não encontrada! O aplicativo pode não funcionar corretamente...")
811
 
812
  sim_state = gr.State(value=estado_inicial_simulacao())
813
 
814
  with gr.Tabs() as abas_principais:
815
  with gr.TabItem("1. Configuração do Caso", id=0):
816
  gr.Markdown("## Detalhes do Caso para Simulação")
817
+ with gr.Row():
818
+ btn_gerar_caso_ia = gr.Button("✨ Gerar Novo Caso com IA", icon="🧠", scale=1)
819
+ btn_carregar_caso_padrao = gr.Button("📄 Carregar Caso Padrão (Esquecimento)", icon="📜", scale=1)
820
  with gr.Row():
821
  with gr.Column(scale=2):
822
  fatos_input = gr.Textbox(lines=7, label="Resumo dos Fatos, Partes e Título:", placeholder="Descreva o caso ou gere/carregue.")
 
836
  with gr.TabItem("2. Audiência Interativa", id=1):
837
  gr.Markdown("## Andamento da Audiência Simulada")
838
  instrucao_usuario_output = gr.Markdown("Instrução: Configure o caso na aba 'Configuração' e clique em 'Salvar e Iniciar' para começar.")
839
+ chat_aij_output = gr.Chatbot(
840
+ label="Transcrição da Audiência",
841
+ height=500,
842
+ show_copy_button=True,
843
+ avatar_images=(None, "https://img.icons8.com/fluency/96/robot-2.png"),
844
+ type="messages" # Corrected
845
+ )
846
  fala_usuario_input = gr.Textbox(show_label=False, placeholder="Digite sua fala aqui ou use os botões de ação abaixo...", scale=4, lines=3)
847
 
848
  btn_responder_conciliacao = gr.Button("Responder à Conciliação", visible=False)
 
855
  btn_juiz_avancar_fase_action = gr.Button("⚖️ Juiz (IA): Concluir Etapa / Avançar Fase", visible=False, variant="secondary")
856
 
857
  with gr.Row():
858
+ btn_enviar_fala_usuario = gr.Button("🎤 Enviar Fala / Ação", variant="stop", scale=3) # Increased scale a bit
859
+ btn_juiz_avancar_fase_action_display = btn_juiz_avancar_fase_action # Display it in the row, scale default
 
860
 
861
  with gr.Accordion("Ações Contextuais do Advogado do Réu (Você)", open=True):
862
  with gr.Row():
 
869
  btn_adv_reu_responde_pela_sua_testemunha_action_display = btn_adv_reu_responde_pela_sua_testemunha_action
870
  btn_apresentar_alegacoes_finais_reu_action_display = btn_apresentar_alegacoes_finais_reu_action
871
 
872
+ lista_botoes_feedback = [
873
  btn_responder_conciliacao, btn_chamar_testemunha_reu_action, dropdown_testemunhas_reu_select,
874
  btn_perguntar_testemunha_autor_action, btn_adv_reu_pergunta_sua_testemunha_action,
875
  btn_adv_reu_responde_pela_sua_testemunha_action, btn_apresentar_alegacoes_finais_reu_action,
 
878
 
879
  with gr.TabItem("3. Feedback da Atuação (Professor IA)", id=2):
880
  gr.Markdown("## 💡 Análise da Sua Atuação na Audiência Interativa")
 
881
  feedback_output = gr.Textbox(lines=20, label="Feedback Detalhado:", interactive=False, show_copy_button=True)
882
 
883
 
884
  with gr.TabItem("4. Treinamento de Argumentação (Defesa)", id=3):
885
  gr.Markdown("## 🗣️ Pratique e Avalie Seus Argumentos (Advogado de Defesa)")
 
886
  fatos_caso_treino_arg_display_tab4 = gr.Textbox(label="Fatos do Caso (da Configuração):", value=CASO_FATOS_COMPLETO_PREDEFINIDO, lines=5, interactive=False)
887
  provas_reu_treino_arg_display_tab4 = gr.Textbox(label="Provas do Réu (da Configuração):", value=PROVAS_REU_TEXTO_PREDEFINIDO, lines=5, interactive=False)
888
  tipo_argumento_treino_tab4 = gr.Radio(
 
904
 
905
  with gr.TabItem("5. Preparar Testemunhas (Defesa)", id=4):
906
  gr.Markdown("## 🎙️ Simule a Inquirição das Suas Testemunhas (Defesa)")
 
907
  fatos_caso_treino_test_display_tab5 = gr.Textbox(label="Fatos do Caso (da Configuração):", value=CASO_FATOS_COMPLETO_PREDEFINIDO, lines=5, interactive=False)
908
  testemunhas_reu_config_treino_display_tab5 = gr.Textbox(label="Definição das Testemunhas do Réu (da Configuração):", value=TESTEMUNHAS_REU_TEXTO_PREDEFINIDO, lines=3, interactive=False)
909
 
 
922
  return gr.Dropdown(choices=nomes if nomes else [t['nome'] for t in TESTEMUNHAS_REU_PREDEFINIDAS], value=nomes[0] if nomes else None, interactive=True)
923
  testemunhas_reu_input.change(update_dropdown_treino_choices_tab5, inputs=testemunhas_reu_input, outputs=dropdown_testemunhas_reu_treino_tab5)
924
 
925
+ chat_treino_testemunha_tab5 = gr.Chatbot(
926
+ label="Simulação de Depoimento (Treino)",
927
+ height=300,
928
+ show_copy_button=True,
929
+ avatar_images=(None, "https://img.icons8.com/officel/80/person-male.png"),
930
+ type="messages" # Corrected
931
+ )
932
  pergunta_testemunha_treino_input_tab5 = gr.Textbox(label="Sua Pergunta para a Testemunha:", placeholder="Ex: 'Senhor Silva, poderia descrever o procedimento editorial?'")
933
  btn_perguntar_testemunha_treino_tab5 = gr.Button("💬 Perguntar à Testemunha (IA)", variant="primary")
934
  btn_limpar_chat_treino_testemunha_tab5 = gr.Button("🗑️ Limpar Chat de Treino")
935
+
 
 
 
 
936
  btn_limpar_chat_treino_testemunha_tab5.click(limpar_chat_treino_tab5, outputs=[chat_treino_testemunha_tab5, pergunta_testemunha_treino_input_tab5])
 
937
  btn_perguntar_testemunha_treino_tab5.click(
938
  gerar_dialogo_testemunha_defesa_para_treino_ui,
939
  inputs=[fatos_caso_treino_test_display_tab5, testemunhas_reu_config_treino_display_tab5, dropdown_testemunhas_reu_treino_tab5, pergunta_testemunha_treino_input_tab5],
 
941
  )
942
 
943
  with gr.TabItem("ℹ️ Ajuda / Sobre o Caso Padrão", id=5):
944
+ # ... (Content of Help Tab as before) ...
945
  gr.Markdown("## Sobre o Caso Padrão: Direito ao Esquecimento vs. Liberdade de Imprensa")
 
946
  gr.Markdown(f"**Título:** {CASO_TITULO_PREDEFINIDO}")
947
+ md_partes = CASO_PARTES_PREDEFINIDO.replace("\n", "\n\n")
948
  gr.Markdown(f"**Partes:**\n{md_partes}")
949
+ gr.Markdown(f"**Resumo do Caso:**\n{CASO_DESCRICAO_PREDEFINIDO}")
950
  with gr.Accordion("Argumentos Principais do Autor (Caso Padrão)", open=False):
951
  gr.Markdown("\n".join([f"- {arg}" for arg in ARGUMENTOS_AUTOR_PREDEFINIDOS]))
952
  with gr.Accordion("Argumentos Principais do Réu/Jornal (Caso Padrão)", open=False):
 
955
  gr.Markdown("\n".join([f"- **{t['nome']}**: {t['pontos_chave']}" for t in TESTEMUNHAS_REU_PREDEFINIDAS]))
956
 
957
  gr.Markdown("### Legislação e Precedentes Relevantes (Geral)")
 
958
  with gr.Row():
959
  with gr.Column():
960
  gr.Markdown("**Potencialmente Favoráveis ao Réu (Jornal):**")
 
963
  gr.Markdown("**Potencialmente Favoráveis ao Autor:**")
964
  gr.Markdown("\n".join([f"- {lei}" for lei in LEGISLACAO_PRECEDENTES_PREDEFINIDO["favoraveis_ao_autor"]]))
965
  gr.Markdown("""
966
+ ## Como utilizar este simulador:
967
+ ... (rest of help text) ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
968
  """)
969
 
 
970
  # --- Event Handlers ---
 
 
 
 
 
 
 
971
  outputs_config_list = [
972
  sim_state, chat_aij_output, feedback_output, instrucao_usuario_output,
973
+ dropdown_testemunhas_reu_select
974
  ] + lista_botoes_feedback
975
 
 
976
  btn_config_iniciar.click(
977
  configurar_e_iniciar_simulacao,
978
  inputs=[sim_state, fatos_input, provas_reu_input, provas_autor_input, testemunhas_reu_input, testemunhas_autor_supostas_input],
979
+ outputs=outputs_config_list
980
  ).then(lambda: gr.Textbox(value=""), outputs=[fala_usuario_input]
981
  ).then(lambda: gr.Tabs(selected=1), inputs=None, outputs=[abas_principais])
982
 
 
 
983
  outputs_fala_usuario_and_actions_list = [
984
  sim_state, chat_aij_output, feedback_output, instrucao_usuario_output,
985
+ fala_usuario_input
986
  ] + lista_botoes_feedback
987
 
 
988
  btn_enviar_fala_usuario.click(lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list)
989
  fala_usuario_input.submit(lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list)
990
 
 
992
  btn_chamar_testemunha_reu_action.click(chamar_testemunha_reu_selecionada, inputs=[sim_state, dropdown_testemunhas_reu_select], outputs=outputs_fala_usuario_and_actions_list).then(lambda: gr.Textbox(value=""), outputs=[fala_usuario_input])
993
 
994
  def create_button_click_handler_wrapper(info_message):
 
995
  def actual_handler_for_button(current_sim_state, current_fala_usuario_input_text):
996
+ gr.Info(info_message)
 
997
  return lidar_com_fala_usuario(current_sim_state, current_fala_usuario_input_text)
998
  return actual_handler_for_button
999
 
 
1001
  create_button_click_handler_wrapper("Conciliação: Digite sua resposta no campo de fala e clique 'Enviar Fala / Ação'."),
1002
  inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list
1003
  )
1004
+ # ... (other similar button clicks)
1005
  btn_perguntar_testemunha_autor_action.click(
1006
  create_button_click_handler_wrapper("Perg. Test. Autor: Digite sua pergunta no campo de fala e clique 'Enviar Fala / Ação'."),
1007
  inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list
 
1019
  inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario_and_actions_list
1020
  )
1021
 
1022
+
1023
+ outputs_on_load_list = [
1024
+ sim_state, chat_aij_output, feedback_output, instrucao_usuario_output,
1025
+ dropdown_testemunhas_reu_select
1026
+ ] + lista_botoes_feedback
1027
+
1028
+ def setup_initial_ui_state_load_wrapper(s_val_load):
1029
  initial_fase = s_val_load["fase_aij"]
1030
  dropdown_choices_load = [t["nome"] for t in s_val_load.get("testemunhas_reu_defs", [])] if s_val_load.get("testemunhas_reu_defs") else []
1031
  updates_for_buttons_load = mostrar_botoes_corretos(initial_fase)
1032
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1033
  final_return_list = [
1034
  s_val_load,
1035
+ s_val_load["transcricao_chat"],
1036
  s_val_load["feedback_para_usuario"],
1037
  s_val_load["instrucao_para_usuario"],
1038
+ gr.Dropdown(choices=dropdown_choices_load, value=None, interactive=True)
1039
  ]
1040
+ final_return_list.extend(updates_for_buttons_load)
 
 
 
 
 
 
 
 
1041
  return tuple(final_return_list)
1042
 
 
 
 
 
 
 
1043
  demo.load(
1044
  setup_initial_ui_state_load_wrapper,
1045
  inputs=[sim_state],
1046
  outputs=outputs_on_load_list
1047
  )
1048
 
 
1049
  if __name__ == "__main__":
1050
  if not GEMINI_API_KEY:
1051
  print("#####################################################################")
1052
+ print("ATENÇÃO: GEMINI_API_KEY não configurada...")
1053
+ print("#####################################################################")
1054
  demo.queue(max_size=20).launch(debug=True)