Instructions to use Edgeai-gio/SmolCpp-MoE-360M with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Edgeai-gio/SmolCpp-MoE-360M with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Edgeai-gio/SmolCpp-MoE-360M")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Edgeai-gio/SmolCpp-MoE-360M", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use Edgeai-gio/SmolCpp-MoE-360M 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 Edgeai-gio/SmolCpp-MoE-360M:F16 # Run inference directly in the terminal: llama cli -hf Edgeai-gio/SmolCpp-MoE-360M:F16
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf Edgeai-gio/SmolCpp-MoE-360M:F16 # Run inference directly in the terminal: llama cli -hf Edgeai-gio/SmolCpp-MoE-360M:F16
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 Edgeai-gio/SmolCpp-MoE-360M:F16 # Run inference directly in the terminal: ./llama-cli -hf Edgeai-gio/SmolCpp-MoE-360M:F16
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 Edgeai-gio/SmolCpp-MoE-360M:F16 # Run inference directly in the terminal: ./build/bin/llama-cli -hf Edgeai-gio/SmolCpp-MoE-360M:F16
Use Docker
docker model run hf.co/Edgeai-gio/SmolCpp-MoE-360M:F16
- LM Studio
- Jan
- vLLM
How to use Edgeai-gio/SmolCpp-MoE-360M with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Edgeai-gio/SmolCpp-MoE-360M" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Edgeai-gio/SmolCpp-MoE-360M", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/Edgeai-gio/SmolCpp-MoE-360M:F16
- SGLang
How to use Edgeai-gio/SmolCpp-MoE-360M 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 "Edgeai-gio/SmolCpp-MoE-360M" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Edgeai-gio/SmolCpp-MoE-360M", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'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 "Edgeai-gio/SmolCpp-MoE-360M" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Edgeai-gio/SmolCpp-MoE-360M", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Ollama
How to use Edgeai-gio/SmolCpp-MoE-360M with Ollama:
ollama run hf.co/Edgeai-gio/SmolCpp-MoE-360M:F16
- Unsloth Desktop
- Docker Model Runner
How to use Edgeai-gio/SmolCpp-MoE-360M with Docker Model Runner:
docker model run hf.co/Edgeai-gio/SmolCpp-MoE-360M:F16
- Lemonade
How to use Edgeai-gio/SmolCpp-MoE-360M with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull Edgeai-gio/SmolCpp-MoE-360M:F16
Run and chat with the model
lemonade run user.SmolCpp-MoE-360M-F16
List all available models
lemonade list
- Atomic Chat
SmolCpp-MoE-360M — SmolLM2-360M Mixture-of-Experts for Code (C++-focused)
Español más abajo / Spanish below
AI disclosure
This project was built with heavy assistance from Claude (Anthropic's AI
assistant): the training pipeline code, architecture decisions (Branch-
Train-MiX, mergekit-moe, QAT integration), dataset research, and debugging
were largely done in collaboration with/by the AI, in a conversational,
iterative process. The human author drove the project's goals, made the key
product decisions (domain focus, expert split), ran every step on real
hardware (Google Colab, then an Android phone via Termux), and debugged
real-world failures as they came up — but does not claim independent
expertise in the ML internals this project touches. If you have questions
about why a particular technical choice was made, the honest answer is
often "the AI suggested it and it seemed to work," not deep prior knowledge.
This disclosure exists because the author would rather be transparent than
imply skills they don't have.
What this is
A small (~360M dense-equivalent) Mixture-of-Experts language model built from HuggingFaceTB/SmolLM2-360M using a Branch-Train-MiX approach: four separate LoRA fine-tunes, each specialized on a distinct coding facet (with an emphasis on C++), merged into a single real Mixture-of-Experts model using mergekit-moe (Mixtral-style architecture), then quantized to GGUF for local/mobile inference via llama.cpp.
The main thing this project actually contributes is not the model's raw
capability (it's a 360M model — don't expect it to compete with 1B+ coder
models). It's a working, documented pipeline for producing a GGUF file with
real MoE routing for small custom models, as opposed to the "dense-equivalent"
workaround that most GGUF conversions of custom MoE architectures currently
fall back to (llama.cpp has no native converter for arbitrary MoE archs, but
it does understand Mixtral natively — so building on the Mixtral arch via
mergekit-moe sidesteps that gap entirely).
Architecture
- Base model: SmolLM2-360M (LLaMA-style architecture)
- Experts: 4 total, one per facet below
- Routing: top-2 (
experts_per_token: 2), Mixtral-style - Gate initialization:
gate_mode: hidden— the router is initialized from the base model's hidden states on facet-representative prompts, rather than trained from scratch. This means the router works reasonably out of the box without a separate training loop, though it has not been further fine-tuned. - Format: GGUF, quantized to Q4_K_M
Experts and training data
Each expert started as SmolLM2-360M, fine-tuned with LoRA (r=16, alpha=32) on one facet, then merged back into the dense weights, then given a short post-merge Quantization-Aware Training (QAT) pass (int4 fake-quantization via torchao, group_size=32) intended to make the weights more tolerant of the eventual 4-bit quantization. Note this QAT scheme does not exactly match llama.cpp's K-quant block structure, so treat it as a general-purpose robustness pass, not a guarantee tuned specifically for Q4_K_M.
| Expert | Facet | Dataset |
|---|---|---|
cpp_instrucciones |
C++ instruction/reasoning → code | nvidia/OpenCodeReasoning-2 (train/cpp split) |
cpp_crudo |
C++ raw code / autocomplete style | bigcode/the-stack-smol (data/c++) |
algoritmos |
Multi-language competitive programming | deepmind/code_contests |
python_referencia |
Python instruction → code (cross-reference) | iamtarun/python_code_instructions_18k_alpaca |
Honest evaluation notes
This was tested manually on a small number of prompts (not a formal
benchmark suite), on-device via llama.cpp on an Android phone. Findings:
cpp_instrucciones: produced syntactically correct, functionally working C++ (a factorial function) with a minor edge-case bug atn=0.cpp_crudo: continues raw C++ code plausibly and correctly, in the autocomplete style it was trained on (not instruction-following).python_referencia: produced a mostly-correct Python factorial usingfunctools.reduce(the classic idiom), but was missing thefrom functools import reduceimport and had a minor logic bug in its edge-case validation.- Generation quality was noticeably worse at default/high sampling
temperature; results above used
--temp 0.2 --repeat-penalty 1.3. At higher temperature the model can hallucinate (e.g., calling a nonexistent module) or get stuck in repetition loops. - Not evaluated: how well the router actually discriminates between facets on realistic mixed prompts (this used hand-picked prompts aligned to each expert's training format, not blind routing tests).
Bottom line: this is a proof of concept, not a production-ready coding assistant. It demonstrates the pipeline works end-to-end; it does not demonstrate strong coding ability at this model size.
Performance
Tested on a Redmi Note 14 4G (MediaTek Helio G99 Ultra, 8GB RAM) via
llama.cpp in Termux, CPU-only, -t 2 (using only the 2 Cortex-A76 cores):
- ~15–18 tokens/second generation
- ~24–25 tokens/second prompt processing
Known llama.cpp CLI quirk (important if you hit it)
On at least one recent Termux-packaged llama-cli build, the interactive/
completion CLI applies an output-validation layer (peg-native /
"Content-only format" parser, originally meant for tool-calling) that can
incorrectly reject plain code completions from this model, aborting
generation with an error. Neither -no-cnv nor --no-jinja reliably fixed
this in testing. Workaround: use llama-server instead of llama-cli,
and query the raw /completion HTTP endpoint directly — this bypasses the
CLI's output parser entirely and worked reliably in testing.
./llama-server -m SmolCpp-MoE-360M-Q4_K_M.gguf -c 2048 -t 2 --port 8080 &
python3 -c "
import json, urllib.request
prompt = '### Problema:\nEscribe una funcion en C++ que calcule el factorial de un numero.\n\n### Solucion en C++:\n'
payload = json.dumps({'prompt': prompt, 'n_predict': 200, 'temperature': 0.2, 'repeat_penalty': 1.3}).encode()
req = urllib.request.Request('http://localhost:8080/completion', data=payload, headers={'Content-Type': 'application/json'})
print(json.loads(urllib.request.urlopen(req).read())['content'])
"
Prompt format
This is a base model (not instruction-tuned by the base model provider), so it has no chat template. Each expert learned its own plain-text format from its training data:
cpp_instrucciones:### Problema:\n{problem}\n\n### Solucion en C++:\npython_referencia:### Instruccion:\n{instruction}\n\n### Codigo:\ncpp_crudo: no special format — just feed it partial C++ code to continue
License
- This model's own weights/code: Apache 2.0 (inherited from the SmolLM2-360M base model).
- Training data licenses vary by expert and are NOT unified — please
review each dataset's own terms before redistributing derivatives:
nvidia/OpenCodeReasoning-2: CC-BY-4.0bigcode/the-stack-smol: no single license — each file retains the license of its original source repository; you must comply with those individual licenses (including attribution where required) when using or redistributing content derived from this expert. See the dataset's terms of use.deepmind/code_contests: check the dataset page for current license terms before redistribution.iamtarun/python_code_instructions_18k_alpaca: check the dataset page for current license terms.
Reproducing this
The full training/merge/quantization notebook (Google Colab, T4 GPU) is
included in this repository. It covers: LoRA fine-tuning per facet,
post-merge QAT with torchao, embedding untying (required for
mergekit-moe to work with SmolLM2's tied embeddings), mergekit-moe
assembly, and GGUF conversion + quantization.
Acknowledgements
- HuggingFaceTB for SmolLM2
- Arcee AI for
mergekit-moe - ggml-org for
llama.cpp - pytorch/ao for QAT tooling
SmolCpp-MoE-360M — SmolLM2-360M, mezcla de expertos para código (enfoque en C++)
Aviso sobre uso de IA
Este proyecto se construyó con asistencia intensiva de Claude (el asistente
de IA de Anthropic): el código del pipeline de entrenamiento, las decisiones
de arquitectura (Branch-Train-MiX, mergekit-moe, integración de QAT), la
investigación de datasets, y la depuración se hicieron en gran parte en
colaboración con/por la IA, en un proceso conversacional e iterativo. El
autor humano llevó los objetivos del proyecto, tomó las decisiones clave de
producto (enfoque de dominio, división de expertos), corrió cada paso en
hardware real (Google Colab, luego un celular Android vía Termux), y
depuró los fallos reales conforme fueron apareciendo — pero no reclama
experiencia independiente en los aspectos internos de ML que toca este
proyecto. Si tienes preguntas sobre por qué se tomó alguna decisión
técnica en particular, la respuesta honesta muchas veces es "la IA lo
sugirió y parecía funcionar", no conocimiento previo profundo. Este aviso
existe porque el autor prefiere ser transparente antes que dar a entender
habilidades que no tiene.
Qué es esto
Un modelo de lenguaje pequeño (~360M, equivalente denso) de Mezcla de Expertos (MoE), construido a partir de HuggingFaceTB/SmolLM2-360M usando un enfoque Branch-Train-MiX: cuatro fine-tunings LoRA separados, cada uno especializado en una faceta distinta de programación (con énfasis en C++), fusionados en un solo modelo MoE real usando mergekit-moe (arquitectura estilo Mixtral), y luego cuantizado a GGUF para inferencia local/móvil vía llama.cpp.
Lo que este proyecto realmente aporta no es la capacidad bruta del
modelo (es un modelo de 360M — no esperes que compita con modelos de código
de 1B+). Es un pipeline funcional y documentado para producir un GGUF con
routing MoE real, en vez del truco "dense-equivalent" al que recurren la
mayoría de las conversiones GGUF de arquitecturas MoE custom actualmente
(llama.cpp no tiene un conversor nativo para arquitecturas MoE arbitrarias,
pero sí entiende Mixtral de forma nativa — así que construir sobre la
arquitectura Mixtral vía mergekit-moe evita ese hueco por completo).
Arquitectura
- Modelo base: SmolLM2-360M (arquitectura estilo LLaMA)
- Expertos: 4 en total, uno por cada faceta listada abajo
- Routing: top-2 (
experts_per_token: 2), estilo Mixtral - Inicialización del router:
gate_mode: hidden— el router se inicializa a partir de los estados ocultos del modelo base sobre prompts representativos de cada faceta, en vez de entrenarse desde cero. Esto significa que el router funciona razonablemente sin un loop de entrenamiento aparte, aunque no se afinó más allá de eso. - Formato: GGUF, cuantizado a Q4_K_M
Expertos y datos de entrenamiento
Cada experto arrancó como SmolLM2-360M, se afinó con LoRA (r=16, alpha=32)
sobre una faceta, se fusionó de vuelta a los pesos densos, y luego recibió
una pasada corta de Quantization-Aware Training (QAT) post-fusión
(fake-quantización int4 vía torchao,
group_size=32), pensada para que los pesos toleren mejor la cuantización a 4
bits. Nota: este esquema de QAT no coincide exactamente con la estructura de
bloques K-quant de llama.cpp, así que trátalo como una pasada general de
robustez, no una garantía afinada específicamente para Q4_K_M.
| Experto | Faceta | Dataset |
|---|---|---|
cpp_instrucciones |
Instrucción/razonamiento en C++ → código | nvidia/OpenCodeReasoning-2 (split train/cpp) |
cpp_crudo |
Código C++ crudo / estilo autocompletado | bigcode/the-stack-smol (data/c++) |
algoritmos |
Programación competitiva multi-lenguaje | deepmind/code_contests |
python_referencia |
Instrucción en Python → código (referencia cruzada) | iamtarun/python_code_instructions_18k_alpaca |
Notas honestas de evaluación
Esto se probó manualmente con un número pequeño de prompts (no es una
batería de benchmarks formal), en el dispositivo vía llama.cpp en un
celular Android. Hallazgos:
cpp_instrucciones: produjo C++ sintácticamente correcto y funcionalmente correcto (una función de factorial), con un bug menor de caso extremo enn=0.cpp_crudo: continúa código C++ crudo de forma plausible y correcta, en el estilo de autocompletado con el que se entrenó (no sigue instrucciones).python_referencia: produjo un factorial en Python mayormente correcto usandofunctools.reduce(el idioma clásico), pero le faltaba el importfrom functools import reducey tenía un bug menor de lógica en su validación de caso extremo.- La calidad de generación fue notablemente peor con temperatura de
muestreo alta/por defecto; los resultados de arriba usaron
--temp 0.2 --repeat-penalty 1.3. Con temperatura más alta el modelo puede alucinar (por ejemplo, llamar a un módulo inexistente) o quedarse atascado en bucles de repetición. - No evaluado: qué tan bien discrimina el router entre facetas con prompts mixtos realistas (se usaron prompts elegidos a mano, alineados al formato de entrenamiento de cada experto, no pruebas ciegas de routing).
En resumen: esto es una prueba de concepto, no un asistente de código listo para producción. Demuestra que el pipeline funciona de punta a punta; no demuestra una capacidad de código fuerte en este tamaño de modelo.
Rendimiento
Probado en un Redmi Note 14 4G (MediaTek Helio G99 Ultra, 8GB RAM) vía
llama.cpp en Termux, solo CPU, -t 2 (usando solo los 2 núcleos
Cortex-A76):
- ~15–18 tokens/segundo en generación
- ~24–25 tokens/segundo en procesamiento del prompt
Detalle conocido del CLI de llama.cpp (importante si te pasa)
En al menos una build reciente de llama-cli empaquetada para Termux, el
CLI interactivo/de completado aplica una capa de validación de salida
(parser peg-native / "Content-only format", pensado originalmente para
llamadas a herramientas) que puede rechazar incorrectamente completados de
código plano de este modelo, abortando la generación con un error. Ni
-no-cnv ni --no-jinja lo arreglaron de forma confiable en las pruebas.
Solución: usa llama-server en vez de llama-cli, y consulta
directamente el endpoint HTTP /completion — esto evita por completo el
parser de salida del CLI y funcionó de forma confiable en las pruebas (ver
el bloque de código en la sección en inglés arriba).
Formato de prompt
Este es un modelo base (no instruction-tuned por el proveedor del modelo base), así que no tiene plantilla de chat. Cada experto aprendió su propio formato de texto plano a partir de sus datos de entrenamiento:
cpp_instrucciones:### Problema:\n{problema}\n\n### Solucion en C++:\npython_referencia:### Instruccion:\n{instruccion}\n\n### Codigo:\ncpp_crudo: sin formato especial — solo dale código C++ parcial para que lo continúe
Licencia
- Los pesos/código de este modelo: Apache 2.0 (heredado del modelo base SmolLM2-360M).
- Las licencias de los datos de entrenamiento varían por experto y NO
están unificadas — por favor revisa los términos de cada dataset antes
de redistribuir derivados:
nvidia/OpenCodeReasoning-2: CC-BY-4.0bigcode/the-stack-smol: sin licencia única — cada archivo conserva la licencia de su repositorio de origen; debes cumplir esas licencias individuales (incluyendo atribución cuando se requiera) al usar o redistribuir contenido derivado de este experto. Ver los términos de uso del dataset.deepmind/code_contests: revisa la página del dataset para los términos de licencia vigentes antes de redistribuir.iamtarun/python_code_instructions_18k_alpaca: revisa la página del dataset para los términos de licencia vigentes.
Cómo reproducir esto
El notebook completo de entrenamiento/fusión/cuantización (Google Colab,
GPU T4) está incluido en este repositorio. Cubre: fine-tuning LoRA por
faceta, QAT post-fusión con torchao, "destar" los embeddings (necesario
para que mergekit-moe funcione con los embeddings atados de SmolLM2),
ensamblaje con mergekit-moe, y conversión + cuantización a GGUF.
Agradecimientos
- HuggingFaceTB por SmolLM2
- Arcee AI por
mergekit-moe - ggml-org por
llama.cpp - pytorch/ao por las herramientas de QAT
- Downloads last month
- 51
4-bit
16-bit
Model tree for Edgeai-gio/SmolCpp-MoE-360M
Base model
HuggingFaceTB/SmolLM2-360M