547 6.3K 0

Canarim-Instruct-PTBR Dataset

Como construí e harmonizei um dataset com 317.932 pares de instrução e resposta em português, os aprendizados da primeira versão e os próximos passos.

Canarim-Instruct-PTBR: como construí 317 mil instruções em português

Eu construí o Canarim-Instruct-PTBR Dataset como uma coleção de exemplos para ajuste supervisionado de modelos de linguagem em português. Cada registro representa uma solicitação, um contexto opcional e a resposta esperada. A publicação reúne 317.932 registros: 316.413 em train e 1.519 em test. Escolhi o nome Canarim, uma forma regional de “canarinho”, pela presença familiar dessa ave no cotidiano brasileiro.[1]

Seu valor imediato é pragmático: em 2023, quando conjuntos de instruction tuning em português ainda eram escassos, publiquei centenas de milhares de pares já normalizados em três colunas e distribuídos como Parquet. Na primeira versão, alertei que poderiam existir erros de tradução. Essa limitação continua importante: há traduções literais, respostas factualmente frágeis, código deformado e tarefas que pedem capacidades não representáveis em texto. Neste artigo, explico como compus e harmonizei os dados, quais decisões tomei e o que pretendo melhorar.

PropriedadeValor verificado
Registros totais317.932
train316.413
test1.519
Camposinstruction, input, output
Tamanho lógico113.787.388 bytes
Download Parquet63.510.092 bytes
Arquivos de dados2
Idioma declaradoportuguês (pt)
Licença atualCC BY-NC 4.0
DOI10.57967/hf/0983

Como compus os 316.413 exemplos de treino

Eu reuni cinco fatias de três linhagens principais: Alpaca traduzido, instructions-pt e a família Self-Instruct/Super-NaturalInstructions. As contagens que publiquei são:

51759+57692+74350+82612+50000=316413.51\,759+57\,692+74\,350+82\,612+50\,000=316\,413.

As participações abaixo são apenas divisões dessas contagens pelo total de treino. Elas não representam taxas medidas antes da tradução, depois de filtros ou após deduplicação, pois não publiquei esses denominadores.

Fatia declaradaLinhasParcela calculada de train
dominguesm/alpaca-data-pt-br51.75916,358%
cahya/instructions-pt (train)57.69218,233%
HuggingFaceH4/self_instruct (train)74.35023,498%
helpful_instructions/self_instruct82.61226,109%
helpful_instructions/super_natural_instructions50.00015,802%

Renderizando diagrama...

1. Alpaca-Cleaned em português

Usei os 51.759 registros de treino de dominguesm/alpaca-data-pt-br, já organizados no esquema instruction/input/output. Eu havia criado esse conjunto como tradução automática de yahma/alpaca-cleaned, uma limpeza do Stanford Alpaca. O Alpaca original gerou aproximadamente 52 mil demonstrações com text-davinci-003, seguindo uma versão simplificada da receita Self-Instruct: vinte instruções por chamada, uma instância por instrução e sem separar tarefas classificatórias.[3]

A limpeza de origem tentou corrigir links ou imagens ausentes, saídas vazias, instruções fundidas, caracteres de controle e respostas erradas. Isso melhora a base inglesa, mas não valida a tradução. Incorporei os 51.759 registros em sua ordem original; por isso, a primeira linha do Canarim corresponde à primeira linha dessa fonte e a linha 51.758 encerra essa fatia.

2. cahya/instructions-pt

Ao incorporar cahya/instructions-pt, trabalhei com uma fonte que oferece apenas a indicação “More Information needed”, não declara licença e usa id: int64 mais text: string, em vez de campos estruturados. Ela reúne 57.692 linhas em train, 1.519 em test e 1.518 em validation.[4] A partir do formato User: ...\nAssistant: ..., removi os marcadores, coloquei as duas partes em instruction e output e deixei input vazio.

Usei as 1.519 linhas de test de cahya/instructions-pt como teste do Canarim, preservando redação e ordem. Não incorporei as 1.518 linhas de validation à soma publicada. Na primeira versão, não publiquei a receita de montagem nem uma semente de separação; portanto, o teste é uma partição herdada dessa fonte, não um split aleatório do conjunto misto.

3. Self-Instruct e Super-NaturalInstructions

