Get the FREE Ultimate OpenClaw Setup Guide →

lex-rag-builder

Scanned
npx machina-cli add skill fbmoulin/lex-intelligentia-skills/lex-rag-builder --openclaw
Files (1)
SKILL.md
11.2 KB

Lex RAG Builder — Pipelines RAG para Direito Brasileiro

Por que RAG Jurídico Precisa de Estratégia Específica

O RAG genérico falha com documentos jurídicos porque:

  • Acórdãos têm estrutura específica (relatório, voto, ementa)
  • Legislação tem hierarquia (CF > LC > Lei Ordinária > Decreto)
  • A precisão de citação é crítica (número, data, relator)
  • Termos jurídicos são polissêmicos (posse ≠ posse em direitos reais)
  • Contexto temporal muda tudo (lei vigente vs. lei revogada)

Arquitetura RAG Jurídica

INGESTÃO
├── Fontes → (PDF, HTML, API tribunais)
├── Extração → (OCR, parsing, limpeza)
├── Metadados → (tipo, tribunal, data, área)
├── Chunking → (estratégia por tipo de doc)
└── Embedding → (modelo especializado em PT-BR jurídico)
        │
        ▼
VECTOR STORE
├── Índices por área (civil, penal, consumidor...)
├── Filtros de metadados (tribunal, período, tipo)
└── Hierarquia de fontes (vinculante > persuasivo)
        │
        ▼
RETRIEVAL
├── Query reformulation (expansão de termos jurídicos)
├── Hybrid search (semântico + BM25 para jargão)
├── Re-ranking (por relevância jurídica + temporalidade)
└── Context compression (resumo dos trechos relevantes)
        │
        ▼
GENERATION
├── System prompt com persona jurídica
├── Instrução anti-alucinação
└── Formatação de citações (ABNT)

Estratégias de Chunking por Tipo de Documento

Acórdãos do STJ/STF

def chunk_acordao(texto: str) -> list[dict]:
    """
    Estratégia: Chunk por seção estrutural do acórdão
    Preserva: EMENTA | RELATÓRIO | VOTO | ACÓRDÃO como chunks separados
    """
    secoes = {
        "EMENTA": r"EMENTA[\s\S]*?(?=RELATÓRIO|ACÓRDÃO|VOTO)",
        "RELATORIO": r"RELATÓRIO[\s\S]*?(?=VOTO|O EXMO)",
        "VOTO": r"VOTO[\s\S]*?(?=ACÓRDÃO|DECISÃO:|Ante o exposto)",
        "DISPOSITIVO": r"(?:Ante o exposto|ACÓRDÃO)[\s\S]*$"
    }
    
    chunks = []
    for nome_secao, pattern in secoes.items():
        match = re.search(pattern, texto, re.IGNORECASE)
        if match:
            chunks.append({
                "content": match.group(0),
                "metadata": {
                    "secao": nome_secao,
                    "tipo": "acordao",
                    "length": len(match.group(0))
                }
            })
    return chunks

Legislação (Artigos de Lei)

def chunk_lei(texto: str, lei_metadata: dict) -> list[dict]:
    """
    Estratégia: Chunk por artigo, preservando caput + incisos + parágrafos juntos
    Não separar artigo do caput, incisos e parágrafos relacionados
    """
    artigos = re.split(r'(?=\bArt\.\s*\d+)', texto)
    
    chunks = []
    for artigo in artigos:
        if artigo.strip():
            num_artigo = re.search(r'Art\.\s*(\d+)', artigo)
            chunks.append({
                "content": artigo.strip(),
                "metadata": {
                    **lei_metadata,
                    "artigo": num_artigo.group(1) if num_artigo else None,
                    "tipo": "legislacao"
                }
            })
    return chunks

Súmulas e Teses Repetitivas

def chunk_sumulas(texto: str, tribunal: str) -> list[dict]:
    """
    Estratégia: Chunk por súmula individual (número + enunciado)
    Tamanho pequeno mas contexto rico em metadata
    """
    sumulas = re.split(r'(?=Súmula\s+\d+|SÚMULA\s+N[Oº]+\s*\d+)', texto)
    
    chunks = []
    for sumula in sumulas:
        if sumula.strip():
            numero = re.search(r'(?:Súmula|SÚMULA)\s+[Nº]*\s*(\d+)', sumula)
            chunks.append({
                "content": sumula.strip(),
                "metadata": {
                    "tipo": "sumula",
                    "tribunal": tribunal,
                    "numero": int(numero.group(1)) if numero else None,
                    "vinculante": tribunal == "STF" and "VINCULANTE" in sumula.upper()
                }
            })
    return chunks

Configuração do Vector Store

Opção 1: Qdrant (Self-hosted ou Cloud)

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct

def setup_qdrant_juridico(client: QdrantClient):
    """
    Coleções separadas por área para controle granular de retrieval
    """
    colecoes = [
        ("jurisprudencia_stj", 1536),   # OpenAI embeddings
        ("jurisprudencia_stf", 1536),
        ("jurisprudencia_tjes", 1536),
        ("legislacao_federal", 1536),
        ("legislacao_estadual", 1536),
        ("doutrina_civil", 1536),
        ("sumulas", 1536),
    ]
    
    for nome, dimensao in colecoes:
        client.create_collection(
            collection_name=nome,
            vectors_config=VectorParams(
                size=dimensao,
                distance=Distance.COSINE
            )
        )

Opção 2: Supabase pgvector (Recomendado para integração n8n)

-- Extensão
CREATE EXTENSION IF NOT EXISTS vector;

-- Tabela principal de documentos jurídicos
CREATE TABLE documentos_juridicos (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    conteudo TEXT NOT NULL,
    embedding VECTOR(1536),
    
    -- Metadados jurídicos
    tipo VARCHAR(50),          -- 'acordao' | 'sumula' | 'lei' | 'doutrina'
    tribunal VARCHAR(20),      -- 'STJ' | 'STF' | 'TJES' | null
    area_direito VARCHAR(50),  -- 'civil' | 'consumidor' | 'processual'
    numero_referencia TEXT,    -- número do processo, artigo, súmula
    data_publicacao DATE,
    vigente BOOLEAN DEFAULT true,
    
    -- Hierarquia (para ranking)
    peso_hierarquia SMALLINT DEFAULT 5,  -- 10=STF vinculante, 1=doutrina
    
    created_at TIMESTAMP DEFAULT NOW()
);

-- Índice para busca vetorial
CREATE INDEX ON documentos_juridicos USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);

-- Índice para filtros comuns
CREATE INDEX idx_tipo ON documentos_juridicos(tipo);
CREATE INDEX idx_tribunal ON documentos_juridicos(tribunal);
CREATE INDEX idx_area ON documentos_juridicos(area_direito);

Modelos de Embedding para PT-BR Jurídico

Ranking por Adequação ao Direito Brasileiro

ModeloDimensõesCustoQualidade Jurídica BRRecomendação
text-embedding-3-large (OpenAI)3072Alto⭐⭐⭐⭐Produção
text-embedding-3-small (OpenAI)1536Médio⭐⭐⭐Dev/Testes
intfloat/multilingual-e5-large1024Grátis⭐⭐⭐Self-hosted
neuralmind/bert-large-portuguese-cased1024Grátis⭐⭐⭐⭐PT-BR nativo
voyageai/voyage-law-21024Médio⭐⭐⭐⭐⭐Especializado jurídico

Recomendação para Lex Intelligentia:

  • Produção: voyage-law-2 (especializado em documentos jurídicos)
  • Fallback: text-embedding-3-large (mais disponível)

Query Reformulation para Buscas Jurídicas

EXPANSION_DICT = {
    # Termos comuns → termos jurídicos precisos
    "cobrar juros abusivos": ["juros remuneratórios abusivos", "capitalização mensal", 
                               "Súmula 382 STJ", "taxa média mercado BACEN"],
    "processo por acidente": ["responsabilidade civil extracontratual", "nexo causal",
                               "dano material", "dano moral", "art. 186 CC"],
    "reclamar produto com defeito": ["vício do produto", "art. 18 CDC", 
                                      "responsabilidade solidária", "prazo decadencial 90 dias"],
    "reintegração de posse": ["art. 561 CPC", "posse anterior", "esbulho", 
                               "periculum in mora possessório"],
}

def expand_query_juridica(query: str) -> list[str]:
    """
    Expande query do usuário com termos técnicos equivalentes
    para melhorar recall da busca semântica
    """
    queries_expandidas = [query]
    for termo_comum, expansoes in EXPANSION_DICT.items():
        if termo_comum.lower() in query.lower():
            queries_expandidas.extend(expansoes)
    return queries_expandidas

Avaliação de Qualidade do RAG

Métricas Específicas para RAG Jurídico

def avaliar_rag_juridico(qa_pairs: list[dict]) -> dict:
    """
    Métricas:
    - Precisão: O chunk recuperado realmente responde a pergunta?
    - Recall: Todos os chunks relevantes foram recuperados?
    - Faithfulness: A resposta gerada é fiel aos chunks recuperados?
    - Citação Válida: As citações (número, data, relator) estão corretas?
    """
    metricas = {
        "precisao": [],
        "recall": [],
        "faithfulness": [],
        "citacoes_validas": []
    }
    
    for par in qa_pairs:
        # Avaliar via Claude como juiz
        # ...
        pass
    
    return {
        "precisao_media": sum(metricas["precisao"]) / len(metricas["precisao"]),
        "recall_medio": sum(metricas["recall"]) / len(metricas["recall"]),
        "faithfulness_media": sum(metricas["faithfulness"]) / len(metricas["faithfulness"]),
        "citacoes_validas_pct": sum(metricas["citacoes_validas"]) / len(metricas["citacoes_validas"])
    }

