a casa do marola-gpt, um adaptador LoRA sobre o Tucano-2b4 · o modelo · a cadeia · licença · histórico
Onde o marola faz o próprio modelo de linguagem pequeno, o marola-gpt: um adaptador LoRA treinado pelo marola no seu corpus de notas sobre o mar e segurança no mar, aplicado sobre o Tucano-2b4, um modelo aberto treinado do zero em português do Brasil. É uma distribuição educacional, feita às claras e mantida pelo marola.
Desde a 0.1.0, o marola-gpt é o Tucano-2b4
(2,44 bilhões de parâmetros, Apache-2.0, de Nicholas Kluge Corrêa, Aniket Sen, Sophia Falk e
Shiza Fatimah) com um adaptador LoRA que o marola treina no
marola-corpus, na versão fixada em
corpus.version. Os pesos do Tucano não mudam: uma release do marola-gpt guarda só o adaptador,
e a base é baixada do repositório do TucanoBR, na revisão que sea/finetune_tucano.py fixa
(ADR 0004).
| Release | Corpus | Modelo | Treino | Melhor perda de validação |
|---|---|---|---|---|
| 0.0.1, 15/10/2026 | v0.1.0: 15 080 caracteres | nanoGPT por caractere, treinado do zero: 4 camadas, 4 cabeças, largura 128; 826 240 parâmetros | 1 000 passos numa CPU hospedada do GitHub | 2,4854 no passo 600 |
| uma rodada local, 15/10/2026 (não publicada) | v0.1.0: 5 005 tokens do Tucano | Tucano-2b4 na revisão b8def49a1931 + LoRA r=8 em q_proj/v_proj; 1 597 440 parâmetros treináveis |
200 passos em 284 s, numa CPU de 4 núcleos e 16 GB | 3,0201 no passo 75 (a base sozinha: 3,1701) |
| 0.1.0 | v0.1.0 | o mesmo LoRA | marola-gpt-publish.yml, tag marola-gpt-v0.1.0 |
ainda não publicada |
O Tucano já escreve português fluente. O que o adaptador acrescenta é pouco, porque o corpus é pequeno e está em inglês: a perda de validação cai de 3,17 para 3,02 e volta a subir depois do passo 75, quando o adaptador começa a decorar o corpus. O texto continua sem compromisso com os fatos. O marola-gpt não é um assistente, e o texto dele nunca é conselho sobre o mar.
Onde ele é distribuÃdo. No Hugging Face, em huggingface.co/h0ffmann/marola-gpt, na conta do
dono por enquanto, público. A partir da 0.1.0, os pesos seguem a Apache-2.0 do Tucano.
nix develop
export SEA_PYTHON=/path/to/python # com sea/requirements.txt instalado
just marola-gpt-ask "A água-viva" # a release mais recente, 120 tokens a mais
just marola-gpt-ask "Correntes de retorno são" --version 0.1.0 --tokens 200 --temperature 0.8 --seed 1O marola-gpt não é um modelo de chat: ele continua o texto que recebe. just marola-gpt-ask baixa
a release do Hugging Face na tag dela, confere cada arquivo contra o CHECKSUMS da release, baixa
o Tucano-2b4 (cerca de 4,9 GB, só na primeira vez) e roda os dois. Tudo fica no cache do próprio
Hugging Face (~/.cache/huggingface). As releases 0.0.x são do nanoGPT e são recusadas por nome.
Gerar texto e treinar rodam nos dois, com --device:
--device |
Onde roda |
|---|---|
auto (o padrão) |
na GPU CUDA, se o torch enxergar uma; senão, na CPU |
cuda |
na GPU, e falha com uma mensagem clara se não houver |
cpu |
na CPU, mesmo com GPU |
just marola-gpt-ask "A água-viva" --device cpu
just marola-gpt-train --device cuda --steps 300Na CPU, o modelo pede uns 10 GB de RAM. Na GPU, a estimativa (não medida: este ambiente não tem GPU) é de uns 6 GB de memória de vÃdeo para gerar e uns 8 GB para treinar. Precisa também de
um torch com CUDA (pip install torch --index-url https://download.pytorch.org/whl/cu128), não da
build só de CPU. Os pesos vão em bf16, como o Tucano foi treinado; numa GPU anterior à Ampere, que
não tem bf16, vão em float16. O marola-gpt-publish.yml sempre treina na CPU do runner hospedado,
com --device cpu, então a publicação não muda de custo.
A cadeia tem quatro passos: o corpus fixado, o treino do adaptador LoRA sobre o Tucano, o
diretório da release e o upload para h0ffmann/marola-gpt. Ela chega ao Hugging Face de dois
jeitos, e nunca por merge:
| Jeito | Você roda | O que publica |
|---|---|---|
| Por tag (CD) | just sea-release minor |
o marola-gpt-publish.yml, na tag marola-gpt-vX.Y.Z enviada |
| À mão | just marola-gpt-publish <v> --yes na sua máquina |
o seu próprio --yes |
Um upload não tem volta. Os dois jeitos recusam uma release cujos arquivos não batem com os
checksums, e um agente não inicia nenhum dos dois: não cria tag, não dispara workflow, não passa
--yes.
O que publica é uma tag marola-gpt-vX.Y.Z num commit de main. just sea-release cria essa tag:
pega a maior tag marola-gpt-v*, incrementa, confere que main está limpo, igual ao origin e com o
CI verde, e então cria e envia a tag. A tag dispara o
marola-gpt-publish.yml num runner hospedado do
GitHub, que treina o adaptador sobre o Tucano a partir do corpus fixado, monta a release e sobe
para h0ffmann/marola-gpt, com a tag vX.Y.Z lá. Precisa do secret HF_TOKEN, um token
fine-grained do Hugging Face com escrita nesse repositório.
git switch main && git pull
just sea-release minor --dry-run # todas as checagens e a tag que seria criada; não envia nada
just sea-release minor # a primeira release LoRA: marola-gpt-v0.1.0
just sea-release # depois, o próximo patch: 0.1.1, 0.1.2, ...
gh run list --workflow marola-gpt-publish.yml --limit 1 # acompanhe a publicaçãoAs versões 0.0.x pertencem ao nanoGPT: o script e o workflow recusam uma delas. Uma tag fora de main é recusada pelo workflow. Merges, quantos forem, não publicam nada até a próxima tag.
Para montar e subir da sua máquina, logado no Hugging Face como h0ffmann (huggingface-cli login, ou HF_TOKEN no ambiente). Precisa de Nix, just e um Python com
sea/requirements.txt instalado, apontado por SEA_PYTHON.
nix develop
export SEA_PYTHON=/path/to/python # torch (CPU: download.pytorch.org/whl/cpu), transformers, peft, huggingface_hub
just marola-gpt-train # 1. o corpus fixado e o adaptador em sea/out-marola-gpt/
just marola-gpt-sample "A água-viva" # veja o que ele aprendeu, antes de virar release
just marola-gpt-package 0.1.0 # 2. sea/release/marola-gpt-0.1.0/: adaptador, licença, card, checksums
just marola-gpt-publish 0.1.0 # 3. um dry run: o que iria, e para onde
just marola-gpt-publish 0.1.0 --yes # 4. o upload para h0ffmann/marola-gpt, com a tag v0.1.0
just marola-gpt 0.1.0 # os passos 1 a 3 de uma vez, terminando no dry runjust marola-gpt-train --steps 300 --lr 1e-4 muda o treino, e --device cuda treina na GPU (GPU ou CPU). Use a mesma versão de uma tag
marola-gpt-v* quando a release precisar bater com ela, e rode a partir do checkout dessa tag
para o model card citar o commit certo. O workflow também roda à mão (Actions → "marola-gpt
publish"): é um dry run, a menos que você desmarque dry_run.
O que roda onde
| Passo | Arquivo | De quem |
|---|---|---|
| baixar o corpus | scripts/corpus-fetch.sh |
do marola |
| ler o corpus | sea/prepare_corpus.py |
do marola |
| treinar o adaptador | sea/finetune_tucano.py |
do marola |
| a base | TucanoBR/Tucano-2b4, revisão b8def49a1931 |
do TucanoBR, Apache-2.0, baixada sem mudança |
| a release | sea/package.py |
do marola |
| o upload | sea/publish_hf.py |
do marola |
| gerar texto | sea/ask.py |
do marola |
| o nanoGPT da 0.0.x | sea/nanogpt/, conferido por sea/fork_check.py |
de Andrej Karpathy, MIT |
O Python offline por trás do marola, de antes do marola-gpt. Nada disso roda quando o app responde uma pergunta.
dspy/: a compilação dos prompts. O workflowcompile promptroda num modelo do Ollama dentro do job e abre um PR no app com os dois arquivos compilados (como rodar).finetune/: o caminho antigo, um fine-tune do Llama 3.2 (Tier 1, um Modelfile; Tier 2, QLoRA SFT e DPO) que gera omarola-llama3.2que o app usa hoje. A página dele diz que foi substituÃdo para o modelo próprio do marola; uma MIP do umbrella decide o fim dele.docs/benchmarks/: as rodadas de benchmark guardadas.scripts/benchmark_gate.pyreprova uma rodada nova que fique mais de 0,05 abaixo da melhor delas, ou abaixo do prompt simples (o doc do gate).Dockerfile.local: o Ollama com omarola-llama3.2já no store, publicado comoghcr.io/marola-dev/marola-ml:localquando passa no gate (docker-local.yml).- O caminho do Llama não tem mais workflow de publicação: o
marola-sea-publish.ymlfoi trocado pelomarola-gpt-publish.ymlem 14 de outubro de 2026.just finetune-publishainda sobe à mão.
nix develop
just quality # todos os gates do CI, com o fork check e os self-tests do marola-gpt
just finetune-dataset # o conjunto de treino do caminho Llama, a partir dos recursos e do corpus fixados
just benchmark # o --benchmark da imagem do app fixada, no seu Ollama, e depois o gatesea/ o marola-gpt: corpus, treino LoRA sobre o Tucano, release, upload, ask
sea/nanogpt/ o nanoGPT de Andrej Karpathy, o código da 0.0.x, conferido por sea/fork_check.py
dspy/ a compilação dos prompts que o app reproduz
finetune/ o caminho Llama 3.2: Modelfile, QLoRA + DPO, datasets, merge e export
scripts/ o gate de benchmark, os fetches fixados, a release por tag
docs/ design, bibliotecas, desenvolvimento, ADRs e as rodadas de benchmark guardadas
Para entender o marola-gpt, leia nesta ordem; cada script diz para que serve nas primeiras
linhas e tem um --self-test que roda só com a biblioteca padrão:
| Passo | Arquivo | O que se aprende |
|---|---|---|
| 1 | sea/prepare_corpus.py |
das notas do corpus ao texto de treino |
| 2 | sea/finetune_tucano.py |
a base fixada, o LoRA, o dispositivo, a perda de validação |
| 3 | sea/ask.py |
como o adaptador continua um texto, e a conferência dos checksums |
| 4 | sea/package.py, sea/publish_hf.py |
o que uma release leva, e o upload que não tem volta |
just quality roda todos os gates do CI, os self-tests incluÃdos, sem GPU e sem baixar o Tucano.
O corpus, os recursos do app e os datasets de treino ficam em .tmp/ e finetune/data/; os
adaptadores, checkpoints e releases, em sea/out-*/, sea/release/ e finetune/out/. O
.gitignore recusa também, em qualquer pasta, os formatos de pesos, arrays e pacotes (*.pt,
*.safetensors, *.gguf, *.npy, *.tar.gz e afins), para um checkpoint perdido não entrar
num commit. O git guarda o que é pequeno e se revisa: código, configurações, as rodadas de
benchmark e os checksums. Uma release vai para o Hugging Face.
Releases fixadas, nunca a árvore de outro repositório: a imagem do app (marola-image), o tarball
de recursos do app (resources.version) e o corpus (corpus.version). just corpus-fetch e
just resources-fetch desempacotam os dois últimos em .tmp/. Os prompts compilados voltam para
o app como PR; o marola-gpt vai para o Hugging Face, e a base dele é fixada por revisão em
sea/finetune_tucano.py. A tabela completa, com o que fixa cada um, está no
AGENTS.md.
- Design: os três trabalhos, nenhum no caminho de uma requisição, e o mapa dos módulos.
- Bibliotecas: cada biblioteca, modelo e ferramenta fixada, e por quê.
- Desenvolvimento: ambiente, GPU, o runner self-hosted, CI, secrets, custo e quem pode rodar o quê, publicação, as versões fixadas.
- A compilação de prompts, o fine-tune, o gate de benchmark: cada trabalho e como rodar.
- Avaliação externa: os modelos e benchmarks que o marola pede a um avaliador externo, e as condições que todo avaliador segue.
- Decisões: ADR 0001, o fork do nanoGPT; ADR 0002, a cadeia do modelo (a parte da licença foi substituÃda); ADR 0003, MIT de novo e o nome marola-gpt; ADR 0004, o marola-gpt sobre o Tucano-2b4.
- Documentação da API: pdoc de
finetune/escripts/, gerado no branchapi-docspelo jobapi-docsdoci.ymla cada push em main. - AGENTS.md: as regras para agentes que trabalham aqui.
Peça o revisor marola-dev/gemini num pull request (barra lateral → Reviewers, ou
gh pr edit <N> --add-reviewer marola-dev/gemini). O marola-gemini-bot publica uma revisão com
no máximo 10 comentários inline marcados [high]/[medium]/[low] e depois envia um commit com
as correções de que tem certeza, quando python3 -m compileall -q finetune scripts dspy passa.
Peça de novo depois de novos commits para uma revisão nova. Ele só roda quando chamado, revisa PRs
de fork sem enviar commits para eles e nunca mexe em .github/. O
.github/workflows/gemini.yml chama o workflow
gemini-review
do devkit.
- Nicholas Kluge Corrêa, Aniket Sen, Sophia Falk e Shiza Fatimah, pelo Tucano (Apache-2.0), a base do marola-gpt desde a 0.1.0 (doi:10.1016/j.patter.2025.101325).
- Andrej Karpathy, pelo nanoGPT (MIT), o código que treinou o marola-gpt 0.0.x.
- Fabio Akita (@akitaonrails), cujo
microgpt deu ao marola a ideia de um GPT treinado do
zero numa máquina só, medido com honestidade. Nenhum código dele está aqui: no dia do fork ele
não tinha licença (marola-site#146).
O mapa do repositório com ordem de leitura e os pesos barrados no
.gitignoreem qualquer pasta seguem a organização que ele deu ao microgpt em 14 de outubro de 2026; as ideias, não o texto. - O layout desta página segue o do marola-research. O desenho no topo é original, feito para este repositório.
O código é MIT (LICENSE, Copyright (c) 2026 marola.dev): qualquer pessoa pode
usar, mudar e distribuir, mantendo o aviso. O código em sea/nanogpt/ é de Andrej Karpathy, sob a
própria licença MIT do nanoGPT (sea/nanogpt/LICENSE, Copyright (c) 2022 Andrej Karpathy).
Os pesos do marola-gpt, a partir da 0.1.0, são Apache-2.0, a licença do Tucano-2b4, de que
eles derivam (sea/LICENSE-Tucano-2b4, copiada byte a byte). Cada
release leva essa licença, dá crédito aos autores do Tucano e diz no model card o que o marola
mudou: só um adaptador LoRA treinado no corpus do marola. A base não é redistribuÃda. As releases
0.0.x, treinadas do zero, continuam MIT.
O REUSE.toml diz a licença e o titular de cada arquivo, como no
umbrella e nos repositórios da
ouroboric-dev, sem cabeçalho por arquivo; o
LICENSES/ tem os textos, e o CI roda reuse lint. Os pesos não entram no
repositório, então o Apache-2.0 fica no sea/LICENSE-Tucano-2b4 e em cada release.
De 14 de outubro de 2026 até a volta ao MIT
(ADR 0003), o main teve uma licença
restrita; nenhuma release saiu sob ela.
A história deste repositório tem quatro partes.
- Do marola. O marola-ml saiu do umbrella
(MIP-0070), com o histórico filtrado para estes arquivos: a compilação de prompts, o gate de
benchmark e um modelo com fine-tune a partir do Llama 3.2 (
finetune/). - O fork do nanoGPT, 14 de outubro de 2026. O código do
karpathy/nanoGPT no commit
3adf61e154c3fe3fca428ad6bc3818b27a3b8291foi copiado sem mudança parasea/nanogpt/, sob a licença MIT dele (Copyright (c) 2022 Andrej Karpathy, mantido emsea/nanogpt/LICENSE). Cada arquivo copiado diz isso nas primeiras linhas, e osea/FORK.tsvregistra o que cada um era no original. Com ele saiu o marola-gpt 0.0.1. - Do marola de novo, por cima. No mesmo dia, o modelo ganhou o nome marola-gpt. O repositório teve por pouco tempo uma licença restrita e voltou ao MIT antes de qualquer release (ADR 0003).
- Sobre o Tucano, 15 de outubro de 2026. O marola-gpt passou a ser um adaptador LoRA sobre o
Tucano-2b4 (ADR 0004, #67). O
sea/nanogpt/fica como o código da 0.0.x.