Como treinar LLM em português europeu com o Arquivo.pt

Como treinar LLM em português europeu com o Arquivo.pt

O problema do português “brasileiro demais” nos LLMs — e por que o Arquivo.pt importa

Treinei, ajustei e quebrei modelos em produção nos últimos anos. O que mais frustra um dev português a trabalhar com IA generativa não é alucinação, nem latência — é o modelo a falar de “ônibus”, “celular” e “trem” quando o meu cliente fala de “autocarro”, “telemóvel” e “comboio”. Segundo o Sapo.pt, este problema tem nome técnico e solução nacional: o Arquivo.pt, com mais de 2TB indexados e suporte para vários LLMs, foi a base da IA Amália, “alimentada” com 5,8 mil milhões de tokens de dados portugueses.

Na minha experiência, qualquer equipa em Portugal que tente construir um assistente, um RAG ou um chatbot para clientes lusos esbarra na mesma parede: os datasets públicos são, na sua esmagadora maioria, brasileiros. E isso não é detalhe cosmético — quebra terminologia, expressões idiomáticas e contexto cultural.

Por que o português do Brasil domina (e o que isso custa)

O português do Brasil representa mais de 80% dos falantes nativos. Consequência direta: a maior parte do conteúdo web, dos dumps da CommonCrawl e dos corpora abertos (mC4, OSCAR, Wikipedia pt) vem de fontes brasileiras. Quando fine-tunas um modelo com esses dados, o resultado fala um português gramaticalmente correto, mas culturalmente deslocado.

Isto aparece em três pontos críticos que já vi em produção:

  • Terminologia técnica: “upload” vira “envio de arquivo”, “dataset” vira “conjunto de dados”, “deploy” vira “implantação”. Funciona no Brasil, soa estranho em Portugal.
  • Expressões idiomáticas: um modelo pode responder “tudo certo?” quando esperava “está tudo bem?” ou usar “a gente” em vez de “nós”.
  • Contexto institucional: referências a “INSS”, “CPF”, “SUS” ou “Receita Federal” são inúteis (e às vezes ofensivas) num sistema para a Administração Pública portuguesa.

O que o Arquivo.pt resolve (e o que não resolve)

O Arquivo.pt preserva a memória digital da Web portuguesa desde os anos 90, com recolhas trimestrais de toda a Web PT e recolhas diárias de cerca de 400 sites de alta frequência — institucionais e órgãos de comunicação social. Isto é ouro para IA em Portugal porque:

  • Dá-te texto realmente português, escrito por portugueses, para portugueses.
  • Inclui contexto temporal — consegues ver como a terminologia evoluiu.
  • Tem escala — 2TB indexados é volume suficiente para alimentar modelos sérios.

O que NÃO resolve: a limpeza dos dados. Vais ter HTML sujo, duplicados, encoding quebrado, menus de navegação misturados com conteúdo útil. Se fores usar isto, vais precisar de pipeline próprio. Chegamos lá já.

Na Prática: como usar o Arquivo.pt para treinar ou alimentar um LLM

Vou mostrar-te o caminho realista que sigo quando preciso de corpus português de qualidade. Não é plug-and-play, mas também não é rocket science.

1. Recolhe os dados via API pública

O Arquivo.pt expõe uma API que permite pesquisar e listar snapshots. Comecei por aqui sempre.

import requests
from datetime import datetime
from typing import Iterator

BASE = "https://arquivo.pt/wayback/search"

def fetch_snapshots(query: str, from_date: str, to_date: str, limit: int = 50) -> Iterator[dict]:
    """Itera sobre snapshots do Arquivo.pt para um query."""
    params = {
        "q": query,
        "from": from_date,
        "to": to_date,
        "limit": limit,
        "output": "json"
    }
    r = requests.get(f"{BASE}", params=params, timeout=30)
    r.raise_for_status()
    for hit in r.json().get("response_items", []):
        yield {
            "url": hit["url"],
            "timestamp": hit["timestamp"],
            "digest": hit["digest"]
        }