Sistema Prompt para Geração com RAG Jurídico

Você é um assistente jurídico especializado em Direito Brasileiro.

REGRAS DE OURO:
1. Use APENAS as informações dos documentos fornecidos como contexto.
2. Se a informação não estiver no contexto, diga "não encontrei informação 
   suficiente nos documentos disponíveis".
3. Cite SEMPRE a fonte (tribunal, número, data) para cada afirmação jurídica.
4. Nunca invente números de processo, datas ou nomes de relatores.
5. Indique o grau de hierarquia da fonte (vinculante > persuasivo).

CONTEXTO RECUPERADO:
{context}

PERGUNTA:
{query}

RESPOSTA (com citações):

Integração com n8n — Workflow RAG

{
  "name": "Lex RAG - Consulta Jurídica",
  "nodes": [
    {"name": "Receber Pergunta", "type": "webhook"},
    {"name": "Reformular Query", "type": "code"},
    {"name": "Buscar no Vector Store", "type": "supabase"},
    {"name": "Re-rank por Hierarquia", "type": "code"},
    {"name": "Gerar Resposta", "type": "anthropic"},
    {"name": "Validar Citações", "type": "anthropic"},
    {"name": "Retornar Resposta", "type": "respond-to-webhook"}
  ]
}

Source

git clone https://github.com/fbmoulin/lex-intelligentia-skills/blob/main/skills/automacao/lex-rag-builder/SKILL.mdView on GitHub

Overview

Permite construir bases de conhecimento jurídicas usando RAG, com chunking específico para acordãos e legislação brasileira. Integra estratégias de embedding legal PT-BR, pipelines de ingestão (jurisprudência, legislação e doutrina) e gestão de vector stores como Pinecone, Qdrant, pgvector e Chroma, otimizando retrieval para perguntas jurídicas.

How This Skill Works

Primeiro, ingere fontes (PDF/HTML/API), extrai metadados e aplica chunking adequado ao tipo de documento. Em seguida, gera embeddings com modelo jurídico PT-BR e armazena em vector stores com filtros por área, tribunal e data. No retrieval, usa reformulação de consulta, busca semântica híbrida, re-ranking e compressão de contexto, com suporte a LlamaIndex e LangChain, antes de passar o conteúdo para geração.

When to Use It

  • Quando precisa construir uma base de conhecimento jurídico para IA ou um sistema de IA jurídica.
  • Para configurar busca semântica em documentos legais, incluindo acordãos, legislação e doutrina.
  • Ao criar um pipeline de ingestão de acórdãos e legislação para alimentar seu motor de busca.
  • Para avaliar a qualidade do retrieval, incluindo relevância, precisão de citações e atualidade temporal.
  • Para otimizar chunking e a base vetorial de decisões judiciais ou construir a base vetorial da plataforma Lex Intelligentia.

Quick Start

  1. Step 1: Defina fontes, tipos de doc e metadados a coletar (tribunal, data, área).
  2. Step 2: Escolha a estratégia de chunking e um modelo de embedding jurídico PT-BR.
  3. Step 3: Configure vetor store (Pinecone, Qdrant, pgvector, Chroma) e execute a ingestão.

Best Practices

  • Defina fontes e metadados de forma padronizada e mantenha um esquema claro de ABNT para citações.
  • Escolha um embedding jurídico PT-BR adequado e mantenha modelos atualizados com atualizações legais.
  • Projete o chunking por tipo de documento (acordao, lei) preservando estrutura como ementa, relatorio e voto.
  • Mantenha filtros de metadados (tribunal, periodo, tipo) e uma hierarquia de fontes para a trilha de evidência.
  • Teste sistematicamente a qualidade do retrieval com métricas de relevância e temporalidade, e valide citações.

Example Use Cases

  • Construção de uma base de conhecimento para a plataforma Lex Intelligentia com busca semântica de acórdãos STF/STJ.
  • Ingestão de legislação para uma agência pública brasileira com retrieval por tópico e datas.
  • Sistema de busca de jurisprudência com formatação ABNT automática de citações.
  • Avaliação de qualidade de retrieval para decisões judiciais, com foco em precisão de citação e atualidade.
  • Base vetorial por área do direito (civil, penal, trabalhista) para suporte a consultoria jurídica.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers