Triagem de Contratos — risco jurídico com RAG e nota auditável

Lê um contrato de qualquer tamanho, aponta multa abusiva e cláusula ilegal com a transcrição literal do trecho, e devolve um nível de risco calculado por política escrita em arquivo — nunca pelo modelo de linguagem. Serve para decidir quais contratos merecem leitura humana, com a conta da nota aberta na tela e a fundamentação citada.

Python 3.13FastAPIRAGSQLiteGeminiClaudeDockerpytestmypy strict

O que resolve

Numa carteira de contratos, o trabalho caro não é escrever o parecer — é descobrir quais contratos merecem um. Um contrato comercial de quinze cláusulas leva de vinte a quarenta minutos de leitura atenta para alguém poder dizer "este tem multa fora da curva", e a maior parte desses minutos é gasta em documentos que não tinham nada de errado. Só que isso só se descobre depois de ler.

Quando o volume aperta, para-se de ler tudo e passa-se a ler uma amostra — o que é assinar sem ler, com um nome mais confortável.

Este sistema faz a triagem: lê o contrato inteiro, aponta multa abusiva e cláusula ilegal com a transcrição literal do trecho, e devolve BAIXO, MEDIO ou ALTO. Ele não substitui o advogado; ele decide a ordem da fila dele.

A decisão que sustenta o resto

A nota nunca é decidida pelo modelo de linguagem. O modelo encontra fatos e cita o trecho; uma política determinística escrita em YAML converte apontamentos em nota e nível. Duas consequências práticas:

  • mesma entrada, mesma nota, em qualquer provedor — trocar de modelo não move a régua;
  • a nota é auditável. A tela mostra cada parcela e a soma, e a soma tem que dar o número do topo. Se não der, o laudo está errado e quem lê descobre sem confiar em ninguém.

As barreiras contra alucinação

  • Citação conferida contra o documento. Todo apontamento carrega o trecho literal, e o trecho é procurado no original antes de entrar no laudo. Não achou, o apontamento é descartado — e a trilha de auditoria diz quantos caíram e por quê.
  • Recuperação híbrida. Para cada cláusula, a base de referência é consultada por similaridade de cosseno e por categoria disparada por gatilho determinístico. Só similaridade não bastava, e isso foi medido: uma cláusula que diz "multa de 15%" não compartilha palavra nenhuma com um texto sobre "cláusula penal", e o trecho pertinente ficava três centésimos abaixo do piso de corte.
  • Fallback determinístico. Se a API falhar, demorar ou responder fora do formato, um motor de regras assume e o laudo sai marcado para conferência humana. A fila nunca para, e o laudo nunca esconde de onde veio.

O defeito que o projeto encontrou em si mesmo

A tela que inspeciona a recuperação mostra, para cada cláusula, os trechos mais próximos — incluindo os que ficaram abaixo do piso, com a linha do corte desenhada. Foi ela que expôs o pior defeito: um contrato de risco médio saía como baixo porque o único trecho capaz de sustentar o apontamento perdeu o corte por 0,03. O modelo tinha obedecido à regra de não afirmar sem fonte; a busca é que não entregou o material.

Um inspetor que mostrasse apenas o que passou pareceria saudável. É por isso que ele mostra o descarte: o defeito de um sistema de RAG quase nunca está no que ele usou, e quase sempre no que ele não recuperou.

Avaliação como porta de CI

Teste unitário não pega perda de qualidade. Um piso ajustado, um peso alterado ou uma expressão mais estreita passam por 168 testes verdes e ainda assim fazem um contrato médio sair como baixo.

Então existe uma segunda porta: um gabarito com contratos de resultado conhecido, e uma métrica que reprova o build se qualquer caso for rebaixado de nível. BAIXO é o único nível que não pede conferência humana — rebaixar significa que ninguém vai olhar. Errar para mais é ruim e é seguro; errar para menos, não.

Essa avaliação encontrou dois defeitos na primeira execução, incluindo um em que a tabela de métricas mostrava precisão 1,00 atribuída ao modelo quando o resultado tinha vindo do motor de regras.

Como é por dentro

Python 3.13 com FastAPI. Banco vetorial escrito à mão sobre SQLite, sem serviço de embedding externo — o que torna a busca auditável linha por linha e, ao mesmo tempo, cega a sinônimo, o que foi exatamente o que exigiu a busca híbrida. Provedores de LLM (Anthropic e Google) atrás de um Protocol de um método só: acrescentar um provedor é um arquivo novo e três linhas na fábrica.

A interface não tem etapa de build, dependência externa nem CDN: HTML, CSS e JavaScript servidos como estão, com Content-Security-Policy sem unsafe-inline. Ela também não conhece regra de domínio — não calcula nota, não tem lista de categorias, não tem limite de faixa. Um teste lê os arquivos entregues ao navegador e falha se um nome de categoria aparecer escrito neles.

Análise assíncrona porque uma chamada real ao Gemini levou 82 segundos neste projeto: o envio devolve 202 com um identificador e o navegador consulta o estado.

Como é construído

Quatro disciplinas, e elas moldaram o código em vez de decorá-lo:

  • First-Context — arquitetura, padrão de nome e vocabulário do domínio vivem em Markdown, lidos antes de qualquer alteração.
  • SDD — as especificações são a fonte da verdade sobre dados. O mesmo schema JSON restringe a geração no servidor e valida a resposta no cliente.
  • BDD — a regra de negócio está em cenários Gherkin em português, cada um com teste correspondente.
  • Regras anti-alucinação — afirmação sem fonte é proibida, e a proibição é verificada em teste, não confiada ao prompt.

168 testes, ruff e mypy --strict limpos, CI em Python 3.12 e 3.13. O verificador de tipos, quando entrou, encontrou cinco defeitos reais — não anotações faltando.

Onde está

No ar em triagem.useadimplo.com.br, em contêiner, atrás do mesmo proxy que serve os outros projetos da máquina. Sem cadastro e sem chave de API: três contratos de exemplo esperam um clique, e cada botão mostra o nível esperado — dá para conferir se o sistema acertou sem ler o documento.

Comece pelo exemplo de risco médio: ele tem cláusulas propositalmente no limite legal, que não devem ser apontadas. Apontar tudo é fácil; o teste é não apontar o que está correto.

Honestidade sobre o estágio

É uma demonstração de engenharia, não um produto jurídico. A base de referência é material sintético, escrito para a demonstração e não revisado por advogado — ela não é a legislação brasileira. A instância pública roda sem chave de API de propósito: instância aberta com chave minha é conta que qualquer visitante gasta.

E o que falta está escrito no repositório em vez de omitido: não há registro de tokens nem de custo por análise (a contagem existe no código e não é gravada), os lotes de cláusula são chamados em sequência, e o histórico de análises vive em memória.