Jurídico 10 semanas

Base de conhecimento semântica para escritório de advocacia

A busca por palavra-chave sobre 40 mil documentos internos (acórdãos, contratos, pareceres) produzia resultados irrelevantes, fazendo advogados gastarem horas procurando precedentes que sabiam que existiam.

Cliente identificado como "Escritório de Advocacia" por acordo de confidencialidade.

0 precisão nas buscas internas (antes: 31%)
0 tempo médio de pesquisa (antes: 3,5 horas)
0 documentos indexados semanticamente
0 do levantamento ao deploy em produção

O desafio

O escritório acumulou, ao longo de 15 anos, uma base densa de conhecimento: acórdãos de tribunais superiores, pareceres internos, contratos modelo, jurisprudência comentada, e decisões administrativas. Tudo em PDF, Word ou e-mail convertido em PDF.

O sistema de busca era um full-text search sobre índice Elasticsearch mal configurado. O problema não era técnico - era conceitual. Busca por palavra-chave encontra o documento onde a palavra aparece; busca semântica encontra o documento onde o conceito está presente, independentemente da palavra exata usada.

Um exemplo concreto: uma advogada pesquisava “responsabilidade solidária em contratos de prestação de serviço com terceiros” e o sistema retornava documentos que continham todas essas palavras, mas não necessariamente juntas ou com o sentido correto. O precedente relevante, que usava “obrigação conjunta” em vez de “responsabilidade solidária”, não aparecia nos primeiros 50 resultados.

O resultado prático: advogados pesquisavam no Google antes de pesquisar no sistema interno, ou chamavam colegas seniores para perguntar “você lembra de um caso parecido?”.

Três características do acervo tornavam o projeto não trivial:

  1. Heterogeneidade de formato: PDFs escaneados com qualidade variável, documentos em DOCX com formatação complexa, e-mails encadeados exportados como PDF, documentos com colunas múltiplas.

  2. Vocabulário especializado: embedding models genéricos performam mal em jurídico brasileiro, que mistura latim, termos técnicos e variações regionais de nomenclatura.

  3. Granularidade de busca: em documentos longos (acórdãos podem ter 80 páginas), o chunk relevante pode ser um parágrafo específico, não o documento inteiro.

A solução

Pipeline de ingestão

A ingestão foi a fase mais longa do projeto (semanas 1 a 4). Cada documento passa por:

  1. Extração de texto: PyMuPDF para PDFs nativos; Tesseract com pré-processamento de imagem para PDFs escaneados; python-docx para Word. Documentos com qualidade de OCR abaixo de 85% entram numa fila de revisão manual.

  2. Limpeza e normalização: remoção de headers/footers repetidos, normalização de quebras de linha, detecção e correção de erros comuns de OCR em vocabulário jurídico (lista de 200+ correções específicas do domínio).

  3. Chunking hierárquico: em vez de chunk fixo por caractere, o pipeline identifica a estrutura do documento (seções, subseções, considerandos, dispositivos) e cria chunks que respeitam fronteiras semânticas. Chunks de 512 tokens com overlap de 64.

  4. Metadata extraction: Claude 3.5 Haiku extrai metadados estruturados de cada documento: tipo, tribunal/origem, data, partes envolvidas, assunto principal. Esses metadados alimentam filtros na interface de busca.

  5. Embedding e indexação: text-embedding-3-large (OpenAI) com dimensionalidade reduzida para 1536. Armazenado no pgvector com índice HNSW para busca aproximada eficiente.

Estratégia de retrieval

A busca usa um pipeline de dois estágios:

Stage 1 - Retrieval: a consulta do usuário é embedded e buscamos os 20 chunks mais similares por cosine similarity, com filtros opcionais de tipo de documento, tribunal e período.

Stage 2 - Reranking com contexto: os 20 chunks recuperados são enviados ao Claude 3.5 com a pergunta original. O modelo seleciona os 5 mais relevantes e explica brevemente por que cada um é pertinente à consulta. Esse reranking elimina falsos positivos de similaridade vetorial pura.

O resultado exibido para o advogado: o trecho relevante com contexto, o documento de origem, e uma frase de explicação da relevância.

class SearchResult(BaseModel):
    chunk_text: str
    document_title: str
    document_date: date
    document_type: str
    relevance_explanation: str
    similarity_score: float
    page_number: int | None

Interface

A interface é uma aplicação Next.js simples: campo de busca em linguagem natural, filtros de metadados, e os resultados com destaque do trecho relevante e link para abrir o documento completo. Sem gamificação, sem painel de analytics - só busca.

O projeto deliberadamente não incluiu um chat sobre os documentos (RAG conversacional). O escritório queria busca, não um assistente que poderia alucinar sobre jurisprudência. A limitação foi uma escolha de produto.

Resultados

A métrica de precisão foi aferida por um painel de 6 advogados que avaliaram 200 consultas representativas do uso real, comparando os resultados do sistema novo com o Elasticsearch antigo. Precisão definida como: “pelo menos um dos 5 primeiros resultados é diretamente relevante para a consulta.”

A melhora de 31% para 89% foi consistente entre especialidades - tributário, trabalhista e societário performaram de forma similar.

O ganho de tempo de 3,5 horas para 20 minutos não é universal: consultas simples já eram rápidas no sistema antigo. O ganho real está nas consultas complexas, que agora têm um ponto de partida concreto em vez de um buraco negro.

O maior feedback qualitativo dos advogados: “agora eu confio que se não apareceu nos resultados, provavelmente não está na base - antes eu nunca tinha certeza disso.”

Stack técnica

pgvectorPostgreSQLClaude 3.5PythonFastAPINext.jstext-embedding-3-large

Próximo passo

Problema parecido no seu caso?

Fazemos um diagnóstico gratuito de 30 minutos: mapeamos o problema, estimamos viabilidade técnica e damos uma direção concreta.

Falar com a equipe