Instructions to use sanjayram-a/nanoagent-15m with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use sanjayram-a/nanoagent-15m with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="sanjayram-a/nanoagent-15m") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("sanjayram-a/nanoagent-15m", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use sanjayram-a/nanoagent-15m with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "sanjayram-a/nanoagent-15m" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "sanjayram-a/nanoagent-15m", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/sanjayram-a/nanoagent-15m
- SGLang
How to use sanjayram-a/nanoagent-15m with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "sanjayram-a/nanoagent-15m" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "sanjayram-a/nanoagent-15m", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "sanjayram-a/nanoagent-15m" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "sanjayram-a/nanoagent-15m", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use sanjayram-a/nanoagent-15m with Docker Model Runner:
docker model run hf.co/sanjayram-a/nanoagent-15m
NanoAgent-15M
A 15M-parameter Llama-style decoder-only transformer for chat and structured tool calling, trained end-to-end on a single RTX 3050 Laptop GPU (4GB VRAM). Built for local edge deployment (~58MB per fp32 checkpoint).
- Full training code + data pipeline:
https://github.com/sanjayram-a/nanoagent-15m - Interactive training curves for every run below live under this repo's Training metrics tab
This is a 15M model. Grade the format (stops at
<|im_end|>, well-formed<tool_call>{β¦}</tool_call>blocks, stays on topic a sentence or two), not GPT-level polish.
Model details
| Architecture | Llama-style decoder-only (transformers.LlamaForCausalLM) |
| Hidden / layers / heads | 384 / 8 / 6 Q + 2 KV (GQA 3:1), SwiGLU 1024 |
| Context length | 1024 tokens (prompt + reply combined) |
| Vocab | 6,144 byte-level BPE, custom-trained (nanoagent_tokenizer/) |
| Positional encoding | RoPE (theta 10,000); RMSNorm; tied word embeddings |
| Parameters | .pt) |
| Chat format | <|im_start|>{role}\n{content}<|im_end|>; tools in <tools>β¦</tools>; calls in <tool_call>{β¦}</tool_call>; results in <tool_response>β¦</tool_response> |
Checkpoints in this repo
| File | Variant | Val loss | Val ppl |
|---|---|---|---|
runs/nanoagent_15m/final_15m_model.pt |
Base (pretrained, no SFT β use with chat.py --raw) |
3.9772 | 53.37 |
runs/nanoagent_15m/best_model.pt |
Base, best-val snapshot | 3.9791 | ~53.5 |
runs/nanoagent-15m-sft/sft_chat_max_final.pt |
SFT run 1 (blended 409,760-row mix) β recommended chat + tool weights | 1.7348 | 5.67 |
runs/nanoagent-15m-sft2/checkpoints/latest.pt |
SFT run 2 / instruct, full training checkpoint (model_state + optimizer) |
1.4783 | 4.39 |
nanoagent_tokenizer/ |
Tokenizer (tokenizer.json, tokenizer_config.json) β required by every checkpoint |
β | β |
Base pretraining β final_15m_model.pt
Trained tokens (read from TensorBoard + training_summary.json)
| Metric | Value |
|---|---|
| Tokens seen | 999,948,288 (~1B) |
| Optimizer steps | 15,256 (batch 16 Γ 1024 Γ grad-accum 4 = 65,536 tok/step) |
| Stage 1 β Stage 2 | 3,051 steps @ 200M tokens β remainder @ 800M tokens |
| Train loss | 8.18 β 4.02 |
| Val loss | 6.19 β 3.98 (best 3.9791, final 3.9772, ppl 53.37) |
| Throughput | ~37β38K tok/s on RTX 3050 Laptop 4GB |
| LR schedule | warmup 1,000 steps to 6e-4, cosine decay to 6e-5 |
| Interruption | crashed once at step 8,239 (inf grad norm, fp16 overflow), resumed from emergency checkpoint to completion |
Datasets (from curriculum_meta.json + run log)
Packed to train.bin (1,000,000,000 tokens, 2000MB) + val.bin (10,000,000 tokens, 20MB).
Acquisition targets below include +15% selection and +15% acquisition margins; the sampler
never shuffles across the 200M-token stage boundary.
| Source | HF dataset (config / split) | Train target (tokens) | Val target (tokens) | Stage 1 share | Stage 2 share |
|---|---|---|---|---|---|
| l3 | openbmb/Ultra-FineWeb-L3 (Ultra-FineWeb-L3-en-Multi-Style-Synthetic / train) |
409,975,000 | 3,967,500 | 35% | 30% |
| fineweb | HuggingFaceFW/fineweb-edu (sample-10BT / train, score β₯ 3) |
357,075,000 | 3,306,250 | 35% | 25% |
| cosmo | HuggingFaceTB/smollm-corpus (cosmopedia-v2 / train) |
330,625,000 | 3,306,250 | 25% | 25% |
| code | openbmb/UltraData-Code (UltraData-Code-L2 / py) |
224,825,000 | 2,645,000 | 5% | 20% |
Documents selected: 12,102 validation / 251,506 stage-1 / 969,804 stage-2.
SFT run 1 β sft_chat_max_final.pt (recommended)
Trained tokens (read from TensorBoard)
| Metric | Value |
|---|---|
| Tokens seen | 409,544,800 (~410M, ~1 epoch over the mix) |
| Optimizer steps | 12,500 |
| Train loss | 6.62 β 1.70 |
| Val loss | 2.36 β 1.79 (final 1.7348, ppl 5.67) |
Datasets (409,760 raw rows, single blended pass + 15% tool-context negatives)
| Source | HF dataset (config) | Rows | Share |
|---|---|---|---|
| instruct | HuggingFaceTB/smoltalk (smol-magpie-ultra) |
150,000 | 36.6% |
| worldqa | HuggingFaceTB/ultrachat_questions_about_world |
86,000 | 21.0% |
| xlam | Salesforce/xlam-function-calling-60k (gated β needs an accepted-terms token) |
60,000 | 14.6% |
| glaive | glaiveai/glaive-function-calling-v2 |
47,500 | 11.6% |
| summarize | HuggingFaceTB/smoltalk (smol-summarize) |
34,000 | 8.3% |
| rewrite | HuggingFaceTB/smoltalk (smol-rewrite) |
30,000 | 7.3% |
| chat | HuggingFaceTB/smoltalk (everyday-conversations) |
2,260 | 0.6% |
Tool-negative injection: 15% of non-tool rows keep their plain-text answer but get an unrelated tool list attached, teaching that tools in context don't always need calling.
SFT run 2 / instruct β checkpoints/latest.pt
Trained tokens (read from TensorBoard)
| Metric | Value |
|---|---|
| Tokens seen | 895,970,816 (~896M) |
| Optimizer steps | 27,350 |
| Train loss | 6.63 β 1.53 |
| Val loss | 2.19 β 1.48 (latest 1.4783, ppl 4.39) |
| LR schedule | warmup 200 steps to 5e-5, cosine decay to 5e-6, grad-accum 4, 8192-token batch budget |
Datasets (on-disk tokenized cache ./sft_cache: 380,573 train / 1,939 val rows, 3 epochs)
| Source | HF dataset | Row cap |
|---|---|---|
| instruct | HuggingFaceTB/smoltalk (smol-magpie-ultra) |
200,000 |
| glaive | glaiveai/glaive-function-calling-v2 |
90,000 |
| xlam | Salesforce/xlam-function-calling-60k (gated) |
60,000 |
| summarize | HuggingFaceTB/smoltalk (smol-summarize) |
40,000 |
| rewrite | HuggingFaceTB/smoltalk (smol-rewrite) |
40,000 |
| chat | HuggingFaceTB/smoltalk (everyday-conversations) |
2,260 |
| worldqa | β (excluded from this run) | 0 |
Tool-negative ratio 0.10. Lowest validation numbers of all three runs.
Usage
Chat script + tool definitions live in the GitHub repo (chat.py, tools.json).
Checkpoints here load with the same architecture:
# Chat + tools (SFT weights)
python chat.py --model_path runs/nanoagent-15m-sft/sft_chat_max_final.pt --tools tools.json
# Single-shot test
python chat.py --model_path runs/nanoagent-15m-sft/sft_chat_max_final.pt \
--tools tools.json --prompt "What is the weather in Paris?" \
--max_new_tokens 40 --temperature 0
# Base weights (never saw the chat template β use --raw)
python chat.py --model_path runs/nanoagent_15m/final_15m_model.pt --raw --prompt "Hello world"
Minimal transformers loading (matches train.py / chat.py exactly)
# Minimal transformers loading (matches train.py / chat.py exactly)
from transformers import LlamaConfig, LlamaForCausalLM, PreTrainedTokenizerFast
import torch
config = LlamaConfig(vocab_size=6144, hidden_size=384, intermediate_size=1024,
num_hidden_layers=8, num_attention_heads=6, num_key_value_heads=2,
max_position_embeddings=1024, rms_norm_eps=1e-5,
rope_theta=10000.0, tie_word_embeddings=True)
model = LlamaForCausalLM(config)
state = torch.load("runs/nanoagent-15m-sft/sft_chat_max_final.pt", map_location="cpu")
model.load_state_dict(state["model_state"] if "model_state" in state else state)
tokenizer = PreTrainedTokenizerFast.from_pretrained("nanoagent_tokenizer")
Limitations
- 15M parameters / 1024-token context: short, simple exchanges only; weak factuality.
- Tool-call format is the skill being taught β always validate emitted JSON before executing.
- xlam-derived rows are ~9% malformed upstream (skipped + counted during SFT).
- No reasoning/scratchpad tokens by design at this size; no QK-Norm (stock Llama has none).
Reproducing / full logs
The GitHub repo contains the full pipeline (train-tokenizer.py, download_and_pack.py,
train.py, sft_chat.py, sft_common.py, sft_agent_openbmb.py, sft-chat-max.py),
the raw run notebook (note.md), per-run TensorBoard events (runs/*/events.out.tfevents.*,
mirrored in the Training metrics tab), and training_config.json / training_summary.json
for the base run.
Evaluation results
- final validation loss on NanoAgent 1B-token pretraining mix (Ultra-FineWeb-L3 + FineWeb-Edu + Cosmopedia-v2 + UltraData-Code)self-reported3.977
- final validation perplexity on NanoAgent 1B-token pretraining mix (Ultra-FineWeb-L3 + FineWeb-Edu + Cosmopedia-v2 + UltraData-Code)self-reported53.370
- final validation loss on Blended SFT mix, 409,760 rows (smoltalk + ultrachat world-QA + xlam-function-calling-60k + glaive-function-calling-v2 + summarize + rewrite)self-reported1.735
- final validation perplexity on Blended SFT mix, 409,760 rows (smoltalk + ultrachat world-QA + xlam-function-calling-60k + glaive-function-calling-v2 + summarize + rewrite)self-reported5.670
- latest validation loss on Instruct-heavy SFT mix, 380,573 tokenized train rows (smol-magpie-ultra + glaive + xlam + summarize + rewrite + chat)self-reported1.478
- latest validation perplexity on Instruct-heavy SFT mix, 380,573 tokenized train rows (smol-magpie-ultra + glaive + xlam + summarize + rewrite + chat)self-reported4.390