🇧🇷 GPT-PT 270M — Base · 1B tokens
Um LLM brasileiro treinado do zero, em português. 270,6M parâmetros. Este é o checkpoint de 1 bilhão de tokens — modelo base, ainda subtreinado.
A Brazilian LLM trained from scratch, in Portuguese. 270.6M parameters. This is the 1-billion-token checkpoint — base model, still undertrained.
Assinado por / Signed by icdron — projeto GPT-PT · setembro / September 2026
⚠️ PT: Modelo base, não-instruído e subtreinado. Este checkpoint tem apenas ~17% do treino planejado (1,14B de 6,6B tokens). Ele não segue instruções, não é chatbot, não tem RLHF/DPO e alucina fatos. Use como base para continuar o pré-treino, estudar a curva de aprendizado ou fazer fine-tuning próprio. Não use em produção sem SFT.
⚠️ EN: Base model, not instruction-tuned and undertrained. This checkpoint covers only ~17% of the planned training (1.14B of 6.6B tokens). It does not follow instructions, is not a chatbot, has no RLHF/DPO and hallucinates facts. Use it to continue pre-training, study the learning curve or do your own fine-tuning. Do not use in production without SFT.
Próximos marcos públicos / Next public milestones: 2B · 3B · 4B · 5B · 6B tokens — cada um / each with a comparable eval.
1. O que é este modelo / What is this model
PT
| Campo | Valor |
|---|---|
| Nome | gpt-pt-270m-base-1b — checkpoint do passo 70.000 |
| Parâmetros | 270,6M |
| Arquitetura | Decoder-only causal LM — LeanGPT (Llama-style): RMSNorm + RoPE + GQA + SwiGLU + tied embeddings |
| Dimensões | vocab 49.152 · d 1024 · 14 camadas · 16 heads (8 KV, GQA) · inner 4096 · seq 2048 |
| Tokenizer | BPE próprio 49.152 tokens, treinado no próprio corpus (`< |
| Corpus | vitin12/gptpt-corpus-v2 — 6,61B tokens, 3,23M linhas de 2048, 32 shards (13 fontes, ver §2) |
| Tokens vistos | 1.146.880.000 (70k steps × 8 bs × 2048 seq) — ~17% do corpus |
| Treino | 2× T4 no Kaggle, torch.compile, ce_head_chunked (sem materializar logits 2048×49k), fp16 + GradScaler, lr 5e-4 → 5e-5 cosine (warmup 2000) + LR adaptativo |
| Licença pesos | MIT — use, adapte, redistribua |
| Formato | model.safetensors + pytorch_model.bin + tokenizer.json + config.json |
| Assinatura | icdron — watermark _icdron_watermark nos pesos + signature: icdron no config.json + este README |
EN
| Field | Value |
|---|---|
| Name | gpt-pt-270m-base-1b — checkpoint at step 70,000 |
| Parameters | 270.6M |
| Architecture | Decoder-only causal LM — LeanGPT (Llama-style): RMSNorm + RoPE + GQA + SwiGLU + tied embeddings |
| Dims | vocab 49,152 · d 1024 · 14 layers · 16 heads (8 KV, GQA) · inner 4096 · seq 2048 |
| Tokenizer | Custom BPE 49,152 tokens, trained on the corpus itself (`< |
| Corpus | vitin12/gptpt-corpus-v2 — 6.61B tokens, 3.23M rows of 2048, 32 shards (13 sources, see §2) |
| Tokens seen | 1,146,880,000 (70k steps × 8 bs × 2048 seq) — ~17% of corpus |
| Training | 2× T4 on Kaggle, torch.compile, ce_head_chunked (no full 2048×49k logits), fp16 + GradScaler, lr 5e-4 → 5e-5 cosine (warmup 2000) + adaptive LR |
| Weights license | MIT — use, adapt, redistribute |
| Format | model.safetensors + pytorch_model.bin + tokenizer.json + config.json |
| Signature | icdron — _icdron_watermark tensor in weights + signature: icdron in config.json + this README |
2. Corpus & arquitetura / Corpus & architecture
Corpus — vitin12/gptpt-corpus-v2
Pré-tokenizado uint16 .bin, linhas de 2048 no formato [SEP, tokens, SEP] onde SEP = <|endoftext|> id 0. Sampler ponderado por fonte via manifest.json.
Pre-tokenized uint16 .bin, rows of 2048 as [SEP, tokens, SEP] where SEP = <|endoftext|> id 0. Source-weighted sampler via manifest.json.
| Fonte / Source | HF dataset | Kind | max_docs | Peso sampler |
|---|---|---|---|---|
gigaverbo_v2 | Polygl0t/gigaverbo-v2 | pt | 7M | 0.7× |
gigaverbo_synth | Polygl0t/gigaverbo-v2-synth | pt | 5M | 2.0× |
openwebmath | open-web-math/open-web-math | en_math | 1.2M | 2.0× |
wikipedia_pt | wikimedia/wikipedia (20231101.pt) | pt | 1.2M | 1.2× |
fineweb2_por | HuggingFaceFW/fineweb-2 (por_Latn) | pt | 4M | 0.7× |
faquad | nicholasKluge/faquad-nli-parquet | qa | 60k | 2.0× |
starcoder_py | bigcode/starcoderdata (python) | code | 2M | 2.0× |
enem | maritaca-ai/enem | qa | 20k | 2.0× |
gigaverbo_sft | Polygl0t/gigaverbo-v2-sft (multi) | chat | 1.5M | 2.0× |
fable5 | AnkitAI/fable-5-traces-sft-chatml | chat_en | 1M | 0.7× |
oasst1_pt | OpenAssistant/oasst1 (pt-BR) | qa | 400k | 2.0× |
gutenberg_pt | manu/project_gutenberg (pt) | book | 1.5k | 1.2× |
c4_pt | allenai/c4 (pt) | pt | 1.5M | 0.7× |
| Total | 6,61B tokens / 3,23M rows / 32 shards |
Filtros / Filters: text_ok (alpha, tamanho, stopwords PT/EN, repetição), dedup SHA, n-gram PPL filter, edu_ok.
Arquitetura / Architecture
LeanGPT(
emb: Embedding(49152 → 1024)
blocks: 14× LeanBlock(
ln1: RMSNorm(1024, eps 1e-6)
attn: Attn(d 1024, h 16, kv 8, dh 64) — qkv + SDPA causal + GQA repeat
ln2: RMSNorm(1024)
mlp: SwiGLU(1024 → 4096 → 1024) — w1 gate + w3 up, SiLU, w2 down
)
norm: RMSNorm(1024)
rope: RoPE(dim 64, max 2048, theta 10000)
head: tied — logits = norm(h) @ emb.weight.T
)
Params: 270,6M (emb 50,3M + 14× ~15,7M + norm/rope)
Treino / Training: bs 8 · seq 2048 · grad_accum 1 → 16.384 tok/step (~11,7k tok/s em 2×T4, MFU ~14,6%), warmup 2000, lr 5e-4 → 5e-5 cosine até 265k steps, wd 0.1, grad_clip 1.0, spike_mult 2.0, lr adaptativo (patience 3000, factor 0.7, floor 5e-5), val_every 250 (16 rows), save 900s + marcos 1000 steps, torch.compile on, GradScaler fp16, ce_head_chunked(chunk=2) para não estourar VRAM.
3. Como usar / How to use
O modelo não é transformers LlamaForCausalLM — é o LeanGPT puro do trainer. Roda com torch + tokenizers + safetensors.
This model is not a transformers LlamaForCausalLM — it's the trainer's pure LeanGPT. Runs with torch + tokenizers + safetensors.
# pip install torch tokenizers safetensors
import torch, torch.nn as nn, torch.nn.functional as F
from tokenizers import Tokenizer
from safetensors.torch import load_file
class RMSNorm(nn.Module):
def __init__(self, dim, eps=1e-6):
super().__init__(); self.w = nn.Parameter(torch.ones(dim)); self.eps = eps
def forward(self, x):
return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps) * self.w
class RoPE(nn.Module):
def __init__(self, dim, max_t, theta=10000.0):
super().__init__()
half = dim // 2
inv = 1.0 / (theta ** (torch.arange(0, dim, 2).float() / dim))
t = torch.arange(max_t).float()
cos = torch.outer(t, inv).cos(); sin = torch.outer(t, inv).sin()
self.register_buffer("cos", torch.cat([cos, cos], dim=-1))
self.register_buffer("sin", torch.cat([sin, sin], dim=-1))
self.half = half
def rot(self, x): return torch.cat((-x[..., self.half:], x[..., :self.half]), dim=-1)
def forward(self, q, k):
c = self.cos[:q.shape[-2]]; s = self.sin[:q.shape[-2]]
return q*c + self.rot(q)*s, k*c + self.rot(k)*s
class Attn(nn.Module):
def __init__(self, d, h, kv):
super().__init__(); self.h=h; self.kv=kv; self.dh=d//h
self.qkv=nn.Linear(d, d+2*self.dh*kv); self.wo=nn.Linear(d,d)
def forward(self, x, rope):
b,s,d=x.shape; qkv=self.qkv(x)
q,k,v=torch.split(qkv,(d,self.dh*self.kv,self.dh*self.kv),dim=-1)
q=q.view(b,s,self.h,self.dh).transpose(1,2)
k=k.view(b,s,self.kv,self.dh).transpose(1,2)
v=v.view(b,s,self.kv,self.dh).transpose(1,2)
q,k=rope(q,k)
if self.h!=self.kv:
r=self.h//self.kv; k=k.repeat_interleave(r,dim=1); v=v.repeat_interleave(r,dim=1)
y=F.scaled_dot_product_attention(q,k,v,is_causal=True)
return self.wo(y.transpose(1,2).reshape(b,s,d))
class MLP(nn.Module):
def __init__(self,d,inner):
super().__init__(); self.w1=nn.Linear(d,inner,bias=False); self.w2=nn.Linear(inner,d,bias=False); self.w3=nn.Linear(d,inner,bias=False)
def forward(self,x): return self.w2(F.silu(self.w1(x))*self.w3(x))
class LeanBlock(nn.Module):
def __init__(self,d,h,kv,inner):
super().__init__(); self.ln1=RMSNorm(d); self.attn=Attn(d,h,kv); self.ln2=RMSNorm(d); self.mlp=MLP(d,inner)
def forward(self,x,rope): x=x+self.attn(self.ln1(x),rope); x=x+self.mlp(self.ln2(x)); return x
class LeanGPT(nn.Module):
def __init__(self,vocab,d,n_layers,h,kv,inner,seq):
super().__init__(); self.emb=nn.Embedding(vocab,d)
self.blocks=nn.ModuleList(LeanBlock(d,h,kv,inner) for _ in range(n_layers))
self.norm=RMSNorm(d); self.rope=RoPE(d//h,seq)
def forward(self,x):
h=self.emb(x)
for blk in self.blocks: h=blk(h,self.rope)
return self.norm(h)
# — carregar / load —
tok = Tokenizer.from_file("tokenizer.json")
sep_id = tok.token_to_id("<|endoftext|>") # 0 — SEMPRE prepend no prompt! / ALWAYS prepend!
vocab, d, n_layers, h, kv, inner, seq = 49152, 1024, 14, 16, 8, 4096, 2048
model = LeanGPT(vocab, d, n_layers, h, kv, inner, seq)
state = load_file("model.safetensors") # ou / or torch.load("pytorch_model.bin")
model.load_state_dict(state, strict=False)
model.eval().cuda()
# — gerar / generate —
prompt = "A cidade de São Paulo é conhecida por"
ids = [sep_id] + tok.encode(prompt).ids
x = torch.tensor([ids], device="cuda")
with torch.no_grad():
for _ in range(80):
with torch.autocast("cuda", dtype=torch.float16):
logits = model(x[:, -seq:])[0] @ model.emb.weight.T
logits = logits[-1] / 0.8
v,_ = torch.topk(logits, 40)
logits[logits < v[-1]] = float("-inf")
nid = torch.multinomial(torch.softmax(logits, dim=-1), 1).item()
x = torch.cat([x, torch.tensor([[nid]], device="cuda")], dim=1)
print(tok.decode(x[0].tolist(), skip_special_tokens=True))
PT — Detalhe crítico: toda sequência do corpus é
[SEP, tokens, SEP]ondeSEP = <|endoftext|>id 0. Sempre façaids = [sep_id] + tok.encode(prompt).ids— sem isso a distribuição quebra e a saída degrada.decode([0]) == ''(token invisível).EN — Critical detail: every corpus row is
[SEP, tokens, SEP]whereSEP = <|endoftext|>id 0. Always doids = [sep_id] + tok.encode(prompt).ids— skipping it breaks the distribution and degrades output.decode([0]) == ''(invisible token).
4. Avaliação — passo 70.000 (1,14B tokens) / Evaluation — step 70,000 (1.14B tokens)
Eval base privado (tools/eval_base.py) — modelo base, sem instrução / base model, no instruction tuning. PPL = perplexidade (menor = melhor / lower = better), cloze = última palavra (top-1/top-5).
4.1 Benchmark privado — números brutos / Private benchmark — raw numbers
hf: marco ckpt_70000.pt (passo 70000) e mais novo que last.pt (passo 56100); usando o marco
tokenizer: 49152 tokens | BOS(sep) id: 0
ckpt: passo 70000 | tokens 1,146,880,000 | dims 49152,1024,14,16,8,4096 | seq 2048
modelo em cuda (270.6M params)
| Suite | PT PPL (loss) | EN PPL (loss) | Nota / Note |
|---|---|---|---|
| Básico / Basic (25 frases/sents) | 82.0 (4.406) | 174.2 (5.160) | PT >> EN ✓ |
| Continuação / Continuation (14) | 16.9 (2.825) | 57.9 (4.059) | PT curto já bom / PT short already good |
| Factual cont. (6) | 100.2 (4.607) | 49.0 (3.892) | ainda quebrado / still broken |
| Python cont. (4) | 11.4 (2.433) | — | excelente / excellent |
| Math cont. (6) | 577.5 (6.359) | — | catastrófico / catastrophic |
Cloze — PT (12 frases, completar última palavra / complete last word):
| Prefixo / Prefix | Gold | Top-1 | Hit |
|---|---|---|---|
O gato bebeu ___ | água | água | ✅ OK |
A menina brinca no ___ | parque | jardim | ~ top-5 |
O cachorro corre atrás da ___ | bola | porta | ❌ |
O sol brilha no céu ___ | azul | noturno | ~ |
Ela comprou flores para a ___ | mãe | festa | ❌ |
O menino lê um livro na ___ | escola | biblioteca | ❌ |
Nós comemos pão com ___ | manteiga | pão | ❌ |
O professor ensina ___ | matemática | a | ❌ |
O pássaro canta na ___ | árvore | sua | ❌ |
O carro está na ___ | garagem | garagem | ✅ OK |
O peixe nada no ___ | lago | mar | ❌ |
A casa é grande e ___ | bonita | o | ❌ |
PT cloze: top-1 2/12 (17%) | top-5 4/12 (33%) · EN cloze: top-1 0/12 (0%) | top-5 1/12 (8%) — viés PT correto / correct PT bias.
EN cloze top-1 todas ❌ (ex.: The cat drank ___ → is vs water; The girl plays in the ___ → world vs park) — 1 hit em top-5 (The sun shines in the blue ___ → and vs sky).
4.2 O que já funciona / What already works
| Métrica / Metric | Valor / Value | Interpretação / Interpretation |
|---|---|---|
| PT básico / Basic | PPL 82.0 | Bem melhor que 27k do step 200 do projeto antigo; ainda longe de 30-40 (coerente) / Much better than 27k at step 200 of the old project; still far from 30-40 (coherent) |
| Cont. PT / PT cont. | PPL 16.9 | Modela bem continuação curta em PT / Models short PT continuation well |
| Python cont. | PPL 11.4 | Excelente — oversample de código funciona / STARCoder 2× oversampling works |
| Cloze PT | 17% / 33% | Acerta água, garagem; jardim≈parque em top-5 / Hits água, garagem; jardim≈parque in top-5 |
| Viés PT >> EN / PT bias | PT 82 vs EN 174 · cont 16.9 vs 57.9 | Não virou modelo inglês / Did not become an English model |
| Identidade / Identity | Eu sou / Quem é você? / Who are you? não vaza / no leak | Gera genérico, sem "sou Claude/GPT" / Generic output, no "I'm Claude/GPT" |
4.3 O que ainda NÃO funciona (esperado com 1B) / What does NOT work yet (expected at 1B)
| Métrica / Metric | PPL | Estado / Status |
|---|---|---|
| Factual PT (capital, água ferve, Au, 1822, Júpiter, Dom Casmurro) | 100.2 | Quebrado / Broken |
| Factual EN (Paris, 100°, Au, Júpiter, Hamlet, luz) | 49.0 | Melhor por acaso do corpus EN / Better by accident (EN-heavy corpus) |
| Math (17×23, trem 60·3, derivada x²) | 577.5 | Catastrófico / Catastrophic |
Normal para 270M com 1B tokens. Fatos e raciocínio só estabilizam após 5-6B + SFT. / Normal for 270M at 1B tokens. Facts and reasoning only stabilize after 5-6B + SFT.
4.4 Amostras reais de geração (temp 0.8, top-k 40) / Real generation samples
Factual — PT / Factual — PT:
"A capital do Brasil é" → "a cidade de São Paulo. Com uma população de 758.700 habitantes, a capital é responsável por abrigar a maior"
"A água ferve a" → "nossa espinha!\nA temperatura da água e a umidade estão aumentando a quantidade de água na nossa espinha.\nEntão,"
"O símbolo químico do ouro é" → "a sua origem.\nA sua origem está ligada à ideia do ouro e ao ouro que é um metal nobre, uma"
"Dom Pedro I proclamou a independência em" → "1521, mas a realidade é que não foi. São os portugueses, portugueses e espanhóis que não são os que dizem"
"O maior planeta do sistema solar é" → "o Sol, que é o segundo mais próximo do sol. Isso significa que ele fica mais próximo do Sol e mais próximo"
"Quem escreveu Dom Casmurro?" → "A nossa vida, o nosso dia a dia, o nosso estado de espírito, o nosso estado de espírito, a"
Factual — EN / Factual — EN:
"The capital of France is" → "the most popular and most important indústria in Europe and the most important factor of the production of natural gas production is the production"
"Water boils at" → "a constant rate of one percent. What is the value of the boiling rate, when it is 0.1%"
"The chemical symbol for gold is" → "Cd. Here's a quick test for it:\n\nThe following chemical symbol for gold is Cd."
"The largest planet is" → "going to be observed on the Sun, so I’ll be sure that the planet will see it.\n\n#"
"Who wrote Hamlet?" → "Let us take a look at the definition of an ideal on a compact disk.\n\nLet $K$"
"The speed of light is about" → "4.0 m/s, so we can write it as 4.3 m/s^2 or 4."
Livre / Free:
"A cidade de São Paulo é conhecida por" → "suas belíssimas praias, arquitetura e vida noturna. Entretanto, o que se pode dizer sobre São Paulo é que ela é um"
"A tecnologia mudou a forma como" → "nos relacionamos e interagimos com o mundo à nossa volta. Ela trouxe novas ferramentas e instrumentos para nos comunicarmos,"
"Os cientistas descobriram que" → "a densidade da água no fundo do oceano aumentou cerca de 2 bilhões de vezes no ano de 2015, aproximadamente em três meses"
Python:
"def fatorial(n):\n if n <= 1:" → "return 1\n else:\n return n * fatorial(n - 1)\n\ndef fatorial_d"
"def is_prime(n):\n for i in range(2, int(n**0.5)+1):" → "if int(i)%i == 0:\n return False\n if is_prime(n):\n if"
"lista = [1,2,3]\nfor x in lista:" → "for y in lista:\nf(x, y)\n}\n\nprint\n\nO código abaixo é"
"import math\nresult = math.sqrt(25)" → "result *= math.sqrt(25)\nresult /= math.sqrt(25)\n\nreturn result"
Math:
"Quanto é 17 * 23?" → "Esta é uma das questões mais antigas que encontramos no GMAT!\n\nO número 17 pode ser escrito como 17"
"Se um trem viaja a 60 km/h por 3 horas, ele percorre " → "60 km e 1.6 km. Se, por outro lado, um trem percorre 60 km por 5 horas,"
"A derivada de x^2 é " → "a raiz quadrada de -6 (4,2)\n\na) Encontre o valor de x ao redor do"
"What is 17 * 23?" → "It is 17 * 23.\n\nIt is 17 * 23.\n\nIt is 17 * 7."
"If a train travels 60 km/h for 3 hours, it covers " → "70 km, and it can travels 300 km. The time for the train and the distance is 400 km/h"
"The derivative of x^2 is " → "$\\frac{x^3}{3}$\n\nThe derivative of the square root of x^2 is $\\"
Identidade / Identity (checar vazamento / leak check):
"Eu sou" → "uma pessoa que não tem vergonha de sorrir, de brincar, de fazer tudo à mão..."
"Meu nome é" → "Marcos, e sou o que sou desde que me mudei para os Estados Unidos em 1975..."
"Quem é você?" → "A gente é a nossa!\nNão há nada mais perigoso do que ficar perto de alguém..."
"I am" → "having a problem with the following code and I am trying to figure it out..."
"My name is" → "Lucky ee\nMy email is Lucky ee@gmail.com\nIt is my blog.\nMy"
"Who are you?" → "# The number of objects in a box is equal to the number of objects in the box's number of objects"
Leitura honesta / Honest take: PT fluente curto ok, factual fraco, math fraco. Curva ainda vai cair muito até 6B. / Short fluent PT ok, factual weak, math weak. Curve will drop a lot until 6B.
5. Limitações e uso responsável / Limitations & responsible use
PT:
- Não é chatbot. Não segue instruções, não faz Q&A confiável, não tem filtro de segurança.
- Alucina. Datas, números, definições e código podem estar errados.
- Português apenas. Treinado e avaliado em PT; EN é incidental.
- Sem garantias. Peso MIT, mas valide toda saída antes de uso real.
EN:
- Not a chatbot. Does not follow instructions, no reliable Q&A, no safety filter.
- Hallucinates. Dates, numbers, definitions and code may be wrong.
- Portuguese only. Trained and evaluated on PT; EN is incidental.
- No guarantees. MIT weights, but validate every output before real use.
6. Reprodução e código / Reproduction & code
- Corpus:
vitin12/gptpt-corpus-v2(shards.binuint16 +manifest.json+tokenizer.json) - Treino / Training:
tools/train_gptpt_v2.py—dims 49152,1024,14,16,8,4096,bs 8,seq 2048,warmup 2000 - Eval:
tools/eval_base.py· Sampling:tools/sample_ckpt.py· Publicação / Publishing:tools/publish_1b_public.py - Este checkpoint / This checkpoint:
ckpt_70000.pt(privado / private invitin12/gptpt-corpus-v2-ckpt) → convertido aqui em / converted here tomodel.safetensors+pytorch_model.bin
# continuar o pré-treino a partir deste checkpoint / continue pre-training from this checkpoint
python tools/train_gptpt_v2.py --ckpt /kaggle/working/ckt_v2 --data /tmp/corpus_v2 --dims 49152,1024,14,16,8,4096
# publicar próximo marco / publish next milestone
python tools/publish_1b_public.py --ckpt_step 140000 --public_repo vitin12/gpt-pt-270m-base-2b
7. Citação / Citation
@misc{gptpt2026_1b,
title = {GPT-PT 270M Base — 1B tokens},
author = {icdron},
year = {2026},
url = {https://huggingface.co/vitin12/gpt-pt-270m-base-1b},
note = {Checkpoint base do passo 70.000 (1,14B tokens). Modelo subtreinado, não-instruído. / Base checkpoint at step 70,000 (1.14B tokens). Undertrained, not instruction-tuned.}
}
Pesos sob MIT. Corpus e eval sob licenças próprias de cada fonte (ver vitin12/gptpt-corpus-v2).
Weights under MIT. Corpus and eval under each source's own license (see vitin12/gptpt-corpus-v2).
Assinado por / Signed by icdron · GPT-PT · 2026
Marca d'água / Watermark: este README e os pesos deste checkpoint carregam a assinatura icdron como marca de origem do projeto. / This README and the weights of this checkpoint carry the icdron signature as the project's origin mark. Redistribuições devem preservar esta atribuição. / Redistributions must preserve this attribution.