produtos

DocVision: extração estruturada de contratos longos, em segundos

Como o DocVision lê contratos longos e devolve JSON estruturado com as cláusulas críticas — a arquitetura schema-first, o retry direcionado e as limitações honestas.

Por Alexandre Brandao12 de maio de 20269 min leitura

TL;DR — O DocVision foi feito para um problema chato: contratos longos que alguém precisa ler de ponta a ponta antes de assinar. Em vez de substituir essa leitura, ele faz a primeira passada: recebe o PDF e devolve um JSON estruturado com as cláusulas que normalmente importam — partes, prazo, multas, rescisão, garantias, reajuste. A ideia é trocar "ler procurando" por "ler validando". Neste post mostramos como funciona por dentro, com um exemplo ilustrativo, e onde ele ainda erra.

O problema que ele ataca

Imagine um time jurídico enxuto — duas advogadas e uma estagiária — responsável por uma carteira grande de contratos de fornecedores. Boa parte do tempo vai embora só em leitura: revisão antes de assinatura, identificação de cláusulas críticas, monitoramento de vencimentos.

O pior caso costuma ser contrato longo de fornecimento de matéria-prima: tipicamente 40-60 páginas, com cláusulas penais espalhadas, índices de reajuste em anexos e condições de rescisão dependentes de tabelas em apêndice. Uma leitura completa pode levar horas — e, mesmo assim, é fácil uma cláusula crítica passar batido.

É exatamente esse tipo de documento que o DocVision tenta destrinchar.

Um exemplo ilustrativo

Para tornar concreto, considere um contrato hipotético de fornecimento de malte com:

  • 4 partes assinantes (cervejaria + 2 maltarias + interveniente bancário)
  • Vigência de 36 meses com renovação automática
  • 8 cláusulas penais distintas (atraso de entrega, qualidade fora de spec, default em pagamento, descumprimento de NDA, etc.)
  • Reajuste anual por IGPM com piso e teto
  • Garantia bancária de 15% do volume anual
  • Foro: comarca de Campinas

O fluxo de uso é simples: abrir app.yourai.com.br/portal/tools/docvision e arrastar o PDF.

O que acontece por dentro

O DocVision faz três passes, sendo dois deles em paralelo.

Pass 1: classificação

Um Gemini Flash determina o tipo de documento primeiro. Isso decide qual schema de extração usar. No exemplo acima: contrato.fornecimento.materia_prima.

const tipo = await classify(pdfText.slice(0, 4000), {
  options: [
    "contrato.fornecimento.materia_prima",
    "contrato.distribuicao",
    "contrato.servico",
    "nf",
    "boleto",
    "memorando",
    // ...
  ],
});

Por que isso importa? Porque cada tipo tem um schema customizado. Um contrato de fornecimento tem campos diferentes de um contrato de distribuição. Tentar extrair tudo com um schema genérico produz JSON cheio de campos null.

Pass 2: extração estruturada

Aqui entra o Gemini Pro. Ele recebe o PDF completo + um schema Zod estrito + um prompt curto:

const schema = z.object({
  partes: z.array(z.object({
    nome: z.string(),
    cnpj: z.string().optional(),
    papel: z.enum(["fornecedor", "comprador", "interveniente"]),
  })),
  vigencia: z.object({
    inicio: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
    fim: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
    renovacao_automatica: z.boolean(),
  }),
  clausulas_penais: z.array(z.object({
    gatilho: z.string(),
    valor_brl: z.number().optional(),
    valor_percentual: z.number().optional(),
    referencia_clausula: z.string(),
  })),
  reajuste: z.object({
    indice: z.enum(["IGPM", "IPCA", "INCC", "outro"]),
    periodicidade: z.string(),
    piso_percentual: z.number().optional(),
    teto_percentual: z.number().optional(),
  }).optional(),
  // ... mais 15 campos
});

O Gemini retorna o JSON, o backend valida contra o Zod, e se algum campo falhar, dispara um segundo pass focado só naquele campo. Esse retry direcionado tende a melhorar a acurácia em relação a uma única passada, ao custo de alguns tokens a mais.

