Retrieval Systems · Natural Language Processing

Building High-Precision RAG Pipelines for Portuguese & Angolan Legal Corpora

Key Takeaway: Naive fixed-token chunking destroys the logical structure of civil-law statutes, separating general obligations from their exceptions in subsequent paragraphs (números and alíneas). To achieve production reliability in platforms like LGT-AO, retrieval pipelines must respect hierarchical statutory boundaries, combine lexical BM25 with multilingual dense embeddings, and enforce post-generation quote verification.

1. Why standard RAG fails on civil-law legislation

Most off-the-shelf Retrieval-Augmented Generation (RAG) tutorials split documents into arbitrary 500-token windows with a 50-token overlap. While acceptable for unstructured blog posts, fixed-window splitting is catastrophic when applied to civil-law codes in Angola, Portugal, or Brazil — such as the Angolan General Labour Law (Lei Geral do Trabalho, Lei n.º 12/23).

In Lusophone legislative drafting, legal meaning is encoded hierarchically across Capítulos (Chapters), Secções (Sections), Artigos (Articles), Números (numbered paragraphs), and Alíneas (lettered sub-clauses). Consider a typical statutory pattern:

  • Paragraph 1 (n.º 1) states the general rule (e.g., the standard maximum duration of a fixed-term employment contract).
  • Paragraph 2 (n.º 2) introduces a critical exception for specific economic sectors or temporary project replacements.
  • Paragraph 3 (n.º 3) specifies the mandatory written notice period required before expiry, cross-referencing a separate article on compensation.

If a 500-token splitter cuts between Paragraph 1 and Paragraph 2, and a user asks whether a contract can be renewed beyond the baseline period, vector similarity may retrieve only Paragraph 1. The language model then confidently answers with the general rule while omitting the legally decisive exception in Paragraph 2. In legal compliance, an incomplete truth is indistinguishable from an error.

2. Hierarchical AST parsing for Portuguese statutes

To prevent context fragmentation, TICNES AI builds deterministic legislative parsers that convert raw official gazette publications (Diário da República) into an Abstract Syntax Tree (AST) before any embedding model is called.

Every indexed document unit corresponds to a complete Artigo (or, for unusually long articles exceeding 1,200 tokens, individual Números that always carry the parent article’s header and Paragraph 1 prepended as immutable context). Each chunk is enriched with a canonical metadata envelope:

{
  "doc_id": "AO-LEI-12-2023",
  "jurisdiction": "AO",
  "statute_title": "Lei Geral do Trabalho (Lei n.º 12/23, de 27 de Dezembro)",
  "chapter": "Capítulo IV — Duração e Organização do Tempo de Trabalho",
  "section": "Secção II — Trabalho Extraordinário",
  "article_number": "Artigo 158.º",
  "article_epigraph": "Limites e remuneração do trabalho extraordinário",
  "cross_references": ["Artigo 156.º", "Artigo 159.º"],
  "effective_from": "2024-03-26",
  "status": "in_force"
}

Before computing dense vector embeddings, we prepend the full hierarchical breadcrumb (`Lei n.º 12/23 > Capítulo IV > Secção II > Artigo 158.º (Limites e remuneração do trabalho extraordinário)`) directly into the text string fed to the embedding encoder. This guarantees that even a short clause like “O limite previsto no número anterior pode ser elevado...” retains its exact subject-matter anchor in vector space.

3. Hybrid retrieval: Reciprocal Rank Fusion of BM25 and dense embeddings

Users query legal systems in two fundamentally different ways. Human resources specialists and lawyers often search by exact statutory identifiers or technical terms (“Artigo 214.º”, “despedimento disciplinar nulidade”, “período experimental 180 dias”). Workers and small-business owners, by contrast, describe everyday situations in colloquial Portuguese (“Fui mandado embora sem aviso depois de dois anos, o que tenho direito a receber?”).

Dense vector embeddings excel at the second case (semantic bridging between everyday language and formal statutory terminology) but frequently underperform on exact article numbers or rare statutory acronyms. Conversely, lexical search (BM25 with Portuguese stemming and diacritic normalisation) nails exact article numbers and legal terms of art.

Our retrieval pipeline executes both searches in parallel and merges the candidate sets using Reciprocal Rank Fusion (RRF), followed by a multilingual cross-encoder reranker:

Pipeline Stage Mechanism Candidate Pool Primary Strength
Stage 1A: Lexical BM25 + Portuguese morphological analyser Top 40 chunks Exact article numbers, dates, statutory terms
Stage 1B: Semantic Multilingual dense embeddings (HNSW index) Top 40 chunks Colloquial phrasing → legal concept mapping
Stage 2: Fusion & Graph Expansion Reciprocal Rank Fusion + 1-hop `cross_references` expansion Top 25 unique articles Pulls in referenced exception clauses automatically
Stage 3: Cross-Encoder Rerank Fine-tuned Portuguese legal cross-encoder Top 6 articles passed to LLM High-precision relevance scoring across query-passage pairs

4. Resolving statutory cross-references via knowledge graphs

Notice Stage 2 in the table above: 1-hop cross-reference expansion. Statutory articles rarely stand alone. When Article 208 states that compensation is calculated “nos termos do artigo 239.º”, retrieving Article 208 without Article 239 leaves the synthesis model unable to compute the answer.

During AST ingestion, our regular-expression and dependency-parsing extractors build a directed graph of every intra-statute reference (`cross_references`). Whenever a primary article ranks in the top 10 of our RRF fusion step, the retrieval engine automatically fetches its direct 1-hop referenced articles and injects them into the cross-encoder candidate pool. In internal benchmarks on Angolan labour law queries, adding 1-hop statutory graph expansion increased multi-article answer completeness from `74.2%` to `96.8%`.

5. Deterministic quote verification and refusal policies

Even with high-recall retrieval, a generative model must never be trusted to quote the law from parametric memory. In our legal and compliance pipelines, the generation step produces a structured response containing two distinct fields for every cited rule:

  1. `verbatim_quote`: An exact substring copied from the retrieved `Artigo` text.
  2. `plain_language_explanation`: A clear explanation of what the obligation means in practice, written in accessible Portuguese or English.

Before the response is rendered to the user, a deterministic post-processor checks that `verbatim_quote` (normalised for whitespace) appears as an exact substring inside the retrieved source chunks for that request. If the substring check fails — indicating that the model paraphrased inside quotation marks or hallucinated an article number — the response is rejected and regenerated with strict constraints. And if the user asks a question that falls outside the indexed statutory corpus (for example, tax law when querying a labour-law assistant), the system executes a clean, explicit refusal rather than speculating.

About the Authors — TICNES AI Legal Engineering & NLP Group

This article documents the retrieval architecture powering LGT-AO and enterprise document intelligence systems built by TICNES, Lda. For custom RAG audits or private document indexing, contact our engineers.