O framework Self-Instruct começa com tarefas-semente escritas por pessoas, pede a um modelo que gere novas instruções e instâncias, filtra itens inválidos ou similares e realimenta o conjunto. O trabalho publicou cerca de 52 mil instruções e 82 mil instâncias; seus autores alertaram que, em uma inspeção de 200 instruções aleatórias, 46% podiam conter algum problema. Mesmo assim, ajustar GPT-3 com esses dados produziu ganho absoluto de 33 pontos em Super-NaturalInstructions sobre o modelo base, mostrando por que supervisão sintética se tornou atraente.[7]

HuggingFaceH4/self_instruct reformata a publicação original em prompt/completion, remove <|endoftext|> e executa train_test_split(test_size=0.1, seed=42). O resultado são 74.350 itens em treino e 8.262 em teste; o Canarim declara usar os 74.350 de treino.[5]

HuggingFaceH4/helpful_instructions agrega pares com prompt, completion e metadados de origem. O Canarim usa duas configurações: os 82.612 exemplos de self_instruct e 50 mil de super_natural_instructions.[6] A segunda linhagem vem de um benchmark de 1.616 tarefas, 76 tipos e instruções especializadas, cobrindo classificação, extração, reescrita e composição, entre outros gêneros.[8]

Existe um risco estrutural importante: helpful_instructions/self_instruct deriva do próprio HuggingFaceH4/self_instruct, que também incorporei separadamente. Na primeira versão, não medi nem publiquei a taxa de sobreposição entre essas duas fatias. Como tradução e parsing podem alterar as strings, uma próxima versão precisa medir duplicatas exatas e aproximadas antes do treinamento.

Como harmonizei os formatos e traduzi o conteúdo

As fontes chegam em três schemas: Alpaca já tem três campos; instructions-pt serializa turnos em text; as coleções H4 usam prompt/completion e, em helpful_instructions, meta. O destino reduz tudo a:

CampoTipoInterpretação operacional
instructionstringtarefa ou pergunta apresentada ao modelo
inputstringcontexto opcional; frequentemente ""
outputstringresposta-alvo para perda supervisionada

Concatenei as cinco fatias nesta ordem, iniciando-as nos índices 0, 51.759, 109.451, 183.801 e 266.413. Traduzi “Find the word that is closest in meaning to fear” como “Encontre a palavra que está mais próxima no significado de medo”. Para Super-NaturalInstructions, separei definição em instruction, instância em input e rótulo em output; em parte dos exemplos H4, mantive o texto de entrada anexado à instrução e deixei input vazio. Essa primeira harmonização não aplicou a mesma separação estrutural a todas as fatias.

Na primeira versão, descrevi o processo apenas como “translation and adaptation” e alertei sobre possíveis erros, mas não registrei o serviço ou modelo de tradução, versão, prompt, temperatura, processamento em lote, tentativas, política para trechos de código, glossário, normalização Unicode, tratamento de Output:/Input:, filtros, número de linhas rejeitadas nem revisão humana.[1] O resultado inclui sinais concretos de translationese: “linha de tags” para tagline, “não faça cram”, repetição de sinônimos e nomes alternando entre João e John. Há ainda saídas truncadas ou incoerentes, como uma resposta gerencial que termina abruptamente e uma área de círculo de raio quatro informada como 12,5664, em vez de aproximadamente 50,27.

Splits, escala e o que os números significam

Somando os dois splits,

316413+1519=317932.316\,413+1\,519=317\,932.

Assim, treino representa 99,5222% e teste 0,4778% dos registros. Como usei o teste de uma única fonte, essa partição pode ter distribuição, estilo e dificuldade diferentes do treino misto; não a apresento como benchmark independente.

No card, informei 113.100.060 bytes lógicos para treino e 687.328 para teste, ou médias de 357,44 e 452,49 bytes por linha na representação da tabela. No conjunto, são

113787388317932=357,90\frac{113\,787\,388}{317\,932}=357{,}90

bytes por registro. Os dois Parquets somam 63.510.092 bytes, 55,81% do tamanho lógico. Essas razões não são comprimentos médios em tokens: incluem a codificação colunar e escondem grande variação entre respostas.

Carregamento e formatação do prompt

O carregamento básico é mostrado abaixo. Para tornar o experimento reproduzível sem expor identificadores internos, registre o DOI, a data de acesso, as contagens por split, as versões das bibliotecas e preserve uma cópia controlada dos arquivos usados.

from datasets import load_dataset
 
dados = load_dataset(
    "dominguesm/Canarim-Instruct-PTBR-Dataset",
)
 
print(dados)
print(dados["train"][0])

O template oficial usa uma variante do formato Alpaca. Tratar string vazia como ausência de contexto evita produzir uma seção Entrada inútil:

def formatar_exemplo(exemplo: dict[str, str]) -> str:
    contexto = (exemplo.get("input") or "").strip()
    if contexto:
        cabecalho = (
            "Abaixo está uma instrução que descreve uma tarefa, emparelhada "
            "com uma entrada que fornece mais contexto. Escreva uma resposta "
            "que conclua adequadamente a solicitação."
        )
    else:
        cabecalho = (
            "Abaixo está uma instrução que descreve uma tarefa. "
            "Escreva uma resposta que conclua adequadamente a solicitação."
        )
    partes = [cabecalho, f"### Instruções:\n{exemplo['instruction'].strip()}"]
    if contexto:
        partes.append(f"### Entrada:\n{contexto}")
    partes.append(f"### Resposta:\n{exemplo['output'].strip()}")
    return "\n".join(partes)

Em treinamento causal, a prática recomendável é mascarar da função de perda os tokens do cabeçalho, instrução e entrada, supervisionando somente a resposta. Caso contrário, o modelo também é otimizado para reproduzir o prompt. O truncamento deve reservar espaço para a saída e registrar quantos exemplos perderam conteúdo; cortar silenciosamente o final pode transformar respostas corretas em alvos incompletos.

Aprendizados da primeira versão: duplicação e qualidade

Na primeira versão, não registrei uma etapa de deduplicação do conjunto pronto. Aprendi que uma próxima versão deve começar preservando source, configuração, split e índice original em colunas auxiliares. Normalizar para comparação não significa sobrescrever o texto: a versão original deve continuar disponível para rastreabilidade.

import re
import unicodedata
 
def normalizar(texto: str) -> str:
    texto = unicodedata.normalize("NFKC", texto or "").casefold()
    return re.sub(r"\s+", " ", texto).strip()
 
def chave_normalizada(exemplo: dict[str, str]) -> tuple[str, ...]:
    campos = ("instruction", "input", "output")
    return tuple(normalizar(exemplo[c]) for c in campos)
 
vistos = set()
duplicatas = 0
for exemplo in dados["train"]:
    chave = chave_normalizada(exemplo)
    duplicatas += chave in vistos
    vistos.add(chave)
 
print({"duplicatas_normalizadas": duplicatas})

A chave normalizada encontra cópias textuais, mas não paráfrases, traduções alternativas ou respostas parcialmente repetidas. No segundo nível, pretendo usar shingles de tokens com MinHash/LSH e, separadamente, embeddings para gerar candidatos semânticos. Todo candidato precisa de regra de decisão registrada. Deduplicação antes de separar avaliação reduz memorização e vazamento; a literatura associa remoção de duplicatas a menor cópia literal, menos passos de treino e avaliação mais confiável.[9][10]

Renderizando diagrama...

Além da duplicação, pretendo fazer a QA medir por fonte: idioma previsto; caracteres corrompidos; proporção de entrada vazia; comprimento em caracteres e tokens; repetição interna; marcadores ingleses residuais; preservação de código; respostas vazias ou truncadas; solvabilidade sem recurso externo; correção de contas; consistência entre rótulo e opções; toxicidade; dados pessoais; e similaridade com benchmarks. Uma amostra humana estratificada por fonte, comprimento e tipo de tarefa deve classificar fidelidade da tradução, validade da instrução e utilidade da saída, reportando concordância entre anotadores e intervalos de confiança.

Escopo atual, licença e próximos passos

Criei o conjunto para ajuste supervisionado experimental de modelos em português, estudo de mistura de fontes e pesquisa sobre filtragem. Ele também serve como matéria-prima para uma versão menor e validada. Sem nova curadoria, não o recomendo como fonte de verdade factual, corpus médico/jurídico, benchmark de segurança ou avaliação imparcial. Modelos treinados nele podem reproduzir alucinações, anglicismos, vieses das fontes e políticas de resposta de GPT-3. A concentração de dados sintéticos não representa a diversidade social, regional e discursiva do português brasileiro.

Publiquei o conjunto sob CC BY-NC 4.0, permitindo compartilhamento e adaptação com atribuição, indicação de mudanças e uso não comercial. Adotei essa licença por causa das origens em gerações de modelos e das políticas da OpenAI.[1][11] Isso não resolve automaticamente toda a cadeia. alpaca-data-pt-br também declara CC BY-NC 4.0; os datasets H4 consultados declaram Apache-2.0; cahya/instructions-pt não declara licença em seu card. Licença de repositório, termos do serviço que gerou o conteúdo e direitos presentes em exemplos são camadas diferentes.

