Neste artigo

Passei semanas medindo esta stack e errei o enquadramento várias vezes. Testei recuperação e chamei de inferência. Testei o forward de um transformer e concluí que a stack falhava — quando a stack não propõe inferência por transformer. Implementei BPE com outro nome e recebi a correção.

Este texto é o que sobrou depois de remover todos esses enquadramentos importados e medir apenas o que a stack propõe: nano → xfactor → madhava, sem softmax, sem amostragem de logits, sem transformer.

Os números são de pesos reais e dados reais.

O que foi medido

Modelos: Qwen2.5-0.5B-Instruct (151.936 tokens × 896d) e GPT-2 (50.257 × 768d), ambos em safetensors, carregados sem torch no caminho da geometria.

Dados: GloVe 6B (400 mil palavras), arXiv 100k (embeddings 1536d de documentos reais), SIFT 1M (128d, o benchmark canônico de busca vetorial).

A matriz completa, seis combinações modelo × corpus:

Qwen2.5 GPT-2
GloVe top-10 99,5% top-10 100,0%
arXiv prova 25,1% prova 25,1%
SIFT prova 100,0% prova 100,0%

Reexecutei a frente GloVe nos dois modelos com o código corrigido, nesta máquina, para este texto. Números por frente:

Qwen2.5 GPT-2
âncoras (256) ortogonalidade 6,0×10⁻⁷ 3,6×10⁻⁷
âncoras explicam 35,3% 48,1%
rank efetivo / exato 792 / 788 629 / 628
top-1 / top-5 / top-10 79,0% / 98,0% / 99,5% 79,5% / 99,5% / 99,5%
top-50 100,0% 100,0%

O GPT-2 marca 99,5% em top-10 na execução com 200 palavras e 100,0% com 500. A diferença é de amostragem, não de método. No Kaggle, com a mesma população mas em 3.13, deu 100,0% — o número estável é "≥99,5%, e 100% a partir da amostra maior". Registrar a amostra de cada linha custa uma frase e evita que a diferença pareça um desacordo.

A recuperação, medida

A pergunta: dado o texto de um token, o caminho geométrico devolve aquele token — o que o BPE devolveria para ele?

Vale ler essa pergunta com cuidado, porque ela é mais fraca do que parece: o alvo já está no índice, endereçado pela mesma função que construiu o índice. Acertar prova que o espaço é coerente consigo mesmo. Não prova que ele produz algo que não estava lá — disso trata a seção seguinte.

O pipeline é o da stack. Texto vira bytes; os bytes viram uma assinatura no espaço de âncoras do modelo; o Madhava busca por desigualdade.

k Qwen2.5 GPT-2 acaso
1 79,0% 79,5% 0,0007%
5 98,0% 99,5% 0,003%
10 99,5% 99,5% 0,007%
50 100,0% 100,0% 0,03%

Zero violações de bound em todos os casos. O índice de 150 mil tokens é construído em 0,6 s.

A correção que levou o resultado de 0% para 99,5% foi de espaço, não de matemática: o índice precisa guardar a assinatura reconstruída por bytes do token, não a assinatura verdadeira dele. Índice e consulta têm de passar pela mesma base. Antes disso, o cosseno entre os dois espaços era 0,50 e a busca não podia funcionar.

O Fold Limit, termo a termo

Esta é a parte que explica tudo o resto. A condição de prova é

$$2\sqrt{1-\nu(s)}\;E[e(q)] \le \tau_K.$$

Medi os três termos no vocabulário, com queries geradas pelo caminho de texto:

r ν E[e] τ₁ LHS/τ₁ prova?
32 0,068 0,966 0,00083 2.249 não
128 0,233 0,874 0,00066 2.304 não
224 0,434 0,754 0,00086 1.326 não
512 1,000 0 0,00086 0 SIM

