Spaces:
Build error
Build error
Update app.py
#1
by GabrielGD - opened
app.py
CHANGED
|
@@ -4,16 +4,17 @@ import json
|
|
| 4 |
import os
|
| 5 |
import copy
|
| 6 |
|
|
|
|
| 7 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
| 8 |
if not GEMINI_API_KEY:
|
| 9 |
print("ALERTA: GEMINI_API_KEY não encontrada como Secret no Hugging Face Space. O app não funcionará.")
|
| 10 |
# Para teste local, descomente e cole sua chave, mas NÃO FAÇA COMMIT DISSO COM A CHAVE.
|
| 11 |
# GEMINI_API_KEY = "SUA_CHAVE_AQUI_PARA_TESTE_LOCAL_APENAS"
|
| 12 |
|
| 13 |
-
|
| 14 |
-
MODEL_NAME = "gemini-1.5-flash-latest"
|
| 15 |
API_URL_BASE = f"https://generativelanguage.googleapis.com/v1beta/models/{MODEL_NAME}:generateContent"
|
| 16 |
|
|
|
|
| 17 |
FASE_INICIAL_CONFIG = "CONFIGURACAO"
|
| 18 |
FASE_ABERTURA_CONCILIACAO = "ABERTURA_E_CONCILIACAO"
|
| 19 |
FASE_TESTEMUNHAS_AUTOR_INICIO = "TESTEMUNHAS_AUTOR_INICIO"
|
|
@@ -27,6 +28,71 @@ FASE_ALEGACOES_FINAIS_REU = "ALEGACOES_FINAIS_REU"
|
|
| 27 |
FASE_ANALISE_FINAL_PROFESSOR = "ANALISE_FINAL_PROFESSOR"
|
| 28 |
FASE_CONCLUIDA = "AIJ_CONCLUIDA"
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
def estado_inicial_simulacao():
|
| 31 |
return {
|
| 32 |
"fase_aij": FASE_INICIAL_CONFIG, "caso_fatos": "", "provas_reu_texto": "",
|
|
@@ -35,7 +101,7 @@ def estado_inicial_simulacao():
|
|
| 35 |
"testemunha_reu_atual_idx": -1, "testemunha_em_depoimento": None,
|
| 36 |
"transcricao_chat": [], "transcricao_logica": [],
|
| 37 |
"feedback_para_usuario": "Aguardando início da simulação.",
|
| 38 |
-
"instrucao_para_usuario": "Configure os detalhes do caso na aba 'Configuração'."
|
| 39 |
}
|
| 40 |
|
| 41 |
def chamar_gemini_api(prompt_text, temperature=0.7, max_output_tokens=800):
|
|
@@ -55,7 +121,7 @@ def chamar_gemini_api(prompt_text, temperature=0.7, max_output_tokens=800):
|
|
| 55 |
]
|
| 56 |
}
|
| 57 |
try:
|
| 58 |
-
response = requests.post(api_url_com_chave, headers=headers, data=json.dumps(data), timeout=
|
| 59 |
response.raise_for_status()
|
| 60 |
response_json = response.json()
|
| 61 |
if response_json.get("candidates") and response_json["candidates"][0].get("content"):
|
|
@@ -63,6 +129,8 @@ def chamar_gemini_api(prompt_text, temperature=0.7, max_output_tokens=800):
|
|
| 63 |
elif response_json.get("promptFeedback") and response_json["promptFeedback"].get("blockReason"):
|
| 64 |
return f"ERRO_API: Conteúdo bloqueado. Razão: {response_json['promptFeedback']['blockReason']}"
|
| 65 |
return "ERRO_API: Resposta inesperada da API."
|
|
|
|
|
|
|
| 66 |
except requests.exceptions.RequestException as e:
|
| 67 |
error_msg = f"ERRO_CONEXAO: {e}"
|
| 68 |
if e.response is not None:
|
|
@@ -80,7 +148,9 @@ def formatar_historico_para_prompt(transcricao_logica, max_turns=15):
|
|
| 80 |
historico_formatado += f"- {ator}: {fala}\n"
|
| 81 |
return historico_formatado
|
| 82 |
|
|
|
|
| 83 |
def gerar_caso_ficticio_com_ia():
|
|
|
|
| 84 |
prompt_geracao_caso = """
|
| 85 |
**Instrução de Persona:** Você é um roteirista jurídico criativo e experiente, especializado em criar casos simulados realistas para treinamento de advogados.
|
| 86 |
**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".
|
|
@@ -102,12 +172,13 @@ def gerar_caso_ficticio_com_ia():
|
|
| 102 |
`## Testemunhas Hipotéticas da Parte RÉ`
|
| 103 |
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.
|
| 104 |
"""
|
| 105 |
-
texto_caso_completo = chamar_gemini_api(prompt_geracao_caso, temperature=0.75, max_output_tokens=
|
| 106 |
if "ERRO_" in texto_caso_completo:
|
| 107 |
return {"fatos": f"Falha ao gerar caso com IA: {texto_caso_completo}", "provas_autor": "", "provas_reu": "", "testemunhas_autor": "", "testemunhas_reu": ""}
|
| 108 |
return parse_caso_gerado(texto_caso_completo)
|
| 109 |
|
| 110 |
def parse_caso_gerado(texto_completo_caso):
|
|
|
|
| 111 |
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"}
|
| 112 |
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É"}
|
| 113 |
fatos_prefix = ""
|
|
@@ -135,9 +206,16 @@ def parse_caso_gerado(texto_completo_caso):
|
|
| 135 |
dados_caso[chave_atual] = fatos_prefix + conteudo_secao if chave_atual == "fatos" and fatos_prefix else conteudo_secao
|
| 136 |
current_pos = fim_conteudo
|
| 137 |
for key_testemunha in ["testemunhas_autor", "testemunhas_reu"]:
|
| 138 |
-
if "Falha no parsing" not in dados_caso[key_testemunha]:
|
| 139 |
linhas = dados_caso[key_testemunha].split('\n')
|
| 140 |
-
linhas_formatadas = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
dados_caso[key_testemunha] = "\n".join(linhas_formatadas)
|
| 142 |
return dados_caso
|
| 143 |
|
|
@@ -146,7 +224,19 @@ def acao_gerar_caso_ficticio_ui():
|
|
| 146 |
dados_gerados = gerar_caso_ficticio_com_ia()
|
| 147 |
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."]
|
| 148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
def gerar_resposta_juiz_ia(estado_simulacao, acao_especifica=""):
|
|
|
|
| 150 |
fase = estado_simulacao["fase_aij"]
|
| 151 |
historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
|
| 152 |
prompt = 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"
|
|
@@ -158,9 +248,10 @@ def gerar_resposta_juiz_ia(estado_simulacao, acao_especifica=""):
|
|
| 158 |
elif fase == FASE_ANALISE_FINAL_PROFESSOR: prompt += "**Tarefa:** Declare audiência encerrada para julgamento (simulado)."
|
| 159 |
else: prompt += f"**Tarefa:** Conduza a audiência. Ação específica: {acao_especifica or 'Nenhuma'}. Mantenha ordem e fluxo."
|
| 160 |
prompt += "\n**Sua Fala (Juiz):**"
|
| 161 |
-
return chamar_gemini_api(prompt, temperature=0.6, max_output_tokens=
|
| 162 |
|
| 163 |
def gerar_resposta_advogado_autor_ia(estado_simulacao, fala_adv_reu=""):
|
|
|
|
| 164 |
fase = estado_simulacao["fase_aij"]
|
| 165 |
historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
|
| 166 |
prompt = 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"
|
|
@@ -181,21 +272,91 @@ def gerar_resposta_advogado_autor_ia(estado_simulacao, fala_adv_reu=""):
|
|
| 181 |
elif fase == FASE_ALEGACOES_FINAIS_AUTOR: prompt += "**Tarefa:** Juiz concedeu palavra para alegações finais. Apresente resumo persuasivo e reitere pedidos."
|
| 182 |
else: prompt += f"**Contexto:** Adv. Réu (Usuário) disse: \"{fala_adv_reu}\"\n**Tarefa:** Responda estrategicamente."
|
| 183 |
prompt += "\n**Sua Resposta (Advogado Autor):**"
|
| 184 |
-
return chamar_gemini_api(prompt, temperature=0.75, max_output_tokens=
|
| 185 |
|
| 186 |
def gerar_resposta_testemunha_autor_ia(estado_simulacao, pergunta_feita):
|
|
|
|
| 187 |
testemunha_obj = estado_simulacao.get("testemunha_em_depoimento")
|
| 188 |
if not testemunha_obj or testemunha_obj["parte"] != "AUTOR": return "Testemunha do Autor (IA): (Erro interno - Nenhuma testemunha do autor em depoimento)"
|
| 189 |
historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
|
| 190 |
prompt = 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}\"\n**Tarefa:** Responda claro, conciso, baseado nos seus pontos. Se Adv. Réu, seja cauteloso(a).\n**Sua Resposta (Testemunha {testemunha_obj['nome']}):**"
|
| 191 |
-
return chamar_gemini_api(prompt, temperature=0.6, max_output_tokens=
|
| 192 |
|
| 193 |
def analisar_atuacao_defesa_ia(estado_simulacao, ultima_fala_reu=""):
|
|
|
|
| 194 |
historico_completo_dialogo = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"], max_turns=len(estado_simulacao["transcricao_logica"]))
|
| 195 |
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}\"\n**Feedback Detalhado (Pontos Fortes, Melhorias, Sugestões, Fundamentação, Estratégia):**"
|
| 196 |
-
return chamar_gemini_api(prompt_analise, temperature=0.65, max_output_tokens=
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
def adicionar_fala_transcricao(estado_simulacao, ator, fala):
|
|
|
|
| 199 |
estado_simulacao["transcricao_logica"].append((ator, fala))
|
| 200 |
if ator == "Advogado do Réu (Você)": estado_simulacao["transcricao_chat"].append((fala, None))
|
| 201 |
else:
|
|
@@ -205,6 +366,7 @@ def adicionar_fala_transcricao(estado_simulacao, ator, fala):
|
|
| 205 |
return estado_simulacao
|
| 206 |
|
| 207 |
def mostrar_botoes_corretos(fase_atual):
|
|
|
|
| 208 |
vis = {
|
| 209 |
"btn_responder_conciliacao": fase_atual == FASE_ABERTURA_CONCILIACAO,
|
| 210 |
"btn_chamar_testemunha_reu": fase_atual == FASE_TESTEMUNHAS_REU_INICIO,
|
|
@@ -217,83 +379,147 @@ def mostrar_botoes_corretos(fase_atual):
|
|
| 217 |
}
|
| 218 |
return [gr.update(visible=vis[k]) for k in sorted(vis.keys())]
|
| 219 |
|
| 220 |
-
|
| 221 |
def configurar_e_iniciar_simulacao(estado_s, fatos, p_reu, p_autor, t_reu_str, t_autor_str):
|
|
|
|
| 222 |
novo_estado = estado_inicial_simulacao()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
novo_estado["caso_fatos"], novo_estado["provas_reu_texto"], novo_estado["provas_autor_supostas_texto"] = fatos, p_reu, p_autor
|
| 224 |
def parse_testemunhas(t_str):
|
| 225 |
-
|
| 226 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
novo_estado["fase_aij"] = FASE_ABERTURA_CONCILIACAO
|
| 228 |
novo_estado = adicionar_fala_transcricao(novo_estado, "Sistema", "Configuração salva. Iniciando simulação...")
|
|
|
|
| 229 |
fala_juiz = gerar_resposta_juiz_ia(novo_estado)
|
| 230 |
novo_estado = adicionar_fala_transcricao(novo_estado, "Juiz (IA)", fala_juiz)
|
| 231 |
fala_adv_autor = gerar_resposta_advogado_autor_ia(novo_estado)
|
| 232 |
novo_estado = adicionar_fala_transcricao(novo_estado, "Advogado do Autor (IA)", fala_adv_autor)
|
| 233 |
novo_estado["instrucao_para_usuario"] = "Responda à proposta de conciliação do Autor ou declare sua posição."
|
| 234 |
novo_estado["feedback_para_usuario"] = analisar_atuacao_defesa_ia(novo_estado)
|
| 235 |
-
nomes_testemunhas_reu = [t["nome"] for t in novo_estado["testemunhas_reu_defs"]]
|
| 236 |
botoes_vis = mostrar_botoes_corretos(novo_estado["fase_aij"])
|
| 237 |
-
|
|
|
|
| 238 |
|
| 239 |
def lidar_com_fala_usuario(estado_s, fala_usuario_txt):
|
|
|
|
| 240 |
if not fala_usuario_txt and estado_s["fase_aij"] not in [FASE_TESTEMUNHAS_REU_INICIO]:
|
| 241 |
estado_s["instrucao_para_usuario"] = "Por favor, digite sua fala ou selecione uma ação."
|
| 242 |
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"])
|
| 243 |
|
| 244 |
estado_s = copy.deepcopy(estado_s)
|
| 245 |
ator_usuario = "Advogado do Réu (Você)"
|
| 246 |
-
if estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_PERGUNTAS_REU
|
| 247 |
-
|
| 248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
|
|
|
|
| 250 |
if estado_s["fase_aij"] == FASE_ABERTURA_CONCILIACAO:
|
| 251 |
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s, fala_adv_reu=fala_usuario_txt)
|
| 252 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 253 |
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Partes se manifestaram sobre conciliação. Decida o prosseguimento.")
|
| 254 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 255 |
-
if any(k in fala_juiz.lower() for k in ["testemunha", "instrução", "prossegu"]):
|
| 256 |
-
if estado_s["testemunhas_autor_supostas_defs"]:
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU:
|
| 261 |
fala_test_autor = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_usuario_txt)
|
| 262 |
estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {estado_s['testemunha_em_depoimento']['nome']} (Autor - IA)", fala_test_autor)
|
| 263 |
-
estado_s["instrucao_para_usuario"] = f"Faça outra pergunta à testemunha {estado_s['testemunha_em_depoimento']['nome']} (Autor) ou
|
| 264 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 265 |
estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR
|
| 266 |
-
fala_adv_autor_ia = gerar_resposta_advogado_autor_ia(estado_s)
|
| 267 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor_ia)
|
| 268 |
-
estado_s["instrucao_para_usuario"] = f"
|
| 269 |
-
|
| 270 |
-
|
|
|
|
|
|
|
| 271 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor_ia)
|
| 272 |
-
if "pergunta" in fala_adv_autor_ia.lower() or "?" in fala_adv_autor_ia
|
| 273 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
elif estado_s["fase_aij"] == FASE_ALEGACOES_FINAIS_REU:
|
| 275 |
-
# estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Réu (Você)", fala_usuario_txt) # Já adicionado no início da função
|
| 276 |
estado_s["fase_aij"] = FASE_ANALISE_FINAL_PROFESSOR
|
| 277 |
fala_juiz = gerar_resposta_juiz_ia(estado_s)
|
| 278 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 279 |
-
estado_s["instrucao_para_usuario"] = "Audiência encerrada. Veja feedback final."
|
| 280 |
-
|
|
|
|
| 281 |
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 "")
|
|
|
|
| 282 |
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"])
|
| 283 |
|
| 284 |
def acao_botao_juiz_avancar(estado_s):
|
|
|
|
| 285 |
estado_s = copy.deepcopy(estado_s)
|
| 286 |
fase_atual = estado_s["fase_aij"]
|
| 287 |
-
|
| 288 |
|
| 289 |
if fase_atual == FASE_ABERTURA_CONCILIACAO:
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s)
|
| 297 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 298 |
if not ("Não tenho mais testemunhas" in fala_adv_autor or "Não arrolei testemunhas" in fala_adv_autor):
|
| 299 |
estado_s["testemunha_autor_atual_idx"] += 1
|
|
@@ -301,164 +527,462 @@ def acao_botao_juiz_avancar(estado_s):
|
|
| 301 |
if idx < len(estado_s["testemunhas_autor_supostas_defs"]):
|
| 302 |
t_info = estado_s["testemunhas_autor_supostas_defs"][idx]
|
| 303 |
estado_s["testemunha_em_depoimento"] = {"nome": t_info["nome"], "pontos_chave": t_info["pontos_chave"], "parte": "AUTOR"}
|
| 304 |
-
fala_test_autor = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_adv_autor)
|
| 305 |
estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {t_info['nome']} (Autor - IA)", fala_test_autor)
|
| 306 |
-
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU, f"Contradite {t_info['nome']} (Autor)."
|
| 307 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
elif fase_atual == FASE_TESTEMUNHAS_AUTOR_INICIO or fase_atual == FASE_TESTEMUNHAS_AUTOR_PERGUNTAS_AUTOR:
|
| 309 |
-
|
|
|
|
| 310 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 311 |
-
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s)
|
| 312 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 320 |
if idx < len(estado_s["testemunhas_autor_supostas_defs"]):
|
| 321 |
t_info = estado_s["testemunhas_autor_supostas_defs"][idx]
|
| 322 |
estado_s["testemunha_em_depoimento"] = {"nome": t_info["nome"], "pontos_chave": t_info["pontos_chave"], "parte": "AUTOR"}
|
| 323 |
-
fala_test_autor = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_adv_autor)
|
| 324 |
estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {t_info['nome']} (Autor - IA)", fala_test_autor)
|
| 325 |
-
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU, f"Contradite {t_info['nome']} (Autor)."
|
|
|
|
|
|
|
|
|
|
|
|
|
| 326 |
elif fase_atual == FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU:
|
|
|
|
| 327 |
estado_s["testemunha_em_depoimento"] = None
|
| 328 |
-
|
| 329 |
-
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica=acao_juiz_txt)
|
| 330 |
-
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 331 |
if estado_s["testemunha_autor_atual_idx"] + 1 < len(estado_s["testemunhas_autor_supostas_defs"]):
|
| 332 |
-
estado_s["fase_aij"]
|
|
|
|
|
|
|
| 333 |
# Adv Autor precisa ser chamado para agir
|
| 334 |
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv Autor chama/pergunta
|
| 335 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 336 |
if not ("Não tenho mais testemunhas" in fala_adv_autor or "Não arrolei testemunhas" in fala_adv_autor):
|
| 337 |
-
estado_s["testemunha_autor_atual_idx"] += 1
|
|
|
|
| 338 |
if idx_new < len(estado_s["testemunhas_autor_supostas_defs"]):
|
| 339 |
t_info_new = estado_s["testemunhas_autor_supostas_defs"][idx_new]
|
| 340 |
estado_s["testemunha_em_depoimento"] = {"nome": t_info_new["nome"], "pontos_chave": t_info_new["pontos_chave"], "parte": "AUTOR"}
|
| 341 |
fala_test_autor_new = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_adv_autor)
|
| 342 |
estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {t_info_new['nome']} (Autor - IA)", fala_test_autor_new)
|
| 343 |
-
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU, f"Contradite {t_info_new['nome']} (Autor)."
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 352 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_aleg_autor)
|
| 353 |
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_ALEGACOES_FINAIS_REU, "Apresente suas Alegações Finais."
|
| 354 |
|
| 355 |
elif fase_atual in [FASE_TESTEMUNHAS_REU_PERGUNTAS_REU, FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR]:
|
|
|
|
|
|
|
| 356 |
estado_s["testemunha_em_depoimento"] = None
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
estado_s =
|
| 365 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 367 |
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_ALEGACOES_FINAIS_REU, "Apresente suas Alegações Finais."
|
|
|
|
| 368 |
elif fase_atual == FASE_ALEGACOES_FINAIS_AUTOR:
|
| 369 |
-
|
| 370 |
-
|
|
|
|
| 371 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 372 |
estado_s["instrucao_para_usuario"] = "Apresente suas Alegações Finais."
|
| 373 |
-
else:
|
| 374 |
-
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Conduza para próxima etapa.")
|
| 375 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 376 |
-
estado_s["instrucao_para_usuario"] = "Siga instruções do Juiz."
|
| 377 |
|
| 378 |
estado_s["feedback_para_usuario"] = analisar_atuacao_defesa_ia(estado_s)
|
|
|
|
| 379 |
return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + mostrar_botoes_corretos(estado_s["fase_aij"])
|
| 380 |
|
| 381 |
def chamar_testemunha_reu_selecionada(estado_s, nome_testemunha_selecionada):
|
|
|
|
| 382 |
estado_s = copy.deepcopy(estado_s)
|
| 383 |
if not nome_testemunha_selecionada:
|
| 384 |
-
estado_s["instrucao_para_usuario"] = "
|
|
|
|
| 385 |
return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + mostrar_botoes_corretos(estado_s["fase_aij"])
|
|
|
|
| 386 |
idx_testemunha = next((i for i, t in enumerate(estado_s["testemunhas_reu_defs"]) if t["nome"] == nome_testemunha_selecionada), -1)
|
| 387 |
if idx_testemunha == -1:
|
| 388 |
-
estado_s["instrucao_para_usuario"] = f"Testemunha '{nome_testemunha_selecionada}' não encontrada."
|
|
|
|
| 389 |
return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + mostrar_botoes_corretos(estado_s["fase_aij"])
|
| 390 |
|
| 391 |
estado_s["testemunha_reu_atual_idx"] = idx_testemunha
|
| 392 |
testemunha_obj = estado_s["testemunhas_reu_defs"][idx_testemunha]
|
| 393 |
estado_s["testemunha_em_depoimento"] = {"nome": testemunha_obj["nome"], "pontos_chave": testemunha_obj["pontos_chave"], "parte": "REU"}
|
| 394 |
-
|
| 395 |
-
|
|
|
|
|
|
|
| 396 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 397 |
-
estado_s["fase_aij"]
|
|
|
|
| 398 |
estado_s["feedback_para_usuario"] = analisar_atuacao_defesa_ia(estado_s)
|
|
|
|
| 399 |
return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + mostrar_botoes_corretos(estado_s["fase_aij"])
|
| 400 |
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
if not
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 405 |
sim_state = gr.State(value=estado_inicial_simulacao())
|
| 406 |
|
| 407 |
with gr.Tabs() as abas_principais:
|
| 408 |
-
with gr.TabItem("1. Configuração", id=0):
|
| 409 |
-
gr.Markdown("## Detalhes do Caso")
|
| 410 |
-
|
|
|
|
|
|
|
|
|
|
| 411 |
with gr.Row():
|
| 412 |
with gr.Column(scale=2):
|
| 413 |
-
fatos_input = gr.Textbox(lines=7, label="Resumo dos Fatos:", placeholder="Descreva
|
| 414 |
-
provas_reu_input = gr.Textbox(lines=4, label="
|
| 415 |
-
provas_autor_input = gr.Textbox(lines=4, label="
|
| 416 |
with gr.Column(scale=1):
|
| 417 |
-
testemunhas_reu_input = gr.Textbox(lines=5, label="Suas Testemunhas (Réu) - Nome: Pontos Chave", placeholder="João Silva: Viu X.\nMaria Costa: Sabe
|
| 418 |
-
testemunhas_autor_supostas_input = gr.Textbox(lines=5, label="Supostas Testemunhas do Autor - Nome: Pontos Chave", placeholder="Carlos Lima: Sofreu Z.\nAna B.:
|
| 419 |
-
btn_config_iniciar = gr.Button("💾 Salvar e Iniciar Simulação", variant="primary")
|
| 420 |
-
status_config_output = gr.Label(value="Aguardando configuração...")
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
btn_enviar_fala_usuario = gr.Button("🎤 Enviar Fala / Ação", variant="stop")
|
| 427 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 428 |
with gr.Row():
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
btn_adv_reu_responde_pela_sua_testemunha_action = gr.Button("Responder por Minha Test.", visible=False)
|
| 435 |
-
btn_apresentar_alegacoes_finais_reu_action = gr.Button("Alegações Finais", visible=False)
|
| 436 |
-
btn_juiz_avancar_fase_action = gr.Button("⚖️ Juiz (IA): Avançar", visible=False, variant="secondary")
|
| 437 |
lista_botoes_feedback = [btn_responder_conciliacao, btn_chamar_testemunha_reu_action, dropdown_testemunhas_reu_select, btn_perguntar_testemunha_autor_action, btn_adv_reu_pergunta_sua_testemunha_action, btn_adv_reu_responde_pela_sua_testemunha_action, btn_apresentar_alegacoes_finais_reu_action, btn_juiz_avancar_fase_action]
|
| 438 |
-
with gr.TabItem("3. Feedback IA", id=2):
|
| 439 |
-
gr.Markdown("## 💡 Análise (Professor IA)")
|
| 440 |
-
feedback_output = gr.Textbox(lines=15, label="Feedback sobre sua atuação:", interactive=False, show_copy_button=True)
|
| 441 |
|
| 442 |
-
|
| 443 |
-
|
|
|
|
|
|
|
| 444 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 445 |
outputs_config = [sim_state, chat_aij_output, feedback_output, instrucao_usuario_output, dropdown_testemunhas_reu_select] + lista_botoes_feedback
|
| 446 |
-
btn_config_iniciar.click(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
|
| 448 |
outputs_fala_usuario = [sim_state, chat_aij_output, feedback_output, instrucao_usuario_output, fala_usuario_input] + lista_botoes_feedback
|
| 449 |
btn_enviar_fala_usuario.click(lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario)
|
| 450 |
fala_usuario_input.submit(lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario)
|
| 451 |
-
|
| 452 |
outputs_acao_juiz = [sim_state, chat_aij_output, feedback_output, instrucao_usuario_output] + lista_botoes_feedback
|
| 453 |
btn_juiz_avancar_fase_action.click(acao_botao_juiz_avancar, inputs=[sim_state], outputs=outputs_acao_juiz).then(lambda: gr.Textbox(value=""), outputs=[fala_usuario_input])
|
| 454 |
btn_chamar_testemunha_reu_action.click(chamar_testemunha_reu_selecionada, inputs=[sim_state, dropdown_testemunhas_reu_select], outputs=outputs_acao_juiz).then(lambda: gr.Textbox(value=""), outputs=[fala_usuario_input])
|
| 455 |
|
| 456 |
-
# Links dos botões
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 462 |
|
| 463 |
if __name__ == "__main__":
|
| 464 |
if not GEMINI_API_KEY:
|
|
@@ -467,4 +991,4 @@ if __name__ == "__main__":
|
|
| 467 |
print("Para rodar localmente, edite o script e insira sua chave ou defina a variável de ambiente.")
|
| 468 |
print("Para Hugging Face Spaces, configure o Secret 'GEMINI_API_KEY'.")
|
| 469 |
print("#####################################################################")
|
| 470 |
-
demo.queue().launch()
|
|
|
|
| 4 |
import os
|
| 5 |
import copy
|
| 6 |
|
| 7 |
+
# --- Configuration from Script 1 & 2 (merged) ---
|
| 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 |
# Para teste local, descomente e cole sua chave, mas NÃO FAÇA COMMIT DISSO COM A CHAVE.
|
| 12 |
# GEMINI_API_KEY = "SUA_CHAVE_AQUI_PARA_TESTE_LOCAL_APENAS"
|
| 13 |
|
| 14 |
+
MODEL_NAME = "gemini-1.5-flash-latest" # Consistent model name
|
|
|
|
| 15 |
API_URL_BASE = f"https://generativelanguage.googleapis.com/v1beta/models/{MODEL_NAME}:generateContent"
|
| 16 |
|
| 17 |
+
# --- Fases da AIJ (from Script 1) ---
|
| 18 |
FASE_INICIAL_CONFIG = "CONFIGURACAO"
|
| 19 |
FASE_ABERTURA_CONCILIACAO = "ABERTURA_E_CONCILIACAO"
|
| 20 |
FASE_TESTEMUNHAS_AUTOR_INICIO = "TESTEMUNHAS_AUTOR_INICIO"
|
|
|
|
| 28 |
FASE_ANALISE_FINAL_PROFESSOR = "ANALISE_FINAL_PROFESSOR"
|
| 29 |
FASE_CONCLUIDA = "AIJ_CONCLUIDA"
|
| 30 |
|
| 31 |
+
# --- Predefined Case Data (from Script 2, adapted for Script 1 structure) ---
|
| 32 |
+
CASO_TITULO_PREDEFINIDO = "O Caso da Reportagem Revisitada"
|
| 33 |
+
CASO_PARTES_PREDEFINIDO = "Autor: Carlos Alberto Mendes\nRéu: Jornal 'A Verdade Diária'"
|
| 34 |
+
CASO_DESCRICAO_PREDEFINIDO = """
|
| 35 |
+
Uma pessoa (Carlos Alberto Mendes) processou um jornal (A Verdade Diária) alegando violação do direito ao esquecimento.
|
| 36 |
+
O jornal publicou uma matéria relembrando um crime ocorrido há 15 anos, no qual o autor foi
|
| 37 |
+
acusado de fraude, mas posteriormente absolvido por falta de provas. A matéria original foi publicada na época dos fatos
|
| 38 |
+
e a nova matéria, parte de uma série "Crimes que Marcaram a Cidade", revisitou o caso, mencionando a absolvição.
|
| 39 |
+
|
| 40 |
+
O autor alega que a republicação da história, mesmo com a menção da absolvição, causou-lhe
|
| 41 |
+
constrangimentos sociais, dificuldades em obter novo emprego e reacendeu traumas passados,
|
| 42 |
+
afetando sua vida familiar. Ele requer a remoção da matéria do site do jornal e uma indenização
|
| 43 |
+
por danos morais.
|
| 44 |
+
|
| 45 |
+
O jornal (réu) defende a liberdade de imprensa e o direito à informação, argumentando que
|
| 46 |
+
a matéria tem interesse público histórico, é factualmente correta (inclusive quanto à absolvição)
|
| 47 |
+
e faz parte do acervo jornalístico que documenta a história da comunidade.
|
| 48 |
+
"""
|
| 49 |
+
CASO_FATOS_COMPLETO_PREDEFINIDO = f"Título: {CASO_TITULO_PREDEFINIDO}\nPartes:\n{CASO_PARTES_PREDEFINIDO}\n\n---INÍCIO DOS FATOS---\n{CASO_DESCRICAO_PREDEFINIDO.strip()}"
|
| 50 |
+
|
| 51 |
+
ARGUMENTOS_AUTOR_PREDEFINIDOS = [
|
| 52 |
+
"Argumento: A matéria publicada reabriu feridas do passado e causou danos psicológicos e sociais ao autor. Prova: Laudo psicológico atestando abalo emocional e depoimentos sobre constrangimento social.",
|
| 53 |
+
"Argumento: O autor já foi absolvido judicialmente e tem direito a reconstruir sua vida sem o estigma do passado. Prova: Cópia da sentença absolutória.",
|
| 54 |
+
"Argumento: O tempo transcorrido (15 anos) torna o caso desatualizado e sem relevância pública atual que justifique a exposição. Prova: Irrelevância pública atual, foco no dano individual.",
|
| 55 |
+
"Argumento: A publicação violou o direito à privacidade e à honra do autor. Prova: Doutrina e jurisprudência sobre direitos da personalidade."
|
| 56 |
+
]
|
| 57 |
+
PROVAS_AUTOR_SUPPOSTAS_TEXTO_PREDEFINIDO = "\n".join(ARGUMENTOS_AUTOR_PREDEFINIDOS)
|
| 58 |
+
|
| 59 |
+
CONTRA_ARGUMENTOS_REU_PREDEFINIDOS = [
|
| 60 |
+
"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.",
|
| 61 |
+
"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.",
|
| 62 |
+
"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.",
|
| 63 |
+
"Argumento: A matéria destacou a absolvição do autor, não havendo intenção de difamar. Prova: Conteúdo da própria matéria."
|
| 64 |
+
]
|
| 65 |
+
PROVAS_REU_TEXTO_PREDEFINIDO = "\n".join(CONTRA_ARGUMENTOS_REU_PREDEFINIDOS)
|
| 66 |
+
|
| 67 |
+
TESTEMUNHAS_REU_PREDEFINIDAS = [
|
| 68 |
+
{"nome": "João Silva", "pontos_chave": "Editor-chefe do jornal. Confirmará o processo editorial, o interesse público da série de reportagens e a ausência de intenção de prejudicar o autor."},
|
| 69 |
+
{"nome": "Dra. Maria Santos", "pontos_chave": "Historiadora local. Atestará a relevância histórica do caso para a comunidade e a importância de preservar a memória de tais eventos."},
|
| 70 |
+
{"nome": "Roberto Almeida", "pontos_chave": "Jornalista responsável pela matéria. Detalhará a pesquisa, a verificação dos fatos e a menção explícita à absolvição do autor."}
|
| 71 |
+
]
|
| 72 |
+
TESTEMUNHAS_REU_TEXTO_PREDEFINIDO = "\n".join([f"{t['nome']}: {t['pontos_chave']}" for t in TESTEMUNHAS_REU_PREDEFINIDAS])
|
| 73 |
+
|
| 74 |
+
# Para o caso padrão, precisamos de testemunhas do autor também.
|
| 75 |
+
TESTEMUNHAS_AUTOR_SUPPOSTAS_PREDEFINIDAS_TEXTO = """
|
| 76 |
+
Dr. Felipe Antunes: Psicólogo do autor. Relatará o impacto emocional da nova reportagem na vida do autor.
|
| 77 |
+
Sra. Clara Dias: Vizinha do autor. Comentará sobre as mudanças no tratamento social que o autor recebeu após a reportagem.
|
| 78 |
+
"""
|
| 79 |
+
|
| 80 |
+
LEGISLACAO_PRECEDENTES_PREDEFINIDO = {
|
| 81 |
+
"favoraveis_ao_reu": [
|
| 82 |
+
"Art. 5º, IV, IX e XIV da Constituição Federal - garantia da liberdade de expressão e acesso à informação",
|
| 83 |
+
"ADPF 130 (STF) - declarou a Lei de Imprensa incompatível com a ordem constitucional atual",
|
| 84 |
+
"RE 1.010.606 (STF) - não reconheceu o direito ao esquecimento na esfera civil de forma irrestrita",
|
| 85 |
+
"Pacto de San José da Costa Rica - proteção à liberdade de expressão",
|
| 86 |
+
],
|
| 87 |
+
"favoraveis_ao_autor": [
|
| 88 |
+
"Art. 5º, X da Constituição Federal - inviolabilidade da intimidade, vida privada e honra",
|
| 89 |
+
"Art. 21 do Código Civil - proteção à vida privada",
|
| 90 |
+
"Enunciado 531 da VI Jornada de Direito Civil - reconhece o direito ao esquecimento",
|
| 91 |
+
"LGPD (Lei Geral de Proteção de Dados) - embora não diretamente, reforça a proteção a dados pessoais."
|
| 92 |
+
]
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
# --- Funções de Estado e API (from Script 1) ---
|
| 96 |
def estado_inicial_simulacao():
|
| 97 |
return {
|
| 98 |
"fase_aij": FASE_INICIAL_CONFIG, "caso_fatos": "", "provas_reu_texto": "",
|
|
|
|
| 101 |
"testemunha_reu_atual_idx": -1, "testemunha_em_depoimento": None,
|
| 102 |
"transcricao_chat": [], "transcricao_logica": [],
|
| 103 |
"feedback_para_usuario": "Aguardando início da simulação.",
|
| 104 |
+
"instrucao_para_usuario": "Configure os detalhes do caso na aba 'Configuração' ou carregue o caso padrão."
|
| 105 |
}
|
| 106 |
|
| 107 |
def chamar_gemini_api(prompt_text, temperature=0.7, max_output_tokens=800):
|
|
|
|
| 121 |
]
|
| 122 |
}
|
| 123 |
try:
|
| 124 |
+
response = requests.post(api_url_com_chave, headers=headers, data=json.dumps(data), timeout=180) # Increased timeout
|
| 125 |
response.raise_for_status()
|
| 126 |
response_json = response.json()
|
| 127 |
if response_json.get("candidates") and response_json["candidates"][0].get("content"):
|
|
|
|
| 129 |
elif response_json.get("promptFeedback") and response_json["promptFeedback"].get("blockReason"):
|
| 130 |
return f"ERRO_API: Conteúdo bloqueado. Razão: {response_json['promptFeedback']['blockReason']}"
|
| 131 |
return "ERRO_API: Resposta inesperada da API."
|
| 132 |
+
except requests.exceptions.Timeout:
|
| 133 |
+
return "ERRO_CONEXAO: Timeout ao chamar a API Gemini. Tente novamente."
|
| 134 |
except requests.exceptions.RequestException as e:
|
| 135 |
error_msg = f"ERRO_CONEXAO: {e}"
|
| 136 |
if e.response is not None:
|
|
|
|
| 148 |
historico_formatado += f"- {ator}: {fala}\n"
|
| 149 |
return historico_formatado
|
| 150 |
|
| 151 |
+
# --- Funções de Geração de Conteúdo IA (from Script 1, some new) ---
|
| 152 |
def gerar_caso_ficticio_com_ia():
|
| 153 |
+
# (Função mantida como no Script 1 original)
|
| 154 |
prompt_geracao_caso = """
|
| 155 |
**Instrução de Persona:** Você é um roteirista jurídico criativo e experiente, especializado em criar casos simulados realistas para treinamento de advogados.
|
| 156 |
**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".
|
|
|
|
| 172 |
`## Testemunhas Hipotéticas da Parte RÉ`
|
| 173 |
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.
|
| 174 |
"""
|
| 175 |
+
texto_caso_completo = chamar_gemini_api(prompt_geracao_caso, temperature=0.75, max_output_tokens=2500) # Increased tokens
|
| 176 |
if "ERRO_" in texto_caso_completo:
|
| 177 |
return {"fatos": f"Falha ao gerar caso com IA: {texto_caso_completo}", "provas_autor": "", "provas_reu": "", "testemunhas_autor": "", "testemunhas_reu": ""}
|
| 178 |
return parse_caso_gerado(texto_caso_completo)
|
| 179 |
|
| 180 |
def parse_caso_gerado(texto_completo_caso):
|
| 181 |
+
# (Função mantida como no Script 1 original)
|
| 182 |
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"}
|
| 183 |
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É"}
|
| 184 |
fatos_prefix = ""
|
|
|
|
| 206 |
dados_caso[chave_atual] = fatos_prefix + conteudo_secao if chave_atual == "fatos" and fatos_prefix else conteudo_secao
|
| 207 |
current_pos = fim_conteudo
|
| 208 |
for key_testemunha in ["testemunhas_autor", "testemunhas_reu"]:
|
| 209 |
+
if "Falha no parsing" not in dados_caso[key_testemunha] and dados_caso[key_testemunha]: # Check if not empty
|
| 210 |
linhas = dados_caso[key_testemunha].split('\n')
|
| 211 |
+
linhas_formatadas = []
|
| 212 |
+
for linha in linhas:
|
| 213 |
+
if linha.strip():
|
| 214 |
+
partes = linha.split(':', 1)
|
| 215 |
+
if len(partes) == 2:
|
| 216 |
+
linhas_formatadas.append(f"{partes[0].strip()}: {partes[1].strip()}")
|
| 217 |
+
else:
|
| 218 |
+
linhas_formatadas.append(partes[0].strip()) # Handle lines without colon if necessary
|
| 219 |
dados_caso[key_testemunha] = "\n".join(linhas_formatadas)
|
| 220 |
return dados_caso
|
| 221 |
|
|
|
|
| 224 |
dados_gerados = gerar_caso_ficticio_com_ia()
|
| 225 |
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."]
|
| 226 |
|
| 227 |
+
def acao_carregar_caso_padrao_ui():
|
| 228 |
+
gr.Info("Carregando caso padrão...")
|
| 229 |
+
return [
|
| 230 |
+
CASO_FATOS_COMPLETO_PREDEFINIDO,
|
| 231 |
+
PROVAS_REU_TEXTO_PREDEFINIDO,
|
| 232 |
+
PROVAS_AUTOR_SUPPOSTAS_TEXTO_PREDEFINIDO,
|
| 233 |
+
TESTEMUNHAS_REU_TEXTO_PREDEFINIDO,
|
| 234 |
+
TESTEMUNHAS_AUTOR_SUPPOSTAS_PREDEFINIDAS_TEXTO,
|
| 235 |
+
"Caso padrão carregado. Revise e salve."
|
| 236 |
+
]
|
| 237 |
+
|
| 238 |
def gerar_resposta_juiz_ia(estado_simulacao, acao_especifica=""):
|
| 239 |
+
# (Função mantida como no Script 1 original)
|
| 240 |
fase = estado_simulacao["fase_aij"]
|
| 241 |
historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
|
| 242 |
prompt = 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"
|
|
|
|
| 248 |
elif fase == FASE_ANALISE_FINAL_PROFESSOR: prompt += "**Tarefa:** Declare audiência encerrada para julgamento (simulado)."
|
| 249 |
else: prompt += f"**Tarefa:** Conduza a audiência. Ação específica: {acao_especifica or 'Nenhuma'}. Mantenha ordem e fluxo."
|
| 250 |
prompt += "\n**Sua Fala (Juiz):**"
|
| 251 |
+
return chamar_gemini_api(prompt, temperature=0.6, max_output_tokens=300)
|
| 252 |
|
| 253 |
def gerar_resposta_advogado_autor_ia(estado_simulacao, fala_adv_reu=""):
|
| 254 |
+
# (Função mantida como no Script 1 original)
|
| 255 |
fase = estado_simulacao["fase_aij"]
|
| 256 |
historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
|
| 257 |
prompt = 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"
|
|
|
|
| 272 |
elif fase == FASE_ALEGACOES_FINAIS_AUTOR: prompt += "**Tarefa:** Juiz concedeu palavra para alegações finais. Apresente resumo persuasivo e reitere pedidos."
|
| 273 |
else: prompt += f"**Contexto:** Adv. Réu (Usuário) disse: \"{fala_adv_reu}\"\n**Tarefa:** Responda estrategicamente."
|
| 274 |
prompt += "\n**Sua Resposta (Advogado Autor):**"
|
| 275 |
+
return chamar_gemini_api(prompt, temperature=0.75, max_output_tokens=450)
|
| 276 |
|
| 277 |
def gerar_resposta_testemunha_autor_ia(estado_simulacao, pergunta_feita):
|
| 278 |
+
# (Função mantida como no Script 1 original)
|
| 279 |
testemunha_obj = estado_simulacao.get("testemunha_em_depoimento")
|
| 280 |
if not testemunha_obj or testemunha_obj["parte"] != "AUTOR": return "Testemunha do Autor (IA): (Erro interno - Nenhuma testemunha do autor em depoimento)"
|
| 281 |
historico = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"])
|
| 282 |
prompt = 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}\"\n**Tarefa:** Responda claro, conciso, baseado nos seus pontos. Se Adv. Réu, seja cauteloso(a).\n**Sua Resposta (Testemunha {testemunha_obj['nome']}):**"
|
| 283 |
+
return chamar_gemini_api(prompt, temperature=0.6, max_output_tokens=250)
|
| 284 |
|
| 285 |
def analisar_atuacao_defesa_ia(estado_simulacao, ultima_fala_reu=""):
|
| 286 |
+
# (Função mantida como no Script 1 original)
|
| 287 |
historico_completo_dialogo = formatar_historico_para_prompt(estado_simulacao["transcricao_logica"], max_turns=len(estado_simulacao["transcricao_logica"]))
|
| 288 |
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}\"\n**Feedback Detalhado (Pontos Fortes, Melhorias, Sugestões, Fundamentação, Estratégia):**"
|
| 289 |
+
return chamar_gemini_api(prompt_analise, temperature=0.65, max_output_tokens=1200)
|
| 290 |
+
|
| 291 |
+
# --- Novas Funções de IA para Treinamento (inspiradas em Script 2) ---
|
| 292 |
+
def avaliar_argumentos_defesa_ia(fatos_caso, provas_reu, tipo_argumento, argumento_usuario):
|
| 293 |
+
if not argumento_usuario.strip():
|
| 294 |
+
return "Por favor, insira seus argumentos para avaliação."
|
| 295 |
+
|
| 296 |
+
contexto_caso = f"""
|
| 297 |
+
Você está avaliando argumentos no contexto de um caso jurídico no Brasil sobre direito ao esquecimento vs. liberdade de imprensa.
|
| 298 |
+
O usuário representa a defesa (jornal).
|
| 299 |
+
**Fatos do Caso:** {fatos_caso if fatos_caso else CASO_DESCRICAO_PREDEFINIDO}
|
| 300 |
+
**Principais Argumentos/Provas da Defesa (Jornal):** {provas_reu if provas_reu else "\n".join(CONTRA_ARGUMENTOS_REU_PREDEFINIDOS)}
|
| 301 |
+
"""
|
| 302 |
+
prompt = f"""
|
| 303 |
+
{contexto_caso}
|
| 304 |
+
|
| 305 |
+
**Persona:** Você é um Juiz experiente em um tribunal brasileiro, com especialidade em casos de liberdade de imprensa e direitos da personalidade.
|
| 306 |
+
**Tarefa:** Avalie o seguinte argumento apresentado pelo advogado de defesa (jornal) para a peça/momento processual: "{tipo_argumento}".
|
| 307 |
+
Forneça feedback detalhado e construtivo em português brasileiro, incluindo:
|
| 308 |
+
1. **Pontos Fortes:** Destaque aspectos positivos (ex: fundamentação legal sólida, coerência lógica, clareza, persuasão, uso de fatos).
|
| 309 |
+
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).
|
| 310 |
+
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).
|
| 311 |
+
4. **Nota Geral (0 a 5):** Atribua uma nota considerando:
|
| 312 |
+
* Fundamentação Legal/Jurisprudencial (Peso 3)
|
| 313 |
+
* Coerência e Lógica (Peso 2)
|
| 314 |
+
* Persuasão e Clareza (Peso 2)
|
| 315 |
+
* Adequação ao tipo de peça/momento (Peso 1)
|
| 316 |
+
* Conexão com os fatos/provas do caso (Peso 2)
|
| 317 |
+
|
| 318 |
+
Formato da Resposta: Utilize linguagem formal e jurídica. Estruture a resposta rigorosamente com os títulos:
|
| 319 |
+
`### Pontos Fortes`
|
| 320 |
+
`### Pontos a Melhorar`
|
| 321 |
+
`### Sugestões Específicas`
|
| 322 |
+
`### Nota Geral`
|
| 323 |
+
|
| 324 |
+
**Argumento do Advogado de Defesa (Jornal):**
|
| 325 |
+
"{argumento_usuario}"
|
| 326 |
+
|
| 327 |
+
**Sua Avaliação:**
|
| 328 |
+
"""
|
| 329 |
+
return chamar_gemini_api(prompt, temperature=0.6, max_output_tokens=1000)
|
| 330 |
+
|
| 331 |
+
def gerar_resposta_testemunha_defesa_para_treino_ia(fatos_caso, nome_testemunha, pontos_chave_testemunha, historico_perguntas_respostas, pergunta_atual_adv_defesa):
|
| 332 |
+
contexto_caso = f"""
|
| 333 |
+
Você está simulando o depoimento de uma testemunha de DEFESA (Jornal) em uma Audiência de Instrução e Julgamento (AIJ) no Brasil.
|
| 334 |
+
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.
|
| 335 |
+
**Fatos do Caso:** {fatos_caso if fatos_caso else CASO_DESCRICAO_PREDEFINIDO}
|
| 336 |
+
"""
|
| 337 |
+
historico_formatado = "\nDepoimento até agora:\n"
|
| 338 |
+
for p, r in historico_perguntas_respostas:
|
| 339 |
+
historico_formatado += f"- Advogado Defesa: {p}\n- {nome_testemunha}: {r}\n"
|
| 340 |
+
|
| 341 |
+
prompt = f"""
|
| 342 |
+
{contexto_caso}
|
| 343 |
+
|
| 344 |
+
**Persona:** Você é {nome_testemunha}, testemunha arrolada pela DEFESA (Jornal).
|
| 345 |
+
**Seus Pontos Chave a Defender/Explicar:** {pontos_chave_testemunha}
|
| 346 |
+
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).
|
| 347 |
+
Use linguagem formal, mas acessível para uma testemunha. Seja objetivo e direto. Evite admitir qualquer falha ou negligência por parte do jornal.
|
| 348 |
+
{historico_formatado if historico_perguntas_respostas else "Este é o início do seu depoimento."}
|
| 349 |
+
|
| 350 |
+
**Pergunta do Advogado de Defesa (Jornal):** "{pergunta_atual_adv_defesa}"
|
| 351 |
+
|
| 352 |
+
**Sua Resposta ({nome_testemunha}):**
|
| 353 |
+
"""
|
| 354 |
+
return chamar_gemini_api(prompt, temperature=0.5, max_output_tokens=300)
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
# --- Funções de Lógica da Simulação e UI (from Script 1, adaptadas e com novas) ---
|
| 358 |
def adicionar_fala_transcricao(estado_simulacao, ator, fala):
|
| 359 |
+
# (Função mantida como no Script 1 original)
|
| 360 |
estado_simulacao["transcricao_logica"].append((ator, fala))
|
| 361 |
if ator == "Advogado do Réu (Você)": estado_simulacao["transcricao_chat"].append((fala, None))
|
| 362 |
else:
|
|
|
|
| 366 |
return estado_simulacao
|
| 367 |
|
| 368 |
def mostrar_botoes_corretos(fase_atual):
|
| 369 |
+
# (Função mantida como no Script 1 original)
|
| 370 |
vis = {
|
| 371 |
"btn_responder_conciliacao": fase_atual == FASE_ABERTURA_CONCILIACAO,
|
| 372 |
"btn_chamar_testemunha_reu": fase_atual == FASE_TESTEMUNHAS_REU_INICIO,
|
|
|
|
| 379 |
}
|
| 380 |
return [gr.update(visible=vis[k]) for k in sorted(vis.keys())]
|
| 381 |
|
|
|
|
| 382 |
def configurar_e_iniciar_simulacao(estado_s, fatos, p_reu, p_autor, t_reu_str, t_autor_str):
|
| 383 |
+
# (Função adaptada do Script 1)
|
| 384 |
novo_estado = estado_inicial_simulacao()
|
| 385 |
+
if not fatos or not p_reu or not p_autor: # Basic validation
|
| 386 |
+
gr.Warning("Por favor, preencha todos os campos de configuração do caso ou carregue o caso padrão.")
|
| 387 |
+
return [novo_estado, novo_estado["transcricao_chat"], "Erro: Configuração incompleta.", "Preencha a configuração.", gr.Dropdown(choices=[], value=None)] + mostrar_botoes_corretos(novo_estado["fase_aij"])
|
| 388 |
+
|
| 389 |
novo_estado["caso_fatos"], novo_estado["provas_reu_texto"], novo_estado["provas_autor_supostas_texto"] = fatos, p_reu, p_autor
|
| 390 |
def parse_testemunhas(t_str):
|
| 391 |
+
defs = []
|
| 392 |
+
if t_str and t_str.strip():
|
| 393 |
+
for linha in t_str.strip().split('\n'):
|
| 394 |
+
if linha.strip():
|
| 395 |
+
partes = linha.split(':', 1)
|
| 396 |
+
if len(partes) == 2:
|
| 397 |
+
defs.append({"nome": partes[0].strip(), "pontos_chave": partes[1].strip()})
|
| 398 |
+
elif len(partes) == 1 and partes[0].strip(): # Testemunha sem pontos chave explícitos
|
| 399 |
+
defs.append({"nome": partes[0].strip(), "pontos_chave": "Não especificado."})
|
| 400 |
+
return defs
|
| 401 |
+
|
| 402 |
+
novo_estado["testemunhas_reu_defs"] = parse_testemunhas(t_reu_str)
|
| 403 |
+
novo_estado["testemunhas_autor_supostas_defs"] = parse_testemunhas(t_autor_str)
|
| 404 |
+
|
| 405 |
novo_estado["fase_aij"] = FASE_ABERTURA_CONCILIACAO
|
| 406 |
novo_estado = adicionar_fala_transcricao(novo_estado, "Sistema", "Configuração salva. Iniciando simulação...")
|
| 407 |
+
gr.Info("Iniciando simulação... Gerando falas iniciais da IA.")
|
| 408 |
fala_juiz = gerar_resposta_juiz_ia(novo_estado)
|
| 409 |
novo_estado = adicionar_fala_transcricao(novo_estado, "Juiz (IA)", fala_juiz)
|
| 410 |
fala_adv_autor = gerar_resposta_advogado_autor_ia(novo_estado)
|
| 411 |
novo_estado = adicionar_fala_transcricao(novo_estado, "Advogado do Autor (IA)", fala_adv_autor)
|
| 412 |
novo_estado["instrucao_para_usuario"] = "Responda à proposta de conciliação do Autor ou declare sua posição."
|
| 413 |
novo_estado["feedback_para_usuario"] = analisar_atuacao_defesa_ia(novo_estado)
|
| 414 |
+
nomes_testemunhas_reu = [t["nome"] for t in novo_estado["testemunhas_reu_defs"]] if novo_estado["testemunhas_reu_defs"] else []
|
| 415 |
botoes_vis = mostrar_botoes_corretos(novo_estado["fase_aij"])
|
| 416 |
+
gr.Info("Simulação iniciada.")
|
| 417 |
+
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
|
| 418 |
|
| 419 |
def lidar_com_fala_usuario(estado_s, fala_usuario_txt):
|
| 420 |
+
# (Função mantida como no Script 1 original, com pequenas adaptações)
|
| 421 |
if not fala_usuario_txt and estado_s["fase_aij"] not in [FASE_TESTEMUNHAS_REU_INICIO]:
|
| 422 |
estado_s["instrucao_para_usuario"] = "Por favor, digite sua fala ou selecione uma ação."
|
| 423 |
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"])
|
| 424 |
|
| 425 |
estado_s = copy.deepcopy(estado_s)
|
| 426 |
ator_usuario = "Advogado do Réu (Você)"
|
| 427 |
+
if estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_PERGUNTAS_REU and estado_s.get("testemunha_em_depoimento"):
|
| 428 |
+
ator_usuario = f"Advogado do Réu (Você) perguntando a {estado_s['testemunha_em_depoimento']['nome']}"
|
| 429 |
+
elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR and estado_s.get("testemunha_em_depoimento"):
|
| 430 |
+
ator_usuario = f"Testemunha {estado_s['testemunha_em_depoimento']['nome']} (Réu) respondendo"
|
| 431 |
+
|
| 432 |
+
if fala_usuario_txt:
|
| 433 |
+
estado_s = adicionar_fala_transcricao(estado_s, ator_usuario, fala_usuario_txt)
|
| 434 |
+
gr.Info(f"Sua fala registrada. Aguardando respostas da IA...")
|
| 435 |
|
| 436 |
+
# Lógica de transição de fases e respostas da IA
|
| 437 |
if estado_s["fase_aij"] == FASE_ABERTURA_CONCILIACAO:
|
| 438 |
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s, fala_adv_reu=fala_usuario_txt)
|
| 439 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 440 |
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Partes se manifestaram sobre conciliação. Decida o prosseguimento.")
|
| 441 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 442 |
+
if any(k in fala_juiz.lower() for k in ["testemunha", "instrução", "prossegu", "oitiva"]):
|
| 443 |
+
if estado_s["testemunhas_autor_supostas_defs"]:
|
| 444 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_AUTOR_INICIO, "Aguarde Juiz/Adv.Autor chamarem testemunha."
|
| 445 |
+
# Adicionar fala do Adv. Autor chamando a testemunha
|
| 446 |
+
fala_adv_autor_chamando = gerar_resposta_advogado_autor_ia(estado_s)
|
| 447 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor_chamando)
|
| 448 |
+
if not ("Não tenho mais testemunhas" in fala_adv_autor_chamando or "Não arrolei testemunhas" in fala_adv_autor_chamando):
|
| 449 |
+
estado_s["testemunha_autor_atual_idx"] += 1
|
| 450 |
+
idx = estado_s["testemunha_autor_atual_idx"]
|
| 451 |
+
if idx < len(estado_s["testemunhas_autor_supostas_defs"]):
|
| 452 |
+
t_info = estado_s["testemunhas_autor_supostas_defs"][idx]
|
| 453 |
+
estado_s["testemunha_em_depoimento"] = {"nome": t_info["nome"], "pontos_chave": t_info["pontos_chave"], "parte": "AUTOR"}
|
| 454 |
+
fala_test_autor = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_adv_autor_chamando)
|
| 455 |
+
estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {t_info['nome']} (Autor - IA)", fala_test_autor)
|
| 456 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU, f"Contradite/pergunte à testemunha {t_info['nome']} (Autor)."
|
| 457 |
+
elif estado_s["testemunhas_reu_defs"]:
|
| 458 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_REU_INICIO, "Selecione sua testemunha para chamar."
|
| 459 |
+
else:
|
| 460 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_ALEGACOES_FINAIS_AUTOR, "Aguarde Juiz iniciar Alegações Finais."
|
| 461 |
+
# Se for para alegações do autor, o juiz deve dar a palavra e o adv. autor falar
|
| 462 |
+
fala_juiz_aleg = gerar_resposta_juiz_ia(estado_s)
|
| 463 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_aleg)
|
| 464 |
+
fala_aleg_autor = gerar_resposta_advogado_autor_ia(estado_s)
|
| 465 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_aleg_autor)
|
| 466 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_ALEGACOES_FINAIS_REU, "Apresente suas Alegações Finais."
|
| 467 |
+
else:
|
| 468 |
+
estado_s["instrucao_para_usuario"] = "Responda ao Juiz ou Adv. Autor sobre conciliação."
|
| 469 |
+
|
| 470 |
elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU:
|
| 471 |
fala_test_autor = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_usuario_txt)
|
| 472 |
estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {estado_s['testemunha_em_depoimento']['nome']} (Autor - IA)", fala_test_autor)
|
| 473 |
+
estado_s["instrucao_para_usuario"] = f"Faça outra pergunta à testemunha {estado_s['testemunha_em_depoimento']['nome']} (Autor) ou clique 'Juiz Avançar'."
|
| 474 |
+
|
| 475 |
+
elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_PERGUNTAS_REU: # Usuário (Adv Réu) perguntou à sua testemunha
|
| 476 |
+
# Aqui, o usuário está *atuando* como sua testemunha para responder à sua própria pergunta.
|
| 477 |
+
# A IA do Adv. Autor fará perguntas à testemunha do Réu.
|
| 478 |
+
# O usuário deve então responder como se fosse sua testemunha.
|
| 479 |
+
# Após a pergunta do usuário à sua testemunha, e a resposta simulada (pelo usuário mesmo, no chat),
|
| 480 |
+
# o Adv. Autor (IA) deve ter a chance de inquirir.
|
| 481 |
estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR
|
| 482 |
+
fala_adv_autor_ia = gerar_resposta_advogado_autor_ia(estado_s) # Adv. Autor IA pergunta à testemunha do Réu
|
| 483 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor_ia)
|
| 484 |
+
estado_s["instrucao_para_usuario"] = f"Como testemunha {estado_s['testemunha_em_depoimento']['nome']}, responda à pergunta do Adv. Autor."
|
| 485 |
+
|
| 486 |
+
elif estado_s["fase_aij"] == FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR: # Usuário respondeu como sua testemunha à pergunta do Adv. Autor
|
| 487 |
+
# Advogado do Autor (IA) pode fazer mais perguntas ou encerrar.
|
| 488 |
+
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
|
| 489 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor_ia)
|
| 490 |
+
if "pergunta" in fala_adv_autor_ia.lower() or "?" in fala_adv_autor_ia and "não tenho mais perguntas" not in fala_adv_autor_ia.lower():
|
| 491 |
+
estado_s["instrucao_para_usuario"] = f"Como testemunha {estado_s['testemunha_em_depoimento']['nome']}, responda à nova pergunta do Adv. Autor."
|
| 492 |
+
else: # Adv. Autor não tem mais perguntas
|
| 493 |
+
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.")
|
| 494 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 495 |
+
estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_PERGUNTAS_REU # Volta para Adv. Réu perguntar
|
| 496 |
+
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."
|
| 497 |
+
|
| 498 |
elif estado_s["fase_aij"] == FASE_ALEGACOES_FINAIS_REU:
|
|
|
|
| 499 |
estado_s["fase_aij"] = FASE_ANALISE_FINAL_PROFESSOR
|
| 500 |
fala_juiz = gerar_resposta_juiz_ia(estado_s)
|
| 501 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 502 |
+
estado_s["instrucao_para_usuario"] = "Audiência encerrada para sentença (simulada). Veja o feedback final do Professor IA."
|
| 503 |
+
# Analise final é chamada abaixo
|
| 504 |
+
|
| 505 |
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 "")
|
| 506 |
+
gr.Info("Respostas da IA geradas.")
|
| 507 |
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"])
|
| 508 |
|
| 509 |
def acao_botao_juiz_avancar(estado_s):
|
| 510 |
+
# (Função mantida e adaptada do Script 1)
|
| 511 |
estado_s = copy.deepcopy(estado_s)
|
| 512 |
fase_atual = estado_s["fase_aij"]
|
| 513 |
+
gr.Info(f"Avançando fase a partir de: {fase_atual}. Aguarde IA...")
|
| 514 |
|
| 515 |
if fase_atual == FASE_ABERTURA_CONCILIACAO:
|
| 516 |
+
# Se partes não chegaram a acordo, ou se o usuário pulou a conciliação.
|
| 517 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", "Considerando frustrada a tentativa de conciliação, passaremos à instrução.")
|
| 518 |
+
if estado_s["testemunhas_autor_supostas_defs"]:
|
| 519 |
+
estado_s["fase_aij"] = FASE_TESTEMUNHAS_AUTOR_INICIO
|
| 520 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s)
|
| 521 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 522 |
+
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv Autor chama/pergunta
|
| 523 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 524 |
if not ("Não tenho mais testemunhas" in fala_adv_autor or "Não arrolei testemunhas" in fala_adv_autor):
|
| 525 |
estado_s["testemunha_autor_atual_idx"] += 1
|
|
|
|
| 527 |
if idx < len(estado_s["testemunhas_autor_supostas_defs"]):
|
| 528 |
t_info = estado_s["testemunhas_autor_supostas_defs"][idx]
|
| 529 |
estado_s["testemunha_em_depoimento"] = {"nome": t_info["nome"], "pontos_chave": t_info["pontos_chave"], "parte": "AUTOR"}
|
| 530 |
+
fala_test_autor = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_adv_autor) # Testemunha responde à pergunta inicial
|
| 531 |
estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {t_info['nome']} (Autor - IA)", fala_test_autor)
|
| 532 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU, f"Contradite ou faça perguntas à testemunha {t_info['nome']} (Autor)."
|
| 533 |
+
else: # Adv Autor não tem testemunhas, mesmo que tenha sido definido
|
| 534 |
+
if estado_s["testemunhas_reu_defs"]: estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_REU_INICIO, "Selecione sua testemunha para chamar."
|
| 535 |
+
else: estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR # Pula para alegações finais
|
| 536 |
+
elif estado_s["testemunhas_reu_defs"]:
|
| 537 |
+
estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
|
| 538 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s)
|
| 539 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 540 |
+
estado_s["instrucao_para_usuario"] = "Selecione sua testemunha para chamar."
|
| 541 |
+
else: # Sem testemunhas de nenhuma parte
|
| 542 |
+
estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
|
| 543 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s) # Juiz anuncia alegações
|
| 544 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 545 |
+
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv Autor faz alegações
|
| 546 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 547 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_ALEGACOES_FINAIS_REU, "Apresente suas Alegações Finais."
|
| 548 |
+
|
| 549 |
elif fase_atual == FASE_TESTEMUNHAS_AUTOR_INICIO or fase_atual == FASE_TESTEMUNHAS_AUTOR_PERGUNTAS_AUTOR:
|
| 550 |
+
# Juiz pede ao Adv. Autor para chamar a *próxima* testemunha ou encerrar
|
| 551 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Verificar se há mais testemunhas do Autor ou encerrar esta fase.")
|
| 552 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 553 |
+
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv. Autor chama próxima ou diz que não tem mais
|
| 554 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 555 |
+
|
| 556 |
+
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"]):
|
| 557 |
+
estado_s["testemunha_em_depoimento"] = None
|
| 558 |
+
if estado_s["testemunhas_reu_defs"]:
|
| 559 |
+
estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
|
| 560 |
+
fala_juiz_trans = gerar_resposta_juiz_ia(estado_s) # Juiz anuncia oitiva das testemunhas do Réu
|
| 561 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_trans)
|
| 562 |
+
estado_s["instrucao_para_usuario"] = "Selecione sua testemunha para chamar."
|
| 563 |
+
else: # Sem testemunhas do Réu, vai para alegações finais
|
| 564 |
+
estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
|
| 565 |
+
fala_juiz_trans = gerar_resposta_juiz_ia(estado_s) # Juiz anuncia alegações
|
| 566 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_trans)
|
| 567 |
+
fala_aleg_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv Autor faz alegações
|
| 568 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_aleg_autor)
|
| 569 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_ALEGACOES_FINAIS_REU, "Apresente suas Alegações Finais."
|
| 570 |
+
else: # Adv Autor chamou próxima testemunha
|
| 571 |
+
estado_s["testemunha_autor_atual_idx"] += 1
|
| 572 |
+
idx = estado_s["testemunha_autor_atual_idx"]
|
| 573 |
+
# Garantir que o índice é válido
|
| 574 |
if idx < len(estado_s["testemunhas_autor_supostas_defs"]):
|
| 575 |
t_info = estado_s["testemunhas_autor_supostas_defs"][idx]
|
| 576 |
estado_s["testemunha_em_depoimento"] = {"nome": t_info["nome"], "pontos_chave": t_info["pontos_chave"], "parte": "AUTOR"}
|
| 577 |
+
fala_test_autor = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_adv_autor) # Testemunha responde à pergunta inicial do Adv. Autor
|
| 578 |
estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {t_info['nome']} (Autor - IA)", fala_test_autor)
|
| 579 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU, f"Contradite ou faça perguntas à testemunha {t_info['nome']} (Autor)."
|
| 580 |
+
else: # Caso raro de lógica inconsistente, trata como se não houvesse mais testemunhas
|
| 581 |
+
estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO # Ou alegações finais, conforme lógica acima
|
| 582 |
+
# ... (repetir lógica de transição para Réu ou Alegações)
|
| 583 |
+
|
| 584 |
elif fase_atual == FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU:
|
| 585 |
+
# Usuário (Adv. Réu) terminou de perguntar à testemunha do Autor.
|
| 586 |
estado_s["testemunha_em_depoimento"] = None
|
| 587 |
+
# Verificar se há mais testemunhas do Autor
|
|
|
|
|
|
|
| 588 |
if estado_s["testemunha_autor_atual_idx"] + 1 < len(estado_s["testemunhas_autor_supostas_defs"]):
|
| 589 |
+
estado_s["fase_aij"] = FASE_TESTEMUNHAS_AUTOR_INICIO # Volta para o juiz pedir ao Adv. Autor chamar a próxima
|
| 590 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Advogado do Réu encerrou perguntas à testemunha do Autor. Verificar próxima testemunha do Autor.")
|
| 591 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 592 |
# Adv Autor precisa ser chamado para agir
|
| 593 |
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv Autor chama/pergunta
|
| 594 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 595 |
if not ("Não tenho mais testemunhas" in fala_adv_autor or "Não arrolei testemunhas" in fala_adv_autor):
|
| 596 |
+
estado_s["testemunha_autor_atual_idx"] += 1
|
| 597 |
+
idx_new = estado_s["testemunha_autor_atual_idx"]
|
| 598 |
if idx_new < len(estado_s["testemunhas_autor_supostas_defs"]):
|
| 599 |
t_info_new = estado_s["testemunhas_autor_supostas_defs"][idx_new]
|
| 600 |
estado_s["testemunha_em_depoimento"] = {"nome": t_info_new["nome"], "pontos_chave": t_info_new["pontos_chave"], "parte": "AUTOR"}
|
| 601 |
fala_test_autor_new = gerar_resposta_testemunha_autor_ia(estado_s, pergunta_feita=fala_adv_autor)
|
| 602 |
estado_s = adicionar_fala_transcricao(estado_s, f"Testemunha {t_info_new['nome']} (Autor - IA)", fala_test_autor_new)
|
| 603 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_AUTOR_CONTRADITA_REU, f"Contradite ou faça perguntas à testemunha {t_info_new['nome']} (Autor)."
|
| 604 |
+
else: # Adv. Autor não tem mais, mesmo que houvesse na lista (raro)
|
| 605 |
+
if estado_s["testemunhas_reu_defs"]: estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_TESTEMUNHAS_REU_INICIO, "Selecione sua testemunha para chamar."
|
| 606 |
+
else: estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
|
| 607 |
+
fala_juiz_trans = gerar_resposta_juiz_ia(estado_s) # Juiz comanda nova fase
|
| 608 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_trans)
|
| 609 |
+
if estado_s["fase_aij"] == FASE_ALEGACOES_FINAIS_AUTOR:
|
| 610 |
+
fala_aleg_autor = gerar_resposta_advogado_autor_ia(estado_s)
|
| 611 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_aleg_autor)
|
| 612 |
+
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_ALEGACOES_FINAIS_REU, "Apresente suas Alegações Finais."
|
| 613 |
+
|
| 614 |
+
else: # Não há mais testemunhas do Autor
|
| 615 |
+
if estado_s["testemunhas_reu_defs"]:
|
| 616 |
+
estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO
|
| 617 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Encerrada oitiva das testemunhas do Autor. Iniciar oitiva das testemunhas do Réu.")
|
| 618 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 619 |
+
estado_s["instrucao_para_usuario"] = "Selecione sua testemunha para chamar."
|
| 620 |
+
else: # Sem testemunhas do Réu, vai para alegações finais
|
| 621 |
+
estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
|
| 622 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Instrução encerrada. Passar para alegações finais do Autor.")
|
| 623 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 624 |
+
fala_aleg_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv Autor faz alegações
|
| 625 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_aleg_autor)
|
| 626 |
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_ALEGACOES_FINAIS_REU, "Apresente suas Alegações Finais."
|
| 627 |
|
| 628 |
elif fase_atual in [FASE_TESTEMUNHAS_REU_PERGUNTAS_REU, FASE_TESTEMUNHAS_REU_INQUIRICAO_AUTOR]:
|
| 629 |
+
# Usuário (Adv. Réu) dispensou sua testemunha atual.
|
| 630 |
+
nome_test_dispensada = estado_s.get("testemunha_em_depoimento", {}).get("nome", "a testemunha do Réu")
|
| 631 |
estado_s["testemunha_em_depoimento"] = None
|
| 632 |
+
fala_juiz_dispensa = f"Juiz (IA): Dispensada {nome_test_dispensada}."
|
| 633 |
+
if estado_s.get("testemunha_em_depoimento"): # Adiciona só se havia uma testemunha em depoimento
|
| 634 |
+
fala_juiz_dispensa = gerar_resposta_juiz_ia(estado_s, acao_especifica=f"Dispensar {nome_test_dispensada}. Perguntar ao Adv. Réu se tem mais testemunhas.")
|
| 635 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz_dispensa)
|
| 636 |
+
|
| 637 |
+
|
| 638 |
+
if estado_s["testemunha_reu_atual_idx"] + 1 < len(estado_s["testemunhas_reu_defs"]):
|
| 639 |
+
estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_INICIO # Volta para o usuário selecionar a próxima
|
| 640 |
+
estado_s["instrucao_para_usuario"] = "Selecione sua próxima testemunha para chamar ou clique 'Juiz Avançar' para encerrar oitiva das suas testemunhas."
|
| 641 |
+
else: # Não há mais testemunhas do Réu
|
| 642 |
+
estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_AUTOR
|
| 643 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Encerrada oitiva das testemunhas do Réu. Passar para alegações finais do Autor.")
|
| 644 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 645 |
+
fala_adv_autor = gerar_resposta_advogado_autor_ia(estado_s) # Adv Autor faz alegações
|
| 646 |
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Autor (IA)", fala_adv_autor)
|
| 647 |
estado_s["fase_aij"], estado_s["instrucao_para_usuario"] = FASE_ALEGACOES_FINAIS_REU, "Apresente suas Alegações Finais."
|
| 648 |
+
|
| 649 |
elif fase_atual == FASE_ALEGACOES_FINAIS_AUTOR:
|
| 650 |
+
# Adv. Autor terminou alegações, Juiz passa palavra ao Réu
|
| 651 |
+
estado_s["fase_aij"] = FASE_ALEGACOES_FINAIS_REU
|
| 652 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s) # Juiz passa a palavra ao Réu
|
| 653 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 654 |
estado_s["instrucao_para_usuario"] = "Apresente suas Alegações Finais."
|
| 655 |
+
else: # Fallback para fases não explicitamente tratadas acima
|
| 656 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica="Conduza para a próxima etapa lógica da audiência.")
|
| 657 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 658 |
+
estado_s["instrucao_para_usuario"] = "Siga as instruções do Juiz ou avance a fase."
|
| 659 |
|
| 660 |
estado_s["feedback_para_usuario"] = analisar_atuacao_defesa_ia(estado_s)
|
| 661 |
+
gr.Info("Fase avançada. Interações da IA geradas.")
|
| 662 |
return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + mostrar_botoes_corretos(estado_s["fase_aij"])
|
| 663 |
|
| 664 |
def chamar_testemunha_reu_selecionada(estado_s, nome_testemunha_selecionada):
|
| 665 |
+
# (Função mantida como no Script 1 original)
|
| 666 |
estado_s = copy.deepcopy(estado_s)
|
| 667 |
if not nome_testemunha_selecionada:
|
| 668 |
+
estado_s["instrucao_para_usuario"] = "Nenhuma testemunha selecionada. Por favor, selecione uma testemunha da lista."
|
| 669 |
+
gr.Warning("Selecione uma testemunha da lista.")
|
| 670 |
return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + mostrar_botoes_corretos(estado_s["fase_aij"])
|
| 671 |
+
|
| 672 |
idx_testemunha = next((i for i, t in enumerate(estado_s["testemunhas_reu_defs"]) if t["nome"] == nome_testemunha_selecionada), -1)
|
| 673 |
if idx_testemunha == -1:
|
| 674 |
+
estado_s["instrucao_para_usuario"] = f"Testemunha '{nome_testemunha_selecionada}' não encontrada na configuração."
|
| 675 |
+
gr.Error(f"Testemunha '{nome_testemunha_selecionada}' não encontrada.")
|
| 676 |
return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + mostrar_botoes_corretos(estado_s["fase_aij"])
|
| 677 |
|
| 678 |
estado_s["testemunha_reu_atual_idx"] = idx_testemunha
|
| 679 |
testemunha_obj = estado_s["testemunhas_reu_defs"][idx_testemunha]
|
| 680 |
estado_s["testemunha_em_depoimento"] = {"nome": testemunha_obj["nome"], "pontos_chave": testemunha_obj["pontos_chave"], "parte": "REU"}
|
| 681 |
+
|
| 682 |
+
gr.Info(f"Chamando testemunha {testemunha_obj['nome']}. Aguarde IA...")
|
| 683 |
+
estado_s = adicionar_fala_transcricao(estado_s, "Advogado do Réu (Você)", f"Chamo para depor minha testemunha, Sr(a). {testemunha_obj['nome']}.")
|
| 684 |
+
fala_juiz = gerar_resposta_juiz_ia(estado_s, acao_especifica=f"Advogado do Réu chamou a testemunha {testemunha_obj['nome']}. Qualifique-a e passe a palavra ao Advogado do Réu para inquirição inicial.")
|
| 685 |
estado_s = adicionar_fala_transcricao(estado_s, "Juiz (IA)", fala_juiz)
|
| 686 |
+
estado_s["fase_aij"] = FASE_TESTEMUNHAS_REU_PERGUNTAS_REU
|
| 687 |
+
estado_s["instrucao_para_usuario"] = f"Faça sua primeira pergunta à sua testemunha, {testemunha_obj['nome']}. Após sua pergunta e a resposta (que você digitará no chat como se fosse a testemunha), o Advogado do Autor (IA) poderá inquirir."
|
| 688 |
estado_s["feedback_para_usuario"] = analisar_atuacao_defesa_ia(estado_s)
|
| 689 |
+
gr.Info("Testemunha chamada. Interações da IA geradas.")
|
| 690 |
return [estado_s, estado_s["transcricao_chat"], estado_s["feedback_para_usuario"], estado_s["instrucao_para_usuario"]] + mostrar_botoes_corretos(estado_s["fase_aij"])
|
| 691 |
|
| 692 |
+
# --- UI Callbacks para Novas Abas ---
|
| 693 |
+
def avaliar_argumentos_defesa_ia_ui(fatos_caso_atual, provas_reu_atual, tipo_argumento_selecionado, argumento_digitado):
|
| 694 |
+
if not GEMINI_API_KEY: return "ERRO: API Key não configurada."
|
| 695 |
+
if not argumento_digitado or not tipo_argumento_selecionado:
|
| 696 |
+
return "Por favor, selecione o tipo de argumento e digite seu texto."
|
| 697 |
+
gr.Info(f"Avaliando seu argumento ({tipo_argumento_selecionado})... Aguarde.")
|
| 698 |
+
feedback = avaliar_argumentos_defesa_ia(fatos_caso_atual, provas_reu_atual, tipo_argumento_selecionado, argumento_digitado)
|
| 699 |
+
gr.Info("Avaliação concluída.")
|
| 700 |
+
return feedback
|
| 701 |
+
|
| 702 |
+
_historico_treino_testemunha_atual = [] # Simples cache para o diálogo de treino
|
| 703 |
+
def gerar_dialogo_testemunha_defesa_para_treino_ui(fatos_caso_atual, testemunhas_reu_defs_atual_str, testemunha_selecionada_nome, pergunta_adv_defesa):
|
| 704 |
+
global _historico_treino_testemunha_atual
|
| 705 |
+
if not GEMINI_API_KEY:
|
| 706 |
+
return _historico_treino_testemunha_atual + [ (None, "ERRO: API Key não configurada.") ]
|
| 707 |
+
|
| 708 |
+
if not testemunha_selecionada_nome:
|
| 709 |
+
return _historico_treino_testemunha_atual + [ (None, "Por favor, selecione uma testemunha da sua lista na aba 'Configuração'.") ]
|
| 710 |
+
if not pergunta_adv_defesa:
|
| 711 |
+
return _historico_treino_testemunha_atual + [ (None, "Por favor, digite sua pergunta para a testemunha.") ]
|
| 712 |
+
|
| 713 |
+
# Recriar testemunhas_reu_defs a partir da string (se fornecida e mudou) ou usar a padrão
|
| 714 |
+
testemunhas_reu_defs_usar = []
|
| 715 |
+
if testemunhas_reu_defs_atual_str:
|
| 716 |
+
try:
|
| 717 |
+
# Re-parse a string de testemunhas do réu da aba de configuração
|
| 718 |
+
linhas = testemunhas_reu_defs_atual_str.strip().split('\n')
|
| 719 |
+
for linha in linhas:
|
| 720 |
+
if linha.strip():
|
| 721 |
+
partes = linha.split(':', 1)
|
| 722 |
+
if len(partes) == 2:
|
| 723 |
+
testemunhas_reu_defs_usar.append({"nome": partes[0].strip(), "pontos_chave": partes[1].strip()})
|
| 724 |
+
elif len(partes) == 1: # Nome sem pontos chave
|
| 725 |
+
testemunhas_reu_defs_usar.append({"nome": partes[0].strip(), "pontos_chave": "Não especificado."})
|
| 726 |
+
except Exception as e:
|
| 727 |
+
print(f"Erro ao parsear testemunhas_reu_defs_atual_str: {e}")
|
| 728 |
+
testemunhas_reu_defs_usar = TESTEMUNHAS_REU_PREDEFINIDAS # Fallback
|
| 729 |
+
else:
|
| 730 |
+
testemunhas_reu_defs_usar = TESTEMUNHAS_REU_PREDEFINIDAS
|
| 731 |
+
|
| 732 |
+
|
| 733 |
+
testemunha_obj = next((t for t in testemunhas_reu_defs_usar if t["nome"] == testemunha_selecionada_nome), None)
|
| 734 |
+
|
| 735 |
+
if not testemunha_obj:
|
| 736 |
+
# Se não achou na lista dinâmica, tenta na lista padrão
|
| 737 |
+
testemunha_obj = next((t for t in TESTEMUNHAS_REU_PREDEFINIDAS if t["nome"] == testemunha_selecionada_nome), None)
|
| 738 |
+
if not testemunha_obj:
|
| 739 |
+
return _historico_treino_testemunha_atual + [ (None, f"Testemunha '{testemunha_selecionada_nome}' não encontrada. Verifique a aba 'Configuração'.") ]
|
| 740 |
+
|
| 741 |
+
# Reinicia o histórico se a testemunha mudou (simplificado)
|
| 742 |
+
if not _historico_treino_testemunha_atual or \
|
| 743 |
+
(_historico_treino_testemunha_atual and not _historico_treino_testemunha_atual[0][1].startswith(f"**{testemunha_obj['nome']}**:")):
|
| 744 |
+
_historico_treino_testemunha_atual = []
|
| 745 |
+
_historico_treino_testemunha_atual.append( (None, f"Iniciando inquirição de **{testemunha_obj['nome']}**. Pontos chave: {testemunha_obj['pontos_chave']}") )
|
| 746 |
+
|
| 747 |
+
gr.Info(f"Gerando resposta da testemunha {testemunha_obj['nome']}... Aguarde.")
|
| 748 |
+
resposta_testemunha = gerar_resposta_testemunha_defesa_para_treino_ia(
|
| 749 |
+
fatos_caso_atual if fatos_caso_atual else CASO_FATOS_COMPLETO_PREDEFINIDO,
|
| 750 |
+
testemunha_obj['nome'],
|
| 751 |
+
testemunha_obj['pontos_chave'],
|
| 752 |
+
[(q,r) for q,r in _historico_treino_testemunha_atual if q is not None], # Passa apenas Q/A anteriores
|
| 753 |
+
pergunta_adv_defesa
|
| 754 |
+
)
|
| 755 |
+
_historico_treino_testemunha_atual.append( (pergunta_adv_defesa, resposta_testemunha) )
|
| 756 |
+
gr.Info("Resposta da testemunha gerada.")
|
| 757 |
+
return _historico_treino_testemunha_atual, "" # Retorna o histórico e limpa o campo de pergunta
|
| 758 |
+
|
| 759 |
+
|
| 760 |
+
# --- Interface Gráfica (Gradio UI) ---
|
| 761 |
+
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"), title="Simulador AIJ Interativo") as demo:
|
| 762 |
+
gr.Markdown("# ⚖️ Simulador Interativo de Audiência de Instrução e Julgamento (AIJ)")
|
| 763 |
+
gr.Markdown("Tema: **Direito ao Esquecimento vs. Liberdade de Imprensa**. Você assume o papel de **Advogado(a) do Réu (Jornal)**.")
|
| 764 |
+
if not GEMINI_API_KEY:
|
| 765 |
+
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.")
|
| 766 |
+
|
| 767 |
sim_state = gr.State(value=estado_inicial_simulacao())
|
| 768 |
|
| 769 |
with gr.Tabs() as abas_principais:
|
| 770 |
+
with gr.TabItem("1. Configuração do Caso", id=0):
|
| 771 |
+
gr.Markdown("## Detalhes do Caso para Simulação")
|
| 772 |
+
gr.Markdown("Preencha os campos abaixo ou use os botões para gerar/carregar um caso.")
|
| 773 |
+
with gr.Row():
|
| 774 |
+
btn_gerar_caso_ia = gr.Button("✨ Gerar Novo Caso com IA", icon="🧠", scale=1)
|
| 775 |
+
btn_carregar_caso_padrao = gr.Button("📄 Carregar Caso Padrão (Esquecimento)", icon="📜", scale=1)
|
| 776 |
with gr.Row():
|
| 777 |
with gr.Column(scale=2):
|
| 778 |
+
fatos_input = gr.Textbox(lines=7, label="Resumo dos Fatos, Partes e Título:", placeholder="Descreva o caso ou gere/carregue.")
|
| 779 |
+
provas_reu_input = gr.Textbox(lines=4, label="Argumentos e Provas do Réu (Seu Cliente - Jornal):", placeholder="Ex: Arg: Liberdade de imprensa. Prova: Art. 5 CF.")
|
| 780 |
+
provas_autor_input = gr.Textbox(lines=4, label="Argumentos e Provas (Supostas) do Autor:", placeholder="Ex: Arg: Dano à imagem. Prova: Laudo X.")
|
| 781 |
with gr.Column(scale=1):
|
| 782 |
+
testemunhas_reu_input = gr.Textbox(lines=5, label="Suas Testemunhas (Réu) - Formato: Nome: Pontos Chave a Depor", placeholder="João Silva: Viu X e Y.\nMaria Costa: Sabe Z.")
|
| 783 |
+
testemunhas_autor_supostas_input = gr.Textbox(lines=5, label="Supostas Testemunhas do Autor - Formato: Nome: Pontos Chave", placeholder="Carlos Lima: Sofreu Z.\nAna B.: Testemunhará sobre Q.")
|
| 784 |
+
btn_config_iniciar = gr.Button("💾 Salvar Configurações e Iniciar Simulação Interativa", variant="primary")
|
| 785 |
+
status_config_output = gr.Label(value="Aguardando configuração do caso...")
|
| 786 |
+
|
| 787 |
+
outputs_gerar_caso = [fatos_input, provas_reu_input, provas_autor_input, testemunhas_reu_input, testemunhas_autor_supostas_input, status_config_output]
|
| 788 |
+
btn_gerar_caso_ia.click(acao_gerar_caso_ficticio_ui, inputs=None, outputs=outputs_gerar_caso)
|
| 789 |
+
btn_carregar_caso_padrao.click(acao_carregar_caso_padrao_ui, inputs=None, outputs=outputs_gerar_caso)
|
| 790 |
+
|
| 791 |
+
with gr.TabItem("2. Audiência Interativa", id=1):
|
| 792 |
+
gr.Markdown("## Andamento da Audiência Simulada")
|
| 793 |
+
instrucao_usuario_output = gr.Markdown("Instrução: Configure o caso na aba 'Configuração' e clique em 'Salvar e Iniciar' para começar.")
|
| 794 |
+
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"))
|
| 795 |
+
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)
|
| 796 |
btn_enviar_fala_usuario = gr.Button("🎤 Enviar Fala / Ação", variant="stop")
|
| 797 |
+
|
| 798 |
+
with gr.Accordion("Ações Contextuais do Advogado do Réu (Você)", open=True):
|
| 799 |
+
with gr.Row():
|
| 800 |
+
btn_responder_conciliacao = gr.Button("Responder à Conciliação", visible=False)
|
| 801 |
+
dropdown_testemunhas_reu_select = gr.Dropdown(label="Sua Testemunha a Chamar:", choices=[], visible=False, interactive=True)
|
| 802 |
+
btn_chamar_testemunha_reu_action = gr.Button("Chamar Testemunha Selecionada", visible=False)
|
| 803 |
with gr.Row():
|
| 804 |
+
btn_perguntar_testemunha_autor_action = gr.Button("Perguntar à Test. do Autor", visible=False)
|
| 805 |
+
btn_adv_reu_pergunta_sua_testemunha_action = gr.Button("Perguntar à Minha Testemunha", visible=False)
|
| 806 |
+
btn_adv_reu_responde_pela_sua_testemunha_action = gr.Button("Responder pela Minha Testemunha (à IA)", visible=False)
|
| 807 |
+
btn_apresentar_alegacoes_finais_reu_action = gr.Button("Apresentar Alegações Finais", visible=False)
|
| 808 |
+
btn_juiz_avancar_fase_action = gr.Button("⚖️ Juiz (IA): Concluir Etapa / Avançar Fase", visible=False, variant="secondary")
|
|
|
|
|
|
|
|
|
|
| 809 |
lista_botoes_feedback = [btn_responder_conciliacao, btn_chamar_testemunha_reu_action, dropdown_testemunhas_reu_select, btn_perguntar_testemunha_autor_action, btn_adv_reu_pergunta_sua_testemunha_action, btn_adv_reu_responde_pela_sua_testemunha_action, btn_apresentar_alegacoes_finais_reu_action, btn_juiz_avancar_fase_action]
|
|
|
|
|
|
|
|
|
|
| 810 |
|
| 811 |
+
with gr.TabItem("3. Feedback da Atuação (Professor IA)", id=2):
|
| 812 |
+
gr.Markdown("## 💡 Análise da Sua Atuação na Audiência Interativa")
|
| 813 |
+
gr.Markdown("Este feedback é gerado pela IA com base na sua participação na aba 'Audiência Interativa'.")
|
| 814 |
+
feedback_output = gr.Textbox(lines=20, label="Feedback Detalhado:", interactive=False, show_copy_button=True)
|
| 815 |
|
| 816 |
+
with gr.TabItem("4. Treinamento de Argumentação (Defesa)", id=3):
|
| 817 |
+
gr.Markdown("## 🗣️ Pratique e Avalie Seus Argumentos (Advogado de Defesa)")
|
| 818 |
+
gr.Markdown("Use esta seção para redigir e obter feedback sobre argumentos específicos para o caso configurado.")
|
| 819 |
+
with gr.Row():
|
| 820 |
+
fatos_caso_treino_arg_display = gr.Textbox(label="Fatos do Caso (da Configuração):", value=CASO_FATOS_COMPLETO_PREDEFINIDO, lines=5, interactive=False) # Mostra fatos do caso padrão ou o configurado
|
| 821 |
+
provas_reu_treino_arg_display = gr.Textbox(label="Provas do Réu (da Configuração):", value=PROVAS_REU_TEXTO_PREDEFINIDO, lines=5, interactive=False)
|
| 822 |
+
tipo_argumento_treino = gr.Radio(
|
| 823 |
+
["Contestação (teses principais)", "Perguntas para Testemunha do Autor", "Perguntas para Testemunha do Réu", "Alegações Finais (memoriais)"],
|
| 824 |
+
label="Selecione o Tipo de Argumento/Peça para Treinar:", value="Alegações Finais (memoriais)"
|
| 825 |
+
)
|
| 826 |
+
argumento_input_treino = gr.Textbox(lines=10, label="Digite seu argumento aqui:", placeholder="Ex: 'Excelência, a matéria jornalística é um retrato fiel dos fatos públicos...'")
|
| 827 |
+
btn_avaliar_argumento_treino = gr.Button("🤖 Avaliar Argumento com IA", variant="primary")
|
| 828 |
+
avaliacao_output_treino = gr.Markdown(label="Feedback da IA sobre o Argumento:")
|
| 829 |
+
|
| 830 |
+
# Atualizar displays quando a configuração mudar
|
| 831 |
+
fatos_input.change(lambda x: x, inputs=fatos_input, outputs=fatos_caso_treino_arg_display)
|
| 832 |
+
provas_reu_input.change(lambda x: x, inputs=provas_reu_input, outputs=provas_reu_treino_arg_display)
|
| 833 |
+
|
| 834 |
+
btn_avaliar_argumento_treino.click(
|
| 835 |
+
avaliar_argumentos_defesa_ia_ui,
|
| 836 |
+
inputs=[fatos_caso_treino_arg_display, provas_reu_treino_arg_display, tipo_argumento_treino, argumento_input_treino],
|
| 837 |
+
outputs=avaliacao_output_treino
|
| 838 |
+
)
|
| 839 |
+
|
| 840 |
+
with gr.TabItem("5. Preparar Testemunhas (Defesa)", id=4):
|
| 841 |
+
gr.Markdown("## 🎙️ Simule a Inquirição das Suas Testemunhas (Defesa)")
|
| 842 |
+
gr.Markdown("Pratique como você (Advogado de Defesa) inquiriria suas próprias testemunhas. A IA responderá como a testemunha selecionada.")
|
| 843 |
+
fatos_caso_treino_test_display = gr.Textbox(label="Fatos do Caso (da Configuração):", value=CASO_FATOS_COMPLETO_PREDEFINIDO, lines=5, interactive=False)
|
| 844 |
+
testemunhas_reu_config_treino_display = gr.Textbox(label="Definição das Testemunhas do Réu (da Configuração):", value=TESTEMUNHAS_REU_TEXTO_PREDEFINIDO, lines=3, interactive=False)
|
| 845 |
+
|
| 846 |
+
# Atualizar displays quando a configuração mudar
|
| 847 |
+
fatos_input.change(lambda x: x, inputs=fatos_input, outputs=fatos_caso_treino_test_display)
|
| 848 |
+
testemunhas_reu_input.change(lambda x: x, inputs=testemunhas_reu_input, outputs=testemunhas_reu_config_treino_display)
|
| 849 |
+
|
| 850 |
+
# Dropdown para selecionar testemunha do réu para treino
|
| 851 |
+
dropdown_testemunhas_reu_treino = gr.Dropdown(label="Selecione Sua Testemunha para Inquirir:", choices=[t['nome'] for t in TESTEMUNHAS_REU_PREDEFINIDAS], interactive=True)
|
| 852 |
+
# Atualizar choices do dropdown quando testemunhas_reu_input mudar
|
| 853 |
+
def update_dropdown_treino_choices(t_reu_str):
|
| 854 |
+
nomes = []
|
| 855 |
+
if t_reu_str and t_reu_str.strip():
|
| 856 |
+
for linha in t_reu_str.strip().split('\n'):
|
| 857 |
+
if linha.strip():
|
| 858 |
+
partes = linha.split(':', 1)
|
| 859 |
+
nomes.append(partes[0].strip())
|
| 860 |
+
return gr.Dropdown(choices=nomes if nomes else [t['nome'] for t in TESTEMUNHAS_REU_PREDEFINIDAS], value=nomes[0] if nomes else None)
|
| 861 |
+
testemunhas_reu_input.change(update_dropdown_treino_choices, inputs=testemunhas_reu_input, outputs=dropdown_testemunhas_reu_treino)
|
| 862 |
+
|
| 863 |
+
|
| 864 |
+
chat_treino_testemunha = 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"))
|
| 865 |
+
pergunta_testemunha_treino_input = gr.Textbox(label="Sua Pergunta para a Testemunha:", placeholder="Ex: 'Senhor Silva, poderia descrever o procedimento editorial?'")
|
| 866 |
+
btn_perguntar_testemunha_treino = gr.Button("💬 Perguntar à Testemunha (IA)", variant="primary")
|
| 867 |
+
btn_limpar_chat_treino_testemunha = gr.Button("🗑️ Limpar Chat de Treino")
|
| 868 |
+
|
| 869 |
+
def limpar_chat_treino():
|
| 870 |
+
global _historico_treino_testemunha_atual
|
| 871 |
+
_historico_treino_testemunha_atual = []
|
| 872 |
+
return [], ""
|
| 873 |
+
btn_limpar_chat_treino_testemunha.click(limpar_chat_treino, outputs=[chat_treino_testemunha, pergunta_testemunha_treino_input])
|
| 874 |
+
|
| 875 |
+
btn_perguntar_testemunha_treino.click(
|
| 876 |
+
gerar_dialogo_testemunha_defesa_para_treino_ui,
|
| 877 |
+
inputs=[fatos_caso_treino_test_display, testemunhas_reu_config_treino_display, dropdown_testemunhas_reu_treino, pergunta_testemunha_treino_input],
|
| 878 |
+
outputs=[chat_treino_testemunha, pergunta_testemunha_treino_input] # Limpa input após envio
|
| 879 |
+
)
|
| 880 |
+
|
| 881 |
+
|
| 882 |
+
with gr.TabItem("ℹ️ Ajuda / Sobre o Caso Padrão", id=5):
|
| 883 |
+
gr.Markdown("## Sobre o Caso Padrão: Direito ao Esquecimento vs. Liberdade de Imprensa")
|
| 884 |
+
gr.Markdown(f"**Título:** {CASO_TITULO_PREDEFINIDO}")
|
| 885 |
+
gr.Markdown(f"**Partes:**\n{CASO_PARTES_PREDEFINIDO.replace('\n', '\n\n')}")
|
| 886 |
+
gr.Markdown(f"**Resumo do Caso:**\n{CASO_DESCRICAO_PREDEFINIDO}")
|
| 887 |
+
with gr.Accordion("Argumentos Principais do Autor (Caso Padrão)", open=False):
|
| 888 |
+
gr.Markdown("\n".join([f"- {arg}" for arg in ARGUMENTOS_AUTOR_PREDEFINIDOS]))
|
| 889 |
+
with gr.Accordion("Argumentos Principais do Réu/Jornal (Caso Padrão)", open=False):
|
| 890 |
+
gr.Markdown("\n".join([f"- {arg}" for arg in CONTRA_ARGUMENTOS_REU_PREDEFINIDOS]))
|
| 891 |
+
with gr.Accordion("Testemunhas do Réu/Jornal (Caso Padrão)", open=False):
|
| 892 |
+
gr.Markdown("\n".join([f"- **{t['nome']}**: {t['pontos_chave']}" for t in TESTEMUNHAS_REU_PREDEFINIDAS]))
|
| 893 |
+
|
| 894 |
+
gr.Markdown("### Legislação e Precedentes Relevantes (Geral)")
|
| 895 |
+
with gr.Row():
|
| 896 |
+
with gr.Column():
|
| 897 |
+
gr.Markdown("**Potencialmente Favoráveis ao Réu (Jornal):**")
|
| 898 |
+
gr.Markdown("\n".join([f"- {lei}" for lei in LEGISLACAO_PRECEDENTES_PREDEFINIDO["favoraveis_ao_reu"]]))
|
| 899 |
+
with gr.Column():
|
| 900 |
+
gr.Markdown("**Potencialmente Favoráveis ao Autor:**")
|
| 901 |
+
gr.Markdown("\n".join([f"- {lei}" for lei in LEGISLACAO_PRECEDENTES_PREDEFINIDO["favoraveis_ao_autor"]]))
|
| 902 |
+
gr.Markdown("""
|
| 903 |
+
## Como utilizar este simulador:
|
| 904 |
+
1. **Configuração (Aba 1):**
|
| 905 |
+
* **Gerar Novo Caso com IA:** Cria um caso fictício aleatório sobre o tema.
|
| 906 |
+
* **Carregar Caso Padrão:** Preenche os campos com o "Caso da Reportagem Revisitada".
|
| 907 |
+
* Ou preencha manualmente os detalhes do seu próprio caso.
|
| 908 |
+
* **Salve e Inicie:** Fundamental para começar a simulação interativa.
|
| 909 |
+
2. **Audiência Interativa (Aba 2):**
|
| 910 |
+
* O núcleo da simulação. Siga as instruções e interaja como Advogado(a) do Réu.
|
| 911 |
+
* Use o campo de texto para suas falas ou os botões de ação contextual.
|
| 912 |
+
* O "Juiz (IA): Avançar Fase" é usado para progredir quando você conclui sua parte em uma etapa ou quando a IA indica.
|
| 913 |
+
3. **Feedback da Atuação (Aba 3):**
|
| 914 |
+
* Após interagir na Aba 2, verifique aqui a análise da IA sobre sua performance.
|
| 915 |
+
4. **Treinamento de Argumentação (Aba 4):**
|
| 916 |
+
* 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.
|
| 917 |
+
5. **Preparar Testemunhas (Aba 5):**
|
| 918 |
+
* 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.
|
| 919 |
+
## Dicas para Atuação como Advogado(a) do Réu (Jornal):
|
| 920 |
+
* **Liberdade de Imprensa:** Seu principal argumento. Fundamente com a Constituição.
|
| 921 |
+
* **Interesse Público:** Demonstre a relevância da matéria.
|
| 922 |
+
* **Veracidade dos Fatos:** Crucial. A matéria deve ser factualmente correta.
|
| 923 |
+
* **Ausência de Dolo/Culpa:** Argumente que não houve intenção de prejudicar, apenas informar.
|
| 924 |
+
* **Menção à Absolvição:** Se o autor foi absolvido e a matéria menciona isso, é um ponto forte para a defesa.
|
| 925 |
+
* **Precedentes (STF):** Cite o RE 1.010.606, que ponderou o direito ao esquecimento com a liberdade de informação.
|
| 926 |
+
* **Contraditório:** Explore as perguntas às testemunhas do Autor para enfraquecer a tese dele.
|
| 927 |
+
* **Suas Testemunhas:** Prepare-as para reforçar a tese da defesa.
|
| 928 |
+
""")
|
| 929 |
+
|
| 930 |
+
# --- Conexões dos Componentes da UI (Event Handlers) ---
|
| 931 |
outputs_config = [sim_state, chat_aij_output, feedback_output, instrucao_usuario_output, dropdown_testemunhas_reu_select] + lista_botoes_feedback
|
| 932 |
+
btn_config_iniciar.click(
|
| 933 |
+
configurar_e_iniciar_simulacao,
|
| 934 |
+
inputs=[sim_state, fatos_input, provas_reu_input, provas_autor_input, testemunhas_reu_input, testemunhas_autor_supostas_input],
|
| 935 |
+
outputs=outputs_config
|
| 936 |
+
).then(lambda: gr.Textbox(value=""), outputs=[fala_usuario_input] # Limpa o campo de fala
|
| 937 |
+
).then(lambda: gr.Tabs(selected=1), outputs=[abas_principais]) # Muda para aba Audiência
|
| 938 |
|
| 939 |
outputs_fala_usuario = [sim_state, chat_aij_output, feedback_output, instrucao_usuario_output, fala_usuario_input] + lista_botoes_feedback
|
| 940 |
btn_enviar_fala_usuario.click(lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario)
|
| 941 |
fala_usuario_input.submit(lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario)
|
| 942 |
+
|
| 943 |
outputs_acao_juiz = [sim_state, chat_aij_output, feedback_output, instrucao_usuario_output] + lista_botoes_feedback
|
| 944 |
btn_juiz_avancar_fase_action.click(acao_botao_juiz_avancar, inputs=[sim_state], outputs=outputs_acao_juiz).then(lambda: gr.Textbox(value=""), outputs=[fala_usuario_input])
|
| 945 |
btn_chamar_testemunha_reu_action.click(chamar_testemunha_reu_selecionada, inputs=[sim_state, dropdown_testemunhas_reu_select], outputs=outputs_acao_juiz).then(lambda: gr.Textbox(value=""), outputs=[fala_usuario_input])
|
| 946 |
|
| 947 |
+
# Links dos botões de ação específicos para lidar_com_fala_usuario (eles apenas enviam o texto do botão como "fala")
|
| 948 |
+
# Estes botões agora estão mais para indicar o contexto da fala do usuário no input principal.
|
| 949 |
+
# A lógica de o que fazer com a fala do usuário está centralizada em `lidar_com_fala_usuario`.
|
| 950 |
+
# Se o botão for para uma ação específica que não envolve fala direta, ele precisa de seu próprio handler.
|
| 951 |
+
# Ex: Responder conciliação, apresentar alegações finais - podem usar o `lidar_com_fala_usuario` se o usuário digitar no campo.
|
| 952 |
+
# Se forem "ações puras" sem texto, podem precisar de lógica adaptada ou de um `fala_usuario_txt` especial.
|
| 953 |
+
# Para simplificar, vamos assumir que o usuário digita a resposta no campo de texto principal após clicar nesses botões (que agora servem mais como lembretes visuais).
|
| 954 |
+
# A alternativa seria esses botões passarem um placeholder de texto para `lidar_com_fala_usuario`.
|
| 955 |
+
# Por exemplo, btn_responder_conciliacao.click(lambda s: lidar_com_fala_usuario(s, "Réu se manifesta sobre conciliação (detalhes no campo de texto)."), ...)
|
| 956 |
+
# Mas a implementação atual já faz o `lidar_com_fala_usuario` receber o texto do `fala_usuario_input`.
|
| 957 |
+
|
| 958 |
+
# Botões que enviam a fala do input principal
|
| 959 |
+
btn_responder_conciliacao.click(lambda: gr.Info("Digite sua resposta à conciliação no campo de fala e envie."), inputs=[], outputs=[]).then(
|
| 960 |
+
lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario
|
| 961 |
+
)
|
| 962 |
+
btn_perguntar_testemunha_autor_action.click(lambda: gr.Info("Digite sua pergunta à testemunha do Autor no campo de fala e envie."), inputs=[], outputs=[]).then(
|
| 963 |
+
lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario
|
| 964 |
+
)
|
| 965 |
+
btn_adv_reu_pergunta_sua_testemunha_action.click(lambda: gr.Info("Digite sua pergunta à sua testemunha no campo de fala e envie. Você também digitará a RESPOSTA dela em seguida."), inputs=[], outputs=[]).then(
|
| 966 |
+
lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario
|
| 967 |
+
)
|
| 968 |
+
btn_adv_reu_responde_pela_sua_testemunha_action.click(lambda: gr.Info("Digite a resposta da sua testemunha (à pergunta do Adv. Autor) no campo de fala e envie."), inputs=[], outputs=[]).then(
|
| 969 |
+
lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario
|
| 970 |
+
)
|
| 971 |
+
btn_apresentar_alegacoes_finais_reu_action.click(lambda: gr.Info("Digite suas alegações finais no campo de fala e envie."), inputs=[], outputs=[]).then(
|
| 972 |
+
lidar_com_fala_usuario, inputs=[sim_state, fala_usuario_input], outputs=outputs_fala_usuario
|
| 973 |
+
)
|
| 974 |
+
|
| 975 |
+
# Estado inicial da UI no carregamento
|
| 976 |
+
def setup_initial_ui_state_load(s):
|
| 977 |
+
initial_fase = s["fase_aij"]
|
| 978 |
+
dropdown_choices = [t["nome"] for t in s.get("testemunhas_reu_defs", [])] if s.get("testemunhas_reu_defs") else []
|
| 979 |
+
return [gr.Dropdown(choices=dropdown_choices, value=None, interactive=True)] + mostrar_botoes_corretos(initial_fase)
|
| 980 |
+
|
| 981 |
+
demo.load(
|
| 982 |
+
lambda s: (s, s["transcricao_chat"], s["feedback_para_usuario"], s["instrucao_para_usuario"]) + tuple(setup_initial_ui_state_load(s)),
|
| 983 |
+
inputs=[sim_state],
|
| 984 |
+
outputs=[sim_state, chat_aij_output, feedback_output, instrucao_usuario_output, dropdown_testemunhas_reu_select] + lista_botoes_feedback
|
| 985 |
+
)
|
| 986 |
|
| 987 |
if __name__ == "__main__":
|
| 988 |
if not GEMINI_API_KEY:
|
|
|
|
| 991 |
print("Para rodar localmente, edite o script e insira sua chave ou defina a variável de ambiente.")
|
| 992 |
print("Para Hugging Face Spaces, configure o Secret 'GEMINI_API_KEY'.")
|
| 993 |
print("#####################################################################")
|
| 994 |
+
demo.queue(max_size=20).launch(debug=False) # Adicionado max_size para melhor gerenciamento de fila.
|