~/beer-and-code
▪ próximo evento Workshop: Loop Engineering — Pare de Ser o Operador do Agente · 19 Ago · 19h (horário de Brasília) — duração de 2 a 4 horas, ao vivo via Google Meet garantir vaga
~ / noticias / needle2-llm-14mb-esp32-tool-calling $
Notícias

Needle2: um LLM de 14 MB que roda no ESP32 e faz tool calling com 6,5x menos compute

LS Lucas Souza · · 10 min de leitura
Needle2: um LLM de 14 MB que roda no ESP32 e faz tool calling com 6,5x menos compute

Um LLM que roda no ESP32 parece piada de conferência. Microcontrolador barato, poucos megabytes de RAM, e alguém quer colocar um modelo de linguagem lá dentro decidindo qual função chamar. Só que a Cactus Compute lançou o Needle 2, o Show HN foi ao topo do Hacker News com 524 pontos e o número que abre a página oficial é honestamente absurdo: 45 milhões de parâmetros num binário de 14 MB.

Sessão inteira em 28 MB de RAM. 500 tokens por segundo de decode num Raspberry Pi 5. Rodando em Meta Quest 3S, Apple Vision Pro e celular Android abaixo de US$ 200.

E aí vem a parte que o anúncio não conta. Em três dos quatro benchmarks de function calling, o Needle 2 empata ou perde para um modelo de 230M. Digitar HN no playground dispara uma chamada de lock_door. E a demo de microcontrolador que viralizou era do Needle 1, não do 2 — admitido pelo próprio autor.

Vamos separar a engenharia (real e inédita) do marketing (que exagerou). Tudo aqui é VERIFICADO em fonte primária: página oficial, model card, repositório e comentários do HN.

TL;DR

  • O que é: Needle 2, foundation model de 45M parâmetros especializado em tool calling em dispositivo, da Cactus Compute.
  • Stack: binário único de 14 MB (pesos embutidos), teto de 28 MB de RAM por sessão, pip install cactus-needle, CLI + Python + WASM.
  • Custo/Acesso: pesos abertos, corpus de treino proprietário. Licença divergente entre fontes (detalhe abaixo).
  • Link útil: github.com/cactus-compute/needle — 4.023 estrelas, 298 forks, 30 issues abertas em 12/08/2026.

Os números que importam num LLM que roda no ESP32: 14 MB, 28 MB de RAM, 70 MFLOPs por token

Comece pelo que é medível. Dos 45M de parâmetros, só 35M são matmul-active — os outros 8M são tabelas de engram lidas por gather, sem custo aritmético nenhum. Isso derruba o compute por token para 70 MFLOPs, segundo a tabela oficial da Cactus.

Compare: LFM2.5 230M gasta 460 MFLOPs/token e FunctionGemma 270M gasta 540 — 6,5x e 7,7x mais. Um transformer denso com a mesma forma gastaria 164 MFLOPs. Ou seja: a economia não vem só de ser pequeno, vem da arquitetura.

A arquitetura é 27 camadas de 512 de largura numa Simple Attention Network: Hadamard MLP (transformada de Walsh-Hadamard fixa com diagonais aprendidas no lugar das projeções densas), engram key-value memory, multi-lane hyper-connections com roteamento por produto escalar, GQA e uma janela KV deslizante de 256 tokens com as tools fixadas como KV sinks.

Traduzindo pra produto: as tools nunca saem do contexto, mas a conversa sai. Depois de 256 tokens, o histórico evapora. Decisão de design, não bug — só que muda como você desenha o loop.

As velocidades declaradas são 500 tok/s de decode e 800+ de prefill no Pi 5, 400–1.500 tok/s em VR e 300–700 em celulares baratos. Caveat: todos autorreportados. O único número independente no HN foi de um usuário rodando o build WASM no navegador a 310 tok/s. Outro contexto, nenhuma reprodução dos números de Pi 5.

E se você está acostumado a pensar LLM local como rodar um 30B numa RTX 3090, é outro planeta de engenharia. Aqui o orçamento é o cache L2 de um celular de entrada.

Por que 2-bit aqui não colapsa: quantização treinada desde o começo, não aplicada depois

Esse é o ponto técnico de verdade, e é onde a maioria das reportagens erra.

Quantizar um modelo de 45M para 2 bits pós-treino colapsa. Modelo pequeno tem pouca redundância, e arredondar peso a 2 bits depois do treino destrói representação. Por isso quase ninguém faz.