A prova só fecha sem compressão. A partir de r < D, a razão LHS/τ₁ fica entre 800 e 2.300 — três ordens de grandeza acima do necessário. O vocabulário de um modelo não tem manifold de baixa dimensão: 128 direções capturam 23% da variância.

Isso não é uma derrota do método. É a condição de contorno dele, e ela prediz corretamente o comportamento nos três corpora:

corpus ν efetivo prova
SIFT (128d, manifold forte) alto 100,0%
arXiv (1536d, manifold moderado) médio 25,1%
vocabulário (896d, quase-isotrópico) baixo 0% com random

O mesmo motor, os mesmos parâmetros, três respostas diferentes — e a diferença é uma propriedade do corpus, prevista pela desigualdade antes de qualquer medição.

O que funciona em cada peça

nano. O isomorfismo ℤ/256ℤ → μ₂₅₆ é exato: round-trip 6/6 em português, russo, japonês, árabe e código; homomorfia com erro 0,000/256; injeção em 128/128 bytes. A construção é correta.

xfactor. O rank efetivo bate com a eigendecomposição exata em todos os testes (792 vs 788 no Qwen; 629 vs 628 no GPT-2). A projeção é simétrica a 0,0. A idempotência degrada com o rank — 3,3×10⁻² no Qwen, 2,4×10⁻¹ no GPT-2 — por acúmulo de deflação em float32, não por erro de fórmula.

madhava. Zero violações de bound em toda a matriz. A cascata funciona: com 0,5% do corpus no pool, o recall@10 é 0,969.

âncoras. Ortonormalidade a 6×10⁻⁷. As 512 âncoras capturam entre 24% e 48% da energia das embeddings, dependendo do modelo.

O limite do histograma, e a correção

O histograma de bytes é comutativo. A assinatura de need e de ened é o mesmo vetor — e nenhum índice pode escolher entre dois vetores idênticos. Medi os erros de top-1 e todos são anagramas, com margem de score exatamente zero:

'need'   -> 'ened'    margem 0.00000
'pc'     -> 'cp'      margem 0.00000
'reward' -> 'drawer'  margem 0.00000
'fit'    -> 'ift'     margem 0.00000

A correção é fazer a posição entrar como isometria:

$$v=\sum_k R_k\,B[b_k], \qquad R_k \text{ rotaciona por } k\cdot\varphi$$

com $\varphi/2\pi$ irracional (ângulo áureo). Por ser rotação, preserva a norma exatamente — é a forma "Parseval" desta agregação. Por ser incomensurável, posições distintas não interferem construtivamente, e a soma deixa de ser comutativa.

Medido em dois modelos, com pesos reais (matriz_binding.py, 1200 palavras do GloVe, modo completo):

modelo representação top-1 top-5 top-10 anagramas (cos máx)
Qwen2.5 histograma 69,7% 96,1% 98,7% 1,0000
Qwen2.5 binding 99,4% 99,4% 99,4% 0,357
GPT-2 histograma 63,6% 96,6% 99,2% 1,0000
GPT-2 binding 100,0% 100,0% 100,0% 0,534

+29,7 pontos no Qwen, +36,4 no GPT-2. Determinístico nos dois (cinco execuções bit a bit idênticas), custo de 0,122 ms por palavra — cerca de 6× o histograma, e ainda 8× abaixo de 1 ms.

Uma nota sobre esta tabela, porque ela é a única deste texto que não fecha exatamente. A versão anterior publicava 71,6% (Qwen) e 67,8% (GPT-2) no histograma, e custo de 0,066 ms. O top-10 (98,7% e 99,2%) e a coluna de anagramas (0,3570 e 0,5341) reproduzem exatamente; os dois valores de top-1 e o custo não.

A causa é a população de palavras, e ela é grande o bastante para importar:

limite do GloVe n_aval simples Qwen top-1 GPT-2 top-1
8.000 400 154 77,9% 80,4%
8.000 1200 454 81,3% 81,3%
50.000 400 56 67,9% 57,1%
50.000 1200 155 69,7% 63,6%

