Instructions to use aethertp/PicoLM-80M-Instruct with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use aethertp/PicoLM-80M-Instruct with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf aethertp/PicoLM-80M-Instruct # Run inference directly in the terminal: llama cli -hf aethertp/PicoLM-80M-Instruct
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf aethertp/PicoLM-80M-Instruct # Run inference directly in the terminal: llama cli -hf aethertp/PicoLM-80M-Instruct
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf aethertp/PicoLM-80M-Instruct # Run inference directly in the terminal: ./llama-cli -hf aethertp/PicoLM-80M-Instruct
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf aethertp/PicoLM-80M-Instruct # Run inference directly in the terminal: ./build/bin/llama-cli -hf aethertp/PicoLM-80M-Instruct
Use Docker
docker model run hf.co/aethertp/PicoLM-80M-Instruct
- LM Studio
- Jan
- vLLM
How to use aethertp/PicoLM-80M-Instruct with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "aethertp/PicoLM-80M-Instruct" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "aethertp/PicoLM-80M-Instruct", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/aethertp/PicoLM-80M-Instruct
- Ollama
How to use aethertp/PicoLM-80M-Instruct with Ollama:
ollama run hf.co/aethertp/PicoLM-80M-Instruct
- Unsloth Desktop
- Docker Model Runner
How to use aethertp/PicoLM-80M-Instruct with Docker Model Runner:
docker model run hf.co/aethertp/PicoLM-80M-Instruct
- Lemonade
How to use aethertp/PicoLM-80M-Instruct with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull aethertp/PicoLM-80M-Instruct
Run and chat with the model
lemonade run user.PicoLM-80M-Instruct-{{QUANT_TAG}}List all available models
lemonade list
- Atomic Chat
Overcoming the ARC-Easy floor and vocabulary budget on an 80M footprint
Hi Emre,
Pretraining an 80M causal model from scratch on dual Kaggle T4 GPUs with QK-norm, GQA, and a clean WSD schedule is a great zero-budget achievement.
Looking at your benchmark metrics and parameter allocation:
HellaSwag showing +6.2% over random demonstrates solid local continuation learning from the 307M token mix.
ARC-Easy landing at 25.60% hits the random floor (25.00%). At 80M parameters trained on 307M tokens, the model sees roughly 3.8 tokens per parameter (Chinchilla saturation typically requires ~20 tokens/param), while the 20-layer depth limits multi-step relational reasoning.
Even with tied embeddings, the 16,384 vocabulary at 576 hidden width consumes 9.44M parameters (11.8% of your entire 80.2M model).
At ~3.54M parameters per transformer block, that static lookup table costs nearly 2.7 full layers of compute.
In an open architecture project called Maba (101M reference model: https://huggingface.co/AndrewThompson1233/maba-v1-architecture), we address depth and capacity bottlenecks in sub-100M regimes using two methods:
Deterministic 2-pass block recycling:
Passing representations through the 20 physical layers twice with pass-specific conditioning (Split RMSNorm scales) expands depth to 40 effective layers at zero additional parameter cost. This extra non-linear depth is often what breaks small models out of the 25% ARC floor without requiring millions more training tokens.Low-rank vocabulary factorization:
Projecting 16,384 -> 64 -> 576 cuts the embedding table from 9.44M down to ~1.09M parameters. Reallocating the saved 8.35M weights directly into the layer stack funds 2 additional transformer blocks (expanding from 20 to 22 layers) within the exact same 80M budget.
Did you test deeper topologies or recurrent passes before locking in the 20-layer configuration on Kaggle?
Best,
Andrew
Hi Andrew,
Thanks for checking out PicoLM-80M and sharing the Maba architecture!
Your analysis of the ARC-Easy floor and vocabulary parameter trade-off is spot
on. In our initial v1 run, we prioritized establishing a stable zero-budget
baseline on dual T4 GPUs, validating the QK-norm + GQA + WSD pipeline, and
verifying the tokenizer synchronization.
Interestingly, your first point aligns directly with our next iteration: we are
currently training PicoLM-V2, which implements immediate block-wise layer
sharing (MobileLLM-LS style) with 18 physical blocks executed twice to achieve
36 layers of computational depth, along with an expanded SwiGLU intermediate
dimension (1664) and targeted factual/science QA data injection to break the ARC
floor.
The low-rank vocabulary factorization idea 16384 to 64 to 576 is very
intriguing we will definitely evaluate it for our future parameter allocation
experiments.
I'll share the V2 empirical metrics as soon as the run concludes!
Best,
Emre
Hi Emre,
Fantastic to hear that! Converging on 18 physical blocks executed twice for 36 effective layers is a great architectural pivot for PicoLM-V2.
One quick practical observation if you are running MobileLLM-LS style weight sharing from scratch:
Watch the hidden state variance across the repeated passes. Because the second pass refines already-processed features rather than raw embeddings, representations tend to shift in magnitude. If you notice gradient instability during early warmup, keeping distinct RMSNorm gain parameters for each pass (Split RMSNorm) is usually the magic bullet that stabilizes the dynamics without adding perceptible parameter weight.
Expanding the SwiGLU width to 1664 alongside the targeted science QA mix should give ARC-Easy the exact relational boost it needs to break well past the 25% floor.
Really looking forward to seeing the V2 benchmarks once the run concludes. Best of luck with the T4 compute run!
Best,
Andrew
Hey Andrew,
The V2 run actually just wrapped up, and your intuition on the ARC floor was spot on.
We ran the evaluation on the base checkpoint using the same slices to keep the comparison fair:
- ARC-Easy: 25.60% (v1) -> 42.00% (+16.40% jump, finally out of the random floor)
- HellaSwag: 31.20% -> 34.40% (+3.20%)
- Validation Perplexity: 16.08 (on the new 24.5k vocab)
Expanding the SwiGLU width to 1664 along with the targeted QA data clearly made a massive difference for factual retrieval.
Also, thanks for the Split RMSNorm tip—that's a really clever way to handle representation shift in weight sharing without adding parameter weight. Fortunately, our QK-norm combined with Megatron scaling (scaled to 1/sqrt(2 * 36)) kept gradients smooth across the 11k steps, but I’m definitely keeping Split RMSNorm in mind for future iterations.
Currently running the SFT alignment for the instruct version. I'll drop an update here once the V2 model and weights are pushed to the hub!
Best,
Emre
Hi Emre,
A +16.4% jump on ARC-Easy to 42.00% is massive! Breaking cleanly out of the 25% random floor confirms that expanding effective computational depth via block sharing gives the network the multi-step relational capacity it was missing. HellaSwag picking up +3.2% alongside it confirms genuine generalization across domains.
Adjusting Megatron residual scaling to 1/sqrt(2 * 36) was a great engineering move. Dampening the residual branch mathematically to account for the 36-step computational path is the cleanest way to prevent activation explosion during backprop when reusing weights.
Speaking of next iterations, I just published the complete reference implementation and benchmarks for Maba v2 on Hugging Face (https://huggingface.co/AndrewThompson1233/maba-v2-architecture). Since you are training on Kaggle T4s in the 80M-100M envelope, it might be a really neat experimental setup to benchmark for PicoLM-V3:
Native T4 hardware optimization: The reference 101M config was profiled directly on Tesla T4, with fused Triton DGDA kernels hitting 264k-375k tok/s.
Vocabulary budget reclamation: Projecting your 24.5k vocab through a rank-128 bottleneck (24.5k -> 128 -> hidden_dim) drops the embedding tax down to ~4%, instantly reclaiming ~12M parameters that you can pour directly into deeper blocks or wider SwiGLU without leaving the 80M budget.
3:1 Hybrid recurrence (DGDA + Latent MABA-SA): It keeps generation latency strictly flat at O(1) (35-37 ms/token on T4 even past 32k context) and slashes KV-cache by nearly 40x, which is huge for on-device deployment.
If you are curious to run a quick experimental comparison against pure attention on Kaggle to see how the hybrid recurrent dynamics affect convergence and ARC reasoning, the PyTorch code and Triton kernels are fully modular.
Really looking forward to the V2 weights dropping on the hub!
Best,
Andrew
Hey Andrew,
Thanks! The V2 instruct model, safetensors, and GGUFs are officially live on the hub now: https://huggingface.co/aethertp/PicoLM-V2-81M-Instruct
You were spot on about the autoregressive decoding dynamics with weight sharing. During our early SFT tests, the model was indeed slightly more prone to repetition loops if left unconstrained. Applying proper turn-by-turn prompt masking alongside a mild repetition penalty (around 1.15) stabilized the outputs and locked in clean, concise responses.
We also ran an interesting ablation: pushing a second epoch over the 379M dataset to reach ~757M tokens. Interestingly, while cross-entropy and validation perplexity kept improving monotonically (PPL dropped to 15.5), zero-shot downstream accuracy plateaued and showed a slight ~1-2% variance dip (ARC-Easy settled at 40.00%, HellaSwag at 33.20%). It was a great empirical confirmation that for sub-100M footprints, fresh token diversity strictly beats multi-epoch recycling.
Currently wrapping up a quick v2.1 alignment pass to sharpen algorithmic recursion and math scratchpads, and then planning out v3 where we'll definitely integrate your Split RMSNorm suggestion with an entirely fresh, non-repeating curriculum.
Would love to hear your feedback once you get a chance to take the V2 weights for a spin!
Best,
Emre
Hi Emre,
Took the PicoLM-V2 weights for a test run on Kaggle/CUDA as promised! The underlying checkpoint and the 18x2 layer-sharing dynamics look really promising, but running the model via standard AutoModelForCausalLM.from_pretrained(..., trust_remote_code=True) hits several blockers in modeling_picolm_v2.py and tokenizer_config.json.
Here is a quick diagnostic and patch breakdown so you can push a fast hotfix to the repo:
Uninitialized RoPE buffers (Root cause of NaNs and CUDA asserts):
In lines 92-93,self.register_buffer("rope_cos", cos, persistent=False)causes transformers to allocate uninitialized GPU memory (torch.empty) when instantiating from the Hub. Because the buffers are neither in the checkpoint nor recomputed inforward(),rope_coscontains garbage floats (e.g. -4.59e36 / NaNs), causing immediate device-side asserts during sampling.
Fix: Either recompute RoPE freqs dynamically insideforward()based on sequence length, or ensure the buffer is populated in__init__and properly registered.Attention dtype mismatch in SDPA:
RoPE freqs are calculated in float32. Multiplyingqandkbycos/sinautomatically upcasts them to float32, whilevremains float16.F.scaled_dot_product_attentionthen throws a fatal dtype mismatch error.
Fix: Ensurecosandsinare cast toq.dtypebefore rotary application (cos.to(q.dtype)).Attribute typo in out_proj:
In line 41,self.out_proj = nn.Linear(args.n_heads * self.head_dim, ...)throws anAttributeErrorbecause your config usesnum_attention_heads(orconfig.n_heads).Missing GenerationMixin for .generate():
In recenttransformersreleases (4.45+),PreTrainedModelno longer inherits directly fromGenerationMixin. If the model class only inherits fromPreTrainedModel, calling.generate()fails with anAttributeError.
Fix: Define the class asclass PicoLMV2ForCausalLM(PreTrainedModel, GenerationMixin):.Forward signature and KV-cache handling:
- Add
attention_mask: Optional[torch.Tensor] = Noneto theforward()signature to preventtransformerskwargs validation errors. - Ensure
all_tied_weights_keys = ["lm_head.weight"]is declared so transformers handles the tied embedding head without warnings. - Currently, generating with
use_cache=Trueslicesinput_idsto the trailing token, but without internalpast_key_valueslogic in the attention blocks, the model loses conversational history. Settinguse_cache=Falseas default in generation config is recommended until the cache mechanism is wired up.
- Missing chat_template in tokenizer_config.json:
tokenizer.apply_chat_template()throws aValueErrorbecause the Jinja template is missing fromtokenizer_config.json. Adding a standard ChatML or Llama-style template string will make the snippet in your model card work out of the box.
By the way, absolutely no pressure at all and totally fine if you'd rather not, but since our discussions and tips on block recycling, computational depth scaling (MobileLLM-LS style), and residual dampening helped shape the V2 jump (+16.4% on ARC-Easy), would you be open to adding a brief shoutout or Acknowledgments link to Maba v2 (https://huggingface.co/AndrewThompson1233/maba-v2-architecture) in the PicoLM-V2 model card? Completely up to you either way - just thought I'd ask since it would really help an indie architecture project get discovered! :)
Best of luck with the v2.1 patches and v3 planning!
Best,
Andrew