Para redistribuição ou treinamento, preserve atribuições, edições e datas de acesso de todas as fontes, documente modificações e não presuma autorização comercial. Dados pessoais, marcas, privacidade e outros direitos podem exigir permissões adicionais. Esta é uma leitura técnica dos artefatos, não aconselhamento jurídico.

Mantenho o Canarim-Instruct-PTBR como uma mistura ampla e acessível em português e como registro dos desafios que encontrei ao trabalhar com datasets sintéticos traduzidos. Para a próxima versão, meu objetivo não é apenas acrescentar linhas: pretendo publicar a receita, preservar proveniência por exemplo, medir a deduplicação, realizar avaliação humana e construir splits por grupos independentes. Essas são próximas etapas, não características da versão atual.

Referências

1. Domingues, M. Canarim-Instruct-PTBR-Dataset, DOI 10.57967/hf/0983: card, API, arquivos e amostras. Consulta em 24 jul. 2026.

2. Domingues, M. DominguesM/Canarim-Instruct-PTBR: README e ativo canarim.png, 2023.

3. Domingues, M. alpaca-data-pt-br; Taori, R. et al. Stanford Alpaca; Gururise. AlpacaDataCleaned, 2023.

4. Cahya. instructions-pt: card e arquivos, 2023.

5. Hugging Face H4. self_instruct: script de criação e arquivos, 2023.

6. Hugging Face H4. helpful_instructions: card e script do dataset, versão 1.0.0, 2023.

7. Wang, Y. et al. Self-Instruct: Aligning Language Models with Self-Generated Instructions. ACL 2023, arXiv:2212.10560.

8. Wang, Y. et al. Super-NaturalInstructions: Generalization via Declarative Instructions on 1600+ NLP Tasks. EMNLP 2022, p. 5085-5109, DOI 10.18653/v1/2022.emnlp-main.340.

9. Broder, A. Z. On the Resemblance and Containment of Documents. Compression and Complexity of SEQUENCES 1997, p. 21-29.

10. Lee, K. et al. Deduplicating Training Data Makes Language Models Better. ACL 2022, p. 8424-8445, DOI 10.18653/v1/2022.acl-long.577.

11. Creative Commons. Attribution-NonCommercial 4.0 International, texto resumido e código legal.

BibTeX

@dataset{domingues2023canarim_instruct,
  author    = {Maicon Domingues},
  title     = {Canarim-Instruct-PTBR-Dataset},
  year      = {2023},
  publisher = {Hugging Face},
  doi       = {10.57967/hf/0983},
  url       = {https://huggingface.co/datasets/dominguesm/Canarim-Instruct-PTBR-Dataset}
}
 
@article{wang2023selfinstruct,
  title   = {Self-Instruct: Aligning Language Models with Self-Generated Instructions},
  author  = {Wang, Yizhong and Kordi, Yeganeh and Mishra, Swaroop and Liu, Alisa and Smith, Noah A. and Khashabi, Daniel and Hajishirzi, Hannaneh},
  journal = {Proceedings of the 61st Annual Meeting of the Association for Computational Linguistics},
  year    = {2023},
  eprint  = {2212.10560},
  archivePrefix = {arXiv},
  url     = {https://arxiv.org/abs/2212.10560}
}
 
@inproceedings{wang2022supernaturalinstructions,
  title     = {Super-NaturalInstructions: Generalization via Declarative Instructions on 1600+ NLP Tasks},
  author    = {Wang, Yizhong and Mishra, Swaroop and Alipoormolabashi, Pegah and others},
  booktitle = {Proceedings of the 2022 Conference on Empirical Methods in Natural Language Processing},
  year      = {2022},
  pages     = {5085--5109},
  doi       = {10.18653/v1/2022.emnlp-main.340},
  url       = {https://aclanthology.org/2022.emnlp-main.340/}
}
 
@inproceedings{lee2022deduplicating,
  title     = {Deduplicating Training Data Makes Language Models Better},
  author    = {Lee, Katherine and Ippolito, Daphne and Nystrom, Andrew and Zhang, Chiyuan and Eck, Douglas and Callison-Burch, Chris and Carlini, Nicholas},
  booktitle = {Proceedings of the 60th Annual Meeting of the Association for Computational Linguistics},
  year      = {2022},
  pages     = {8424--8445},
  doi       = {10.18653/v1/2022.acl-long.577},
  url       = {https://aclanthology.org/2022.acl-long.577/}
}