O --rapido usa as 8 mil primeiras linhas do GloVe; o modo completo usa 50 mil. O top-1 varia de 57% a 81% só com essa escolha — o vocabulário do GloVe é ordenado por frequência, então as primeiras 8 mil palavras são justamente as que o BPE do modelo cobre melhor.

Varri nove tamanhos de amostra com 25 sementes cada no modo completo. 71,6% aparece (n_aval=1600, seed=16), mas com n=194 e não n=155 — ou seja, a linha publicada não veio de nenhuma combinação reproduzível de semente e amostra que eu consiga identificar. A que está na tabela acima é a que sai do comando documentado.

A conclusão não depende disso: o binding separa anagramas que o histograma não pode separar (0,357 e 0,534 contra 1,0000), e ganha de 20 a 36 pontos em top-1 em qualquer das populações.

O que isso não resolve. A acurácia não é garantia. A prova por Cauchy-Schwarz no vocabulário continua zero: o Fold Limit exige $\nu$ alto, e o vocabulário distribui sua variância por centenas de direções (23% em 128 de 896). O binding melhora a recuperação; não cria o manifold que a prova exigiria. O resultado é reprodutível e medido — não certificado.

A pergunta que o benchmark não fazia

Tudo acima é verdade e nenhuma das medições responde à pergunta que a palavra "inferência" promete. T5 tem uma estrutura particular: a consulta é o texto do token, e o alvo é o próprio token indexado. Acertar é recuperação — a informação já estava no índice, endereçada por uma função que o índice usou para se construir. Isso mede a coerência do espaço, não a capacidade de produzir algo novo.

Três medições fecham essa lacuna, e o resultado é negativo.

Texto livre. Consulta = frase inteira, índice = os 150.300 tokens. Quantos dos 10 devolvidos pertencem à frase?

frase top-10 pertinentes
A capital da França é Paris 0/10 — devolve parede, parad, paras, pasar
O rato roeu a roupa do rei de Roma 0/10 — devolve radio, road, ora, arose
the quick brown fox jumps over the lazy dog 0/10 — devolve CJK e árabe

Média: 0,0 de 10. O índice devolve o token com a massa de bytes mais parecida com a da frase — que é exatamente o que a construção pede que ele faça. A geometria não está falhando; a especificação não contém semântica.

Próximo token. A prova mais direta de inferência: dado o começo, prever o que vem depois, usando como contexto a média dos embeddings reais do prompt (a aproximação mais generosa possível, já que um transformer faz atenção, não média).

prompt esperado devolvido no top-10
A capital da França é Paris 0, 2, 1, 5, 8, 3, 4
The quick brown fox jumps ĠOh, Ðĩ, éĦħ, ĠÐķ

Nenhum acerto em três prompts. Nem o binding muda isso: reconstruindo o índice para cada representação (a comparação correta), o binding sobe de 76,7% para 100% em identidade de token e continua em 0,3/10 em generalização — o mesmo 0,3 do histograma, medido em 20 mil tokens, não no vocabulário inteiro. Ele separa anagramas, o que é real e está medido; não produz o próximo token.

Uma ressalva de redação: esse parágrafo soma dois experimentos com populações diferentes — 20 mil tokens para o par histograma/binding e o vocabulário inteiro para a frase livre. O sinal é o mesmo nos dois, mas o 0,3 daqui não é o mesmo 0,3 do parágrafo anterior, e escrever "os mesmos" sem essa nota seria mais do que os dados dizem.

O que isso quer dizer. Byte → geometria → âncoras localiza itens que já estão no índice. A ordem dos bytes carrega informação (o binding prova isso), mas ordem de bytes não é o que gera linguagem: um transformer calcula atenção sobre estados contextuais, e superposição vetorial sofre interferência entre os fatores — um limite conhecido do formalismo VSA/HRR, não um defeito de implementação. A stack é um buscador geométrico determinístico muito bom. Inferência de linguagem é outra tarefa.