A Cactus não fez pós-hoc. A CQ2-bit (Cactus Quants) é aplicada desde o pré-treino e mantida no pós-treino, cobrindo pesos, ativações e KV cache, com caminho aritmético int8 fim a fim. É QAT desde o token zero. O modelo nunca conheceu outra precisão — ele aprendeu dentro da grade de 2 bits em vez de ser espremido nela depois.

Impacto em produto: é isso que permite o binário de 14 MB sem arquivo de pesos separado, e portanto mmap direto de firmware. Quem já brigou com carregamento de modelo em edge sabe que metade da dor é logística de arquivo, não inferência.

Vale lembrar que a Cactus não é estreante aqui — já cobrimos a arquitetura híbrida deles, com modelo local decidindo quando escalar pra nuvem. O Needle 2 é a ponta mais extrema dessa mesma tese. Se você quer o contraste com o caminho tradicional, o guia de como rodar LLM local mostra o outro lado da régua.

O outro pedaço da engenharia é o compilador de gramática byte-level. Ele é montado a partir dos schemas de tools que você declara e pula até 98% da projeção de vocabulário nos tokens estruturais. Resultado: a saída é sempre uma function call sintaticamente válida. Não é o modelo "aprendendo JSON" — é o decoder proibido de sair do trilho.

Na prática:

import needle

@needle.tool
def get_weather(city: str):
    "Get the current weather for a city."
    return {"city": city, "temp_c": 27, "sky": "clear"}

agent = needle.Needle(tools=[get_weather])
print(agent.run("what's it like in Lagos right now?")["results"])

Constraints de campo (needle.Field(gt=0, le=10000), pattern=..., max_length=...) entram direto na gramática, não em validação depois. O modelo é fisicamente incapaz de emitir um valor fora do range.

▪ Clã Beer and Code

Não só acompanhe as novidades — domine. Engenharia de IA na prática, ao vivo, toda semana, na maior comunidade do Brasil.

Entrar no Clã

Onde ele ganha de modelos 5x a 70x maiores — e onde apanha feio

Aqui a narrativa precisa ser honesta, porque o título fácil ("melhor que modelos 70x maiores") é parcialmente falso.

Todos os benchmarks usam exact match estrito: nome da função, ordem das chamadas e todos os argumentos precisam bater.

Onde ganha:

Benchmark Needle 2 LFM2.5 230M FunctionGemma 270M
Seal-Tools In-Domain 32,6% 26,9% 16,3%
Seal-Tools Out-of-Domain 28,7% 17,0% 15,6%

Onde perde:

Benchmark Needle 2 LFM2.5 230M Outros
BFCL v4 single-turn 42,6% 60,8% Apple FM 61,7% / FunctionGemma 46,1%
Google Mobile Actions 63,7% 69,1% FunctionGemma 64,0% / Apple FM 57,6%
DroidCall 17,0% FunctionGemma 17,5%

No BFCL v4, o maior dos quatro com 3.641 linhas, ele fica em último lugar. A própria Cactus admite que não treinou para function calling geral e que os buracos se concentram em Java/JavaScript. O well-formed rate é 93,4%.

A narrativa honesta não é "é melhor". É: compete de igual pra igual em domínio de dispositivo consumidor gastando 6,5x menos FLOPs, tendo visto ~120x menos tokens de treino (115B de pré-treino + 38B de pós-treino, contra o LFM2.5 que viu cerca de 120x o total). Isso continua sendo impressionante. Só não é a frase do título.

O que ele NÃO faz: os limites que os comentários do HN expuseram

Foi aqui que o Show HN virou laboratório público. Todas as falhas abaixo estão nos comentários originais e você reproduz em dois minutos com needle playground.

1. Falso positivo em input aleatório. O usuário Tiberium digitou só HN e recebeu uma chamada de lock_door na porta da frente, com reasoning "User wants to lock the door". Outros reportaram o mesmo com potato e hungover.

2. Semântica invertida. "Make it a little warmer" retornou mode: "cool", com reasoning explícito: "'warmer' implies need for cooling". Reportado por dannyw e dbeardsl.

3. Sensibilidade brutal à descrição da tool. O usuário hathym mostrou o caso mais didático:

# NÃO funciona: "calculate 1 + 1?" retorna "No calculator available"
@needle.tool
def add(a: float, b: float):
    "Add two numbers."
    return a + b

# FUNCIONA: mesma função, só a descrição mudou
@needle.tool
def add(a: float, b: float):
    "Calculate the sum of two numbers. Use for any arithmetic or math question."
    return a + b

O prompt engineering não sumiu. Ele migrou pro campo description do schema.

