lex-rag-builder
Scannednpx machina-cli add skill fbmoulin/lex-intelligentia-skills/lex-rag-builder --openclawLex 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
| Modelo | Dimensões | Custo | Qualidade Jurídica BR | Recomendação |
|---|---|---|---|---|
text-embedding-3-large (OpenAI) | 3072 | Alto | ⭐⭐⭐⭐ | Produção |
text-embedding-3-small (OpenAI) | 1536 | Médio | ⭐⭐⭐ | Dev/Testes |
intfloat/multilingual-e5-large | 1024 | Grátis | ⭐⭐⭐ | Self-hosted |
neuralmind/bert-large-portuguese-cased | 1024 | Grátis | ⭐⭐⭐⭐ | PT-BR nativo |
voyageai/voyage-law-2 | 1024 | Mé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
- Step 1: Defina fontes, tipos de doc e metadados a coletar (tribunal, data, área).
- Step 2: Escolha a estratégia de chunking e um modelo de embedding jurídico PT-BR.
- 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.