O que isso significa

A stack tem uma lógica coerente e ela funciona: mede-se geometria, não se amostra probabilidade. O caminho completo — texto → bytes → assinatura → âncoras do modelo → bound → top-k — localiza o token do BPE com 99,5% de acurácia em top-10, sem invocar um tokenizador em tempo de encoding. É recuperação de token, e a seção anterior mostra por que não é mais que isso.

E o limite é igualmente preciso: o Madhava prova exclusão quando o corpus tem manifold. No vocabulário de um modelo, não tem — e aí ele opera como busca heurística, que é o que sempre foi quando o Fold Limit não fecha.

Uma ressalva sobre o que "prova" significa no índice de tokens. Rodei o motor com a configuração exata do T5 (basis=random, stage1_dim=64, k1_fraction=0.05, k2_max=2000), 150.300 tokens, k=100, e separei os descartes por origem. A fração certificada não é um número — é uma função da dimensão:

âncoras d bound/query prefilter/query certificado
128 128 145.286 3.714 97,5%
256 256 91.729 57.271 61,6%
384 384 55.284 93.916 37,2%
512 512 35.165 113.535 23,6%

Isso não é ruído de amostragem: é a desigualdade do Fold Limit se tornando mais difícil de satisfazer conforme o espaço ganha direções. $2\sqrt{1-\nu}\, E[e] \le \tau_k$ — quanto maior $d$, menor $\nu$ para o mesmo $r$ e maior $E[e]$, e a condição deixa de fechar. A curva cai monotonicamente, e cai pelo motivo que a própria desigualdade prevê.

O número de 7,6% que eu havia medido antes é o mesmo fenômeno num ponto diferente (512 âncoras com consulta de palavra); a leitura correta não é "o bound certifica 7,6% do vocabulário", e sim "o bound certifica o que a dimensão permite, e no vocabulário do Qwen isso vai de 97,5% a 23,6% conforme a base escolhida".

bound_violations = 0 é verdade e é consistente por construção em todos os pontos da curva — é o que o próprio código do Madhava documenta desde agosto ("a garantia é bound-correctness dentro do pool, não recall global"). O número que informa alguma coisa é quanto foi efetivamente certificado, e chamar "zero violações" de certificado sem esse denominador é ler consistência interna como garantia.

As duas coisas são verdade ao mesmo tempo, e a desigualdade diz qual vale para qual corpus antes de qualquer benchmark.

Dois defeitos encontrados ao refazer as medições

Convenção de bytes. O índice aplica .replace("Ġ", " ") antes de codificar; a consulta fazia t.encode("utf-8") cru. Para um token como Ġthe o índice guarda o byte 0x20 e a consulta mandava 0xC4 0xA0. Medido nos 300 tokens que têm Ġ:

consulta top-1
com a convenção do índice 87,7%
crua, como estava 3,7%

O número publicado sobreviveu porque a população do T5 vem do GloVe e filtra tokens sem Ġ — a correção certa aplicada a um subconjunto que esconde o problema. Corrigido em benchmark_stack_real.py e benchmark_stack_colab.py.

A linha r = D do T6 era um print com os números escritos à mão. A conclusão a que ela serve está correta — $r=D$ é a identidade, $\nu=1$ e $E[e]=0$ valem por definição, e a prova fecha trivialmente. Mas uma linha de tabela que não foi medida não é evidência. Agora ela é calculada, marcada como identidade, e excluída da conta de fecha_com_compressao (senão a resposta seria sempre SIM e a pergunta perderia o sentido).