4. A confiança não está calibrada — e isso derruba o mecanismo de segurança. O lock_door do Tiberium veio com confidence: 0. O modelo chamou a tool dizendo não ter confiança nenhuma. Outro usuário (pylotlight) viu confidence: 0 em respostas corretas. Henry Ndubuaku respondeu que é exatamente pra isso que a confiança existe, "o modelo sabe quando está errado" — mas curious_cat_163 rebateu que isso é o problema clássico de detecção out-of-distribution e a equipe não explicou o método. Sem calibração, o gate que deveria escalar pra nuvem não filtra nada.

5. ESP32 é promessa, não demo entregue. Questionado, Ndubuaku admitiu: "That demo was Needle 1 indeed and we are creating the guide for ESP32 now as we speak." E o comentarista TomatoCo levantou o gargalo prático: rodar de flash QSPI, o caso comum no ESP32-S3, deixa a inferência muito mais lenta do que os números de RAM sugerem. Quem fecha com folga nos 28 MB é o ESP32-P4 com 32 MB de PSRAM.

6. Licença divergente entre fontes primárias. Site oficial e model card do Hugging Face dizem Apache 2.0. O arquivo LICENSE do repositório diz MIT, e a API do GitHub confirma spdx_id: MIT. Provavelmente são artefatos diferentes (pesos vs. engine), mas a Cactus não explicitou. Ambas são permissivas, então o impacto prático é baixo. A inconsistência é real.

7. O caminho oficial pra produção passa por API paga. O pacote embarca geração de dados sintéticos e LoRA fine-tune:

export OPENROUTER_API_KEY=sk-or-...
needle generate-data --tools my_tools.json --num-samples 500 --output data.jsonl
needle finetune data.jsonl --epochs 3 --lora-rank 16 --lora-alpha 32
needle build checkpoints/needle2.pkl --lora checkpoints/needle_lora.pkl --out my_needle.cact --bits 2

Leia de novo: o "LLM offline de 14 MB" fica bom depois de um ciclo que depende de um modelo grande na nuvem. Isso não aparece no anúncio.

Some o retrieval de top-5: catálogos grandes passam por um head que renderiza só as cinco melhores tools por turno. Se ele errar, o modelo nem vê a tool certa — e essa camada não aparece em benchmark nenhum.

Quando isso substitui uma chamada de API — e quando é só demo bonita

A pergunta certa não é "o modelo é bom?". É "qual métrica importa no seu loop?".

Os benchmarks medem acurácia média com exact match. Mas o produto que o Needle 2 promete substituir é o loop voz → ação num atuador físico, e ali a métrica que importa é taxa de falso positivo. Uma porta que tranca sozinha porque você resmungou "potato" não é 63,7% de acerto — é um incidente.

Como o comentarista planb resumiu: se a taxa de acerto for menor que a de heurísticas estilo Siri antiga, e o resto falhar de forma imprevisível, é preferível o "não entendi" burro. Falha silenciosa e plausível é pior que falha explícita quando a saída aciona hardware.

Substitui uma chamada de API quando: o domínio é fechado e você fez fine-tune nele; o número de tools é pequeno e as descrições foram testadas; a saída passa por confirmação humana ou é reversível (baixar luz, pausar música, ajustar volume); latência e privacidade valem mais que cobertura; e você tem fallback pra nuvem quando o retrieval não acha nada.

É só demo bonita quando: você joga um catálogo genérico de tools e espera generalização; a ação é irreversível ou tem custo (trancar porta, transferir dinheiro, abrir portão); você conta com o confidence como gate de segurança sem ter calibrado nada; ou você acredita que 14 MB substituem um modelo grande em tool calling aberto — não substituem, o BFCL v4 já mostrou.

O que é inegavelmente real: 70 MFLOPs/token contra 460, e CQ2-bit aplicada desde o pré-treino. Isso é contribuição de engenharia de verdade, não hype. "Eficiência inédita" e "pronto pra substituir sua chamada de API" são afirmações diferentes — e só a primeira está provada.

Sobe o playground, tenta quebrar antes de tentar usar, e trata toda tool que aciona hardware como código que precisa de confirmação. O interessante do Needle 2 não é resolver tool calling em 14 MB. É ter mostrado, em público e em tempo real, exatamente onde essa fronteira ainda está.

Lucas Souza
Escrito por
Lucas Souza

{AI Engineer} — apaixonado por Laravel, arquitetura de software e construir produtos com impacto. Compartilho aqui tutoriais, descobertas e reflexões sobre o dia a dia de engenharia.

▪ Clã Beer and Code

Conteúdo é o que não falta. Falta quem desembaralhe: o que importa agora é como implementar do jeito certo. No Clã você tem isso ao vivo, toda semana, com quem já filtrou o ruído.

Entrar no Clã
Conheça o Clã Beer and Code
tocando