Adicionar src-py/renatoxsr/scripts/avaliar_dataset.py
This commit is contained in:
@@ -0,0 +1,143 @@
|
|||||||
|
#vim: ts=4 sw=4 et ft=python :
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# --- CONFIGURAÇÕES ---
|
||||||
|
OLLAMA_URL = "http://192.168.14.20:11434/api/generate"
|
||||||
|
MODEL_NAME = "gemma4:e4b"
|
||||||
|
INPUT_FILE_PATH = Path("dataset.jsonl")
|
||||||
|
OUTPUT_FILE_PATH = Path("avaliado.jsonl")
|
||||||
|
|
||||||
|
# O System Prompt que criamos, definido como a regra mestra.
|
||||||
|
SYSTEM_PROMPT = """
|
||||||
|
Você é um Assistente Jurídico Sênior e especialista em Direito brasileiro. Sua função é realizar uma análise técnica, crítica e altamente estruturada de documentos jurídicos. Você deve manter o tom de voz de um profissional qualificado, objetivo e conciso.
|
||||||
|
|
||||||
|
SEU OBJETIVO: Analisar o documento jurídico fornecido e extrair quatro informações cruciais.
|
||||||
|
|
||||||
|
REGRAS OBRIGATÓRIAS:
|
||||||
|
1. Tom: O tom de todas as respostas deve ser técnico, formal e imparcial.
|
||||||
|
2. Formato: A saída deve ser ESTREITAMENTE um objeto JSON válido. Nenhum texto introdutório, explicação ou texto fora do JSON é permitido.
|
||||||
|
3. Detalhe: Mantenha a clareza e a profundidade técnica em todos os campos.
|
||||||
|
|
||||||
|
AS CHAVES E AS REGRAS DE CADA CAMPO:
|
||||||
|
|
||||||
|
(1) `tipo`: Deve identificar a categoria jurídica principal do documento (ex: Contrato de Prestação de Serviços, Petição Inicial, Escritura Pública, Contrato de Compra e Venda, Procuração Ad Judicia). Seja o mais específico possível.
|
||||||
|
(2) `resumo`: Um resumo executivo do objeto do documento, contendo no máximo 3 frases. Deve ser extremamente conciso, focado no tema central.
|
||||||
|
(3) `argumentos`: Lista em formato de array (JSON array) dos principais pontos jurídicos, premissas ou teses argumentativas que sustentam o documento.
|
||||||
|
(4) `qualidade`: Avaliação da qualidade do documento sob o ponto de vista técnico-jurídico. Você deve escolher *somente* um dos seguintes termos: "ótimo", "bom" ou "médio".
|
||||||
|
* "Ótimo": Documento juridicamente impecável, claro, completo e em conformidade com a melhor prática do direito.
|
||||||
|
* "Bom": Documento funcional, com clareza e cobertura dos pontos principais, mas pode ter pequenas imprecisões ou omissões.
|
||||||
|
* "Médio": Documento que apresenta falhas significativas de linguagem, inconsistências jurídicas graves ou que não cumpre seu propósito principal sem intervenção.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def get_llm_response(prompt_full: str) -> str:
|
||||||
|
"""
|
||||||
|
Envia o prompt para o Ollama local e retorna a resposta em string.
|
||||||
|
"""
|
||||||
|
print("🤖 Enviando requisição para o Ollama...")
|
||||||
|
try:
|
||||||
|
payload = {
|
||||||
|
"model": MODEL_NAME,
|
||||||
|
"prompt": prompt_full,
|
||||||
|
"options": {
|
||||||
|
"temperature": 0.1, # Temperatura baixa para respostas determinísticas e factuais
|
||||||
|
"num_predict": 2048 # Aumenta o limite de tokens
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(OLLAMA_URL, json=payload)
|
||||||
|
response.raise_for_status() # Levanta exceção para códigos de erro HTTP
|
||||||
|
|
||||||
|
# O Ollama retorna os resultados dentro do campo 'response'
|
||||||
|
return response.json()['response'].strip()
|
||||||
|
|
||||||
|
except requests.exceptions.ConnectionError:
|
||||||
|
print("\n" + "="*80)
|
||||||
|
print(f"❌ ERRO DE CONEXÃO: Não foi possível conectar ao Ollama em {OLLAMA_URL}.")
|
||||||
|
print("Por favor, verifique se o serviço Ollama está rodando e se a porta e o IP estão corretos.")
|
||||||
|
print("="*80 + "\n")
|
||||||
|
return None
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
print(f"\n❌ ERRO GERAL ao comunicar com a API: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def run_evaluation_cycle():
|
||||||
|
"""
|
||||||
|
Processa o arquivo e executa a análise para cada documento.
|
||||||
|
"""
|
||||||
|
if not INPUT_FILE_PATH.exists():
|
||||||
|
print(f"ERRO: Arquivo de entrada '{INPUT_FILE_PATH.name}' não encontrado. Execute o passo anterior primeiro.")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Iniciando a avaliação de {INPUT_FILE_PATH.name} contra o modelo {MODEL_NAME}...")
|
||||||
|
|
||||||
|
results = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(INPUT_FILE_PATH, 'r', encoding='utf-8') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro ao ler o arquivo: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
try:
|
||||||
|
data = json.loads(line.strip())
|
||||||
|
markdown_content = data.get("markdown", "")
|
||||||
|
|
||||||
|
if not markdown_content:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 1. Montar o Prompt Completo
|
||||||
|
full_prompt = f"""
|
||||||
|
DOCUMENTO JURÍDICO PARA ANÁLISE:
|
||||||
|
---
|
||||||
|
{markdown_content}
|
||||||
|
---
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 2. Adicionar o prompt ao System Prompt
|
||||||
|
final_prompt = f"{SYSTEM_PROMPT}\n\n{full_prompt}"
|
||||||
|
|
||||||
|
# 3. Chamar o LLM
|
||||||
|
llm_output = get_llm_response(final_prompt)
|
||||||
|
|
||||||
|
# 4. Estruturar e Salvar Resultados
|
||||||
|
if llm_output:
|
||||||
|
result_record = {
|
||||||
|
"hash": data.get("hash", "unknown_id"),
|
||||||
|
"documento_original": markdown_content[:200] + "...", # Trunca para melhor visualização
|
||||||
|
"resultado_ollama": llm_output
|
||||||
|
}
|
||||||
|
results.append(result_record)
|
||||||
|
print(f"[{i+1}/{len(lines)}] ✅ Processado com sucesso. Salvando resultado.")
|
||||||
|
else:
|
||||||
|
results.append({
|
||||||
|
"hash": data.get("hash", "unknown_id"),
|
||||||
|
"documento_original": markdown_content[:200] + "...",
|
||||||
|
"resultado_ollama": "FALHA: Verifique os logs de erro acima."
|
||||||
|
})
|
||||||
|
print(f"[{i+1}/{len(lines)}] ❌ FALHA no processamento.")
|
||||||
|
|
||||||
|
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print(f"AVISO: Linha {i+1} inválida JSON encontrada e pulada.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERRO inesperado ao processar a linha {i+1}: {e}")
|
||||||
|
|
||||||
|
# Salvando todos os resultados
|
||||||
|
if results:
|
||||||
|
with open(OUTPUT_FILE_PATH, 'w', encoding='utf-8') as f:
|
||||||
|
for record in results:
|
||||||
|
f.write(json.dumps(record, ensure_ascii=False) + '\n')
|
||||||
|
print("\n=======================================================================")
|
||||||
|
print("✅ Avaliação concluída!")
|
||||||
|
print(f"Total de documentos processados e salvos em: {OUTPUT_FILE_PATH.name}")
|
||||||
|
print("Examine este arquivo para identificar padrões de erro ou sucesso.")
|
||||||
|
print("=======================================================================")
|
||||||
|
|
||||||
|
# Executar o ciclo completo
|
||||||
|
run_evaluation_cycle()
|
||||||
Reference in New Issue
Block a user