A certificação do bound não é um número. Ao levar esse resultado para o notebook do Kaggle, três medições da mesma pergunta deram valores diferentes — 7,6%, 35,4% e 49,9%. Investigar em vez de escolher um foi o que revelou o fenômeno: a fração certificada é uma função da dimensão, e a réplica em numpy que eu havia escrito dava 49,9% porque omitia o stage-2 do motor real (35,4%). O notebook passou a usar o motor, e a reportar a curva.

Nenhum desses muda a conclusão do texto. Mudam o que se pode afirmar sobre ela.

Como reproduzir

No Colab, agora

benchmark_stack_colab.py — cole o arquivo inteiro numa célula do Google Colab e execute. Ele instala as dependências, baixa os pesos do Qwen2.5 e os dados (GloVe + SIFT), e roda as oito frentes. Saída de uma execução completa (--rapido, CPU):

 T1  256 âncoras | ortogonalidade 6.0e-07 | explica 35.3% da assinatura
 T2  round-trip 6/6 | 128/128 fases | homomorfia erro 0.000/256
 T3  rank 792 (exato 788) | ‖Pᵀ−P‖ 0.0e+00
 T4  random       prova  89.8% | viol 0 | 129.59 ms
 T4  pca_corpus   prova 100.0% | viol 0 | 135.35 ms
 T5  top-1 79.0% | top-5 98.0% | top-10 99.5% | top-50 100.0%
 T6  Fold Limit fecha com compressão: NÃO (só em r=D)
 T7  generalização (tokens da frase no top-10): 0.0/10
 T8  certificação por bound: 97.5% (d=128) -> 23.6% (d=512)

Tempo: 356 s de ponta a ponta nesta máquina (CPU, sem GPU), incluindo o download dos pesos e dos dados. A versão anterior deste texto dizia 26 s — esse número vinha de uma execução com tudo em cache e sem T7, e não é o que alguém vê na primeira vez. Preferi o número que se reproduz.

No Kaggle

winnex-benchmark-integral-da-stack — o mesmo benchmark em quatro frentes, rodando no kernel do Kaggle (Python 3.13), com o motor Madhava real quando a ABI permite. É a versão mais direta: abre, clica em Run All, e o relatório sai montado dos números medidos.

Não precisa de torch. O leitor de safetensors é binário e decodifica bfloat16 deslocando 16 bits — o checkpoint do Qwen é bf16 e o numpy não tem dtype para ele. Verifiquei o decodificador contra o safetensors.torch: 290 tensores, idênticos bit a bit, sem carregar 800 MB de torch.

Se o kernel não for 3.12, o script detecta — os wheels de winnex-nano e winnex-xfactor só existem para cp312. Ele então instala o Python 3.12, cria um venv, instala as dependências ali e reexecuta o benchmark nesse interpretador. Testei a partir de um Python 3.10 limpo: completa as seis frentes em 270 s com os mesmos números.

Bind de ordem

winnex_binding_matriz.ipynb — compara histograma e binding de ordem em Qwen2.5 e GPT-2, com análise de anagramas, determinismo e custo. Também no Kaggle: winnex-binding-matriz.

Localmente, com a matriz completa

Armadilhas que custaram tempo e estão tratadas no código: o Qwen codifica espaço como Ġ (U+0120) e aplica byte-encoding duplo em UTF-8; forward.h calcula head_dim sem guarda de zero (SIGFPE em qualquer config GPT-2); o ForwardEngine guarda ponteiro cru para o Safetensors; e OMP_NUM_THREADS precisa ser fixado antes do import do motor.

Cada teste declara antes de rodar qual resultado o falsificaria, e o relatório é montado dos números. É a oitava vez que aplico essa regra neste texto — e as que mais me corrigiram foram as que me fizeram desmontar um enquadramento importado e medir o que a stack realmente propõe.

Um benchmark que nunca contraria quem o escreveu provavelmente não está medindo nada.

Continue lendo

AnteriorΨQRH: o que a curvatura prova, e o que o benchmark não mediu

← todos os artigos