# Exemplo: recolher artigos do Público sobre tecnologia em 2024
for snap in fetch_snapshots(
    "site:público.pt tecnologia",
    from_date="20240101",
    to_date="20241231",
    limit=20
):
    print(snap["timestamp"], snap["url"])

2. Extrai o texto limpo (a parte chata)

HTML de arquivo é HTML de arquivo — menus, banners, trackers, comentários. Aqui entra o trafilatura, que na minha experiência dá o melhor resultado para conteúdo em português.

import trafilatura

def clean_html(raw_html: str) -> str | None:
    """Extrai texto principal de HTML arquivado."""
    extracted = trafilatura.extract(
        raw_html,
        include_comments=False,
        include_tables=False,
        favor_recall=True,
        language="pt"
    )
    return extracted

# Pipeline típico
import hashlib

def dedup_key(text: str) -> str:
    return hashlib.sha256(text.encode("utf-8")).hexdigest()

seen = set()
clean_docs = []

for snap in fetch_snapshots("site:sapo.pt", "20230101", "20231231"):
    raw = requests.get(f"https://arquivo.pt/wayback/{snap['timestamp']}/{snap['url']}").text
    clean = clean_html(raw)
    if clean and len(clean) > 500:  # descarta páginas vazias
        key = dedup_key(clean)
        if key not in seen:
            seen.add(key)
            clean_docs.append(clean)

print(f"Documentos limpos: {len(clean_docs)}")

3. Tokeniza e formata para treino

Para fine-tuning com Hugging Face, o padrão é gerar JSONL com campos text ou messages.

import json
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.2-3B-Instruct")

with open("amalia_corpus.jsonl", "w", encoding="utf-8") as f:
    for doc in clean_docs:
        tokens = tokenizer.encode(doc)
        if 200 < len(tokens) < 4000:  # descarta extremos
            f.write(json.dumps({"text": doc}, ensure_ascii=False) + "\n")

4. Fine-tuna com QLoRA (a forma eficiente)

Não precisas de 8x A100. Uma única A100 80GB ou mesmo uma 4090 com 24GB serve para modelos até 7B em QLoRA. Uso sempre o peft da Hugging Face.

pip install -q transformers peft trl bitsandbytes datasets accelerate
from peft import LoraConfig, get_peft_model
from trl import SFTTrainer
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
import torch

bnb = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.2-3B-Instruct",
    quantization_config=bnb,
    device_map="auto"
)

lora = LoraConfig(
    r=16, lora_alpha=32, lora_dropout=0.05,
    target_modules=["q_proj", "v_proj"],
    task_type="CAUSAL_LM"
)

trainer = SFTTrainer(
    model=get_peft_model(model, lora),
    train_dataset=load_dataset("json", data_files="amalia_corpus.jsonl")["train"],
    args=TrainingArguments(
        output_dir="./amalia-pt",
        num_train_epochs=2,
        per_device_train_batch_size=4,
        gradient_accumulation_steps=4,
        learning_rate=2e-4,
        bf16=True,
        logging_steps=10
    )
)
trainer.train()

Erros Comuns — onde vi equipas a tropeçar

Já vi isto em três projetos diferentes. Anota.

Erro 1: Tratar o Arquivo.pt como "Big Data pronto a usar"

Não é. É fonte primária. Vais gastar 60-70% do teu tempo em limpeza e deduplicação. O conteúdo da Amália (5,8 mil milhões de tokens) não apareceu do dia para a noite — exigiu pipeline sério. Na minha experiência, quem pula esta fase acaba com um modelo que aprende os menus do site em vez do conteúdo.

Erro 2: Esquecer o filtro temporal

Conteúdo dos anos 90 tem encoding Latin-1, referências a marcos que já não existem, e terminologia completamente desatualizada. Limita sempre o intervalo temporal ao que faz sentido para o teu caso de uso. Para um assistente em 2026, raramente precisas de dados anteriores a 2010.

Erro 3: Ignorar a licença

Atenção aqui: nem tudo o que está arquivado está livre para uso comercial. Sites institucionais públicos (como o .gov.pt) tendem a ter licenças abertas, mas órgãos de comunicação social têm direitos. Antes de treinar, confirma a política de cada fonte. Isto não é burocracia — é evitar uma carta do advogado do outro lado.

