diff --git a/src-py/renatoxsr/scripts/avaliar_dataset.py b/src-py/renatoxsr/scripts/avaliar_dataset.py new file mode 100644 index 0000000..5f021da --- /dev/null +++ b/src-py/renatoxsr/scripts/avaliar_dataset.py @@ -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() \ No newline at end of file