Pass 3: extração de tabelas e anexos

Em paralelo ao Pass 2, outro fluxo lê tabelas estruturadas (preços por mês, tabelas de reajuste, anexos com valores). Usa Gemini Vision com prompt específico para tabelas, retorna CSV, e o backend faz join com o JSON principal por referência cruzada.

No contrato do exemplo, é esse passe que pegaria:

  • Tabela de preços de malte Pilsen por mês (Anexo II)
  • Tabela de penalidades escalonadas por número de dias de atraso (Cláusula 8.3)
  • Cronograma de entregas trimestrais (Apêndice A)

Como interpretar o resultado

Ao final, a tela mostra o JSON estruturado, campo a campo. Na prática, o resultado não vem perfeito — e o produto foi desenhado partindo dessa premissa.

Campos "duros" (partes, CNPJs, vigência, foro, valores principais) tendem a sair bem. Onde a coisa fica delicada é em redação ambígua ou condicional: cláusulas do tipo "reajuste por IGPM, ou IPCA-15 se mais favorável ao fornecedor", riders que qualificam uma garantia ("15% do volume líquido projetado"), ou uma referência de cláusula trocada. São justamente esses pontos que o revisor humano precisa olhar.

Por isso o ganho não é "ele lê por você". É: o sistema entrega um mapa do contrato e aponta onde olhar primeiro — você deixa de procurar e passa a validar.

Como isso muda o workflow

O DocVision não substitui o advogado. Ele substitui a primeira leitura linear. Um fluxo realista fica mais ou menos assim:

  1. DocVision processa o contrato e devolve o JSON estruturado
  2. Um humano valida o JSON, focando nos campos críticos
  3. Cláusulas marcadas como "atenção" (linguagem ambígua, valores fora do range esperado) entram numa lista de revisão
  4. O advogado lê integralmente só as páginas sinalizadas

O potencial de ganho é grande — em vez de ler 50 páginas do zero, você valida um resumo estruturado e lê a fundo só os pontos marcados. Quanto isso economiza na prática depende muito do tipo de contrato e do nível de revisão exigido; trate qualquer número como estimativa, não como garantia.

Por que essa abordagem

Três decisões técnicas sustentam o resultado:

1. Schema-first, não free-form. O LLM não decide o que extrair — o schema Zod decide. Isso reduz drift entre extrações e dá garantias de tipo para o sistema downstream.

2. Retry direcionado em vez de pipeline gigante. Se o JSON falha em um campo, o sistema faz uma segunda chamada focada só naquele campo, com mais contexto. Custa mais tokens, mas tende a recuperar acurácia onde a passada única falha.

3. Confidence labeling automático. O DocVision marca cada campo com um nível de confiança (alta, média, baixa). Campos de baixa confiança vão direto para a lista de revisão humana, em vez de se misturarem aos demais como se fossem certeza.

Limitações honestas

Não está perfeito, e os casos abaixo derrubam a qualidade:

  • Contratos manuscritos ou com scan de qualidade ruim: a acurácia cai bastante. Recomendamos OCR + revisão antes.
  • Cláusulas com referências cruzadas para anexos externos ("conforme tabela acordada por e-mail entre as partes"): o sistema sinaliza, mas não consegue resolver.
  • Português jurídico muito arcaico: contratos antigos perdem nuances; em escrituras de décadas atrás a qualidade despenca.
  • Cláusulas penais com fórmulas complexas (ex.: "multa será o maior valor entre 10% do contrato e 3x o valor da última fatura"): captura a fórmula, mas pode errar a interpretação.

Para qualquer um desses casos, o sistema avisa antes de processar.

Quer testar com um documento seu?

Se você tem 30 minutos e um contrato (ou qualquer documento estruturado: NF, boleto, memorando), agende uma demo. A gente roda ao vivo, com seu doc real, e você sai com o JSON estruturado em mãos para validar.

E se quiser entender melhor a tecnologia por trás, leia como construímos um data lakehouse Medallion — o DocVision nasceu lá, como parte do pipeline de NFs digitalizadas.

DocVision
Document AI
Produto
Demo