Erro 4: Misturar dados sem curadoria

Um modelo que mistura Público, Observador, blogues pessoais e sites governamentais fala com cinco vozes diferentes. Define o tom-alvo primeiro, depois seleciona fontes compatíveis. Para um assistente técnico, priorizo documentação institucional e técnica. Para um chatbot de atendimento ao cliente, foco em FAQs institucionais.

Erro 5: Não avaliar com benchmarks em PT-PT

Se não medires o resultado em português europeu, não sabes se melhoraste. Cria um pequeno conjunto de teste (50-100 perguntas) com respostas escritas por falantes nativos de Portugal e mede antes e depois do fine-tune. Sem isto, estás a navegar às cegas.

Comparação com alternativas

O Arquivo.pt não é a única fonte de português europeu — é a mais completa. Outras opções que considero:

Fonte Vantagem Limitação
Arquivo.pt Escala, contexto histórico, cobertura institucional Requer limpeza pesada
Wikipedia PT Limpo, estruturado, licença aberta Pouco texto por artigo, tom enciclopédico
DGT (Dicionários) Terminologia oficial validada Não é texto natural
EUR-Lex / legislação EU-PT Português formal, jurídico Domínio muito específico
CommonCrawl filtrado Volume enorme Maioria brasileira, qualidade variável

O sweet spot que encontrei: Arquivo.pt como base principal (60-70%), complementado com Wikipedia e EUR-Lex para tarefas técnicas, e datasets europeus quando disponíveis.

FAQ — Perguntas que devs realmente fazem

O Arquivo.pt é gratuito?

Sim, o serviço é público e gratuito para consulta. Para uso em projetos de IA, confirma diretamente com a FCT os termos de licenciamento para treino de modelos, especialmente se for uso comercial.

Quanto tempo demora a construir um corpus limpo a partir do Arquivo.pt?

Na minha experiência, para um corpus de 1-2GB de texto limpo, espera 2-4 semanas de pipeline (recolha, extração, limpeza, deduplicação). Para volumes maiores como o da Amália (5,8 mil milhões de tokens), são meses.

Preciso mesmo de fine-tuning, ou chega o RAG?

Depende. Para Q&A sobre documentação específica, RAG com embeddings é mais rápido e barato. Para alterar o estilo de escrita, terminologia ou tom cultural do modelo, fine-tuning é melhor. Em produção, muitas vezes combino ambos.

Que modelo base recomendo para PT-PT?

Para fine-tuning até 7B parâmetros, o Llama 3.2 3B Instruct é sólido e corre em hardware modesto. Para melhores resultados, o Mistral 7B ou o Qwen2.5 7B (excelente em multilingue). Evita modelos muito pequenos (<1B) — perdem-se nuances do português.

Vale a pena usar a IA Amália diretamente?

Se o teu caso de uso é genérico (atendimento, Q&A, sumarização), sim — já vem treinada em dados portugueses e evita-te o pipeline todo. Se precisas de algo especializado (jurídico, médico, técnico), o fine-tuning a partir de um modelo base ainda é o caminho.

Conclusão

O trabalho que a FCT está a fazer com o Arquivo.pt é daquelas coisas que parece "chato" — preservar páginas antigas — mas é infraestrutura crítica para qualquer IA séria em Portugal. Sem dados nacionais de qualidade, ficamos reféns de modelos que confundem "autocarro" com "ônibus" e não percebem a diferença entre um NIF e um CPF.

Se estás a construir algo em IA para clientes portugueses em 2026, trata o Arquivo.pt como matéria-prima estratégica. Sim, dá trabalho. Mas é o tipo de trabalho que te coloca à frente da concorrência que ainda acha que "português é tudo igual".

Gostou? Me segue no GitHub e deixa um comentário se tiver dúvida ou quiser aprofundar algum ponto.

Y

Yuri Sousa

Front-End Developer / Designer

Desenvolvedor apaixonado por criar experiências digitais acessíveis e visualmente perfeitas. Escrevo sobre desenvolvimento web, design e tecnologia.