Skip to content
marola-devPublic

Latest commit

 

History

116 Commits

Folders and files

Repository files navigation

Uma pequena onda que se enrola uma vez e segue como uma linha de letras, cada uma um ponto, crescendo: desenho original feito para o marola-ml

marola-ml

a casa do marola-gpt, um adaptador LoRA sobre o Tucano-2b4 · o modelo · a cadeia · licença · histórico

ci base: TucanoBR/Tucano-2b4 marola-gpt: SLM educacional Hugging Face: h0ffmann/marola-gpt código: MIT pesos: Apache--2.0

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.

marola-gpt

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.

Pergunte a ele

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 1

O 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.

GPU ou CPU

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 300

Na 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.

Do corpus ao Hugging Face

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.

Release por tag: just sea-release

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ção

As 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.

Release manual no Hugging Face

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 run

just 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 resto do marola-ml

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 workflow compile prompt roda 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 o marola-llama3.2 que 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.py reprova 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 o marola-llama3.2 já no store, publicado como ghcr.io/marola-dev/marola-ml:local quando passa no gate (docker-local.yml).
  • O caminho do Llama não tem mais workflow de publicação: o marola-sea-publish.yml foi trocado pelo marola-gpt-publish.yml em 14 de outubro de 2026. just finetune-publish ainda 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 gate

Mapa do repositório

sea/             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.

Dados e pesos fora do git

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.

Contratos

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.

Documentação

  • 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/ e scripts/, gerado no branch api-docs pelo job api-docs do ci.yml a cada push em main.
  • AGENTS.md: as regras para agentes que trabalham aqui.

Revisão do Gemini

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.

Créditos

  • 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 .gitignore em 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.

Licença

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.

Histórico do fork

A história deste repositório tem quatro partes.

  1. 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/).
  2. O fork do nanoGPT, 14 de outubro de 2026. O código do karpathy/nanoGPT no commit 3adf61e154c3fe3fca428ad6bc3818b27a3b8291 foi copiado sem mudança para sea/nanogpt/, sob a licença MIT dele (Copyright (c) 2022 Andrej Karpathy, mantido em sea/nanogpt/LICENSE). Cada arquivo copiado diz isso nas primeiras linhas, e o sea/FORK.tsv registra o que cada um era no original. Com ele saiu o marola-gpt 0.0.1.
  3. 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).
  4. 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.

Releases

Packages

Contributors

Languages