| --- |
| title: MiniCPM5-1B-Agent |
| emoji: 🛠️ |
| colorFrom: gray |
| colorTo: yellow |
| sdk: docker |
| app_port: 7860 |
| pinned: true |
| |
| tags: |
| - best-minicpm-build |
| - backyard-ai |
| - best-use-of-codex |
| - best-use-of-modal |
| - off-brand |
| - best-agent |
| - best-demo |
| - tiny-titan |
| - bonus-quest-champion |
| - judges-wildcard |
| - well-tuned |
| - llama-champion |
| - off-the-grid |
| - track:backyard |
| - track:wood |
| - sponsor:openbmb |
| - sponsor:openai |
| - sponsor:modal |
| - achievement:offgrid |
| - achievement:welltuned |
| - achievement:offbrand |
| - achievement:llama |
| - achievement:sharing |
| --- |
| |
| # 🛠️ MiniCPM5-1B-Agent |
|
|
| **A tiny agentic coding agent that runs the whole write → run → read → debug → verify loop on a free CPU.** |
|
|
| Social [media post link](https://discord.com/channels/879548962464493619/1514734596930142218); demo video: |
| <table><tr> |
| <td><img src="minicpm5-1b-agent-demo.gif" alt="MiniCPM5-1B-Agent demo GIF" width="480"></td> |
| <td><video src="https://huggingface.co/spaces/build-small-hackathon/MiniCPM5-1B-Agent/resolve/main/long_demo_build-small-hackathon_MiniCPM5-1B-Agent_16x.mp4" controls width="480"></video></td> |
| </tr></table> |
|
|
| A full fine-tune of [`openbmb/MiniCPM5-1B`](https://huggingface.co/openbmb/MiniCPM5-1B) (1B params), served as a |
| Q8_0 GGUF on llama.cpp, no GPU. Give it a task; it reasons in `<think>`, then uses `bash` / `write` / `read` / |
| `edit` in a sandbox to build, run, and fix code, and renders the result (charts, images, live HTML) inline in |
| the chat. Multi-turn: files and history persist across messages. It is also exposed as an **MCP tool** |
| (`run_coding_task` at `/gradio_api/mcp/`). |
|
|
|
|
| ## What it is |
|
|
| Most coding agents are 70B+ behind a cloud API. This is the opposite: a **1B** model doing the *real* agentic |
| loop on a **2-vCPU CPU Space**, no GPU. It writes a file, runs it, reads the output, debugs, and shows you the |
| artifact, the same loop a big agent runs, shrunk to something you could host in your own backyard. |
|
|
| ## How it was built |
|
|
| - Modal platform was used to evaluate the model via inference. |
| - **Data (`train_v4`, 45,762 rows):** the proven v2 backbone (retail-filtered teacher mixes + real-usage agent |
| traces) kept whole, plus ~3,538 curated additions, gated to a small served tool vocab and solution-aware |
| MinHash-deduped. Bundled on the model repo under `dataset/`. |
| - **SFT:** full fine-tune (not LoRA, the long agentic mix needs the capacity) of the abliterated base, 1 epoch, |
| 24k context, fits in ~15-18 GB VRAM (direct Liger fused cross-entropy + mem-efficient SDPA). |
| - **DPO (on-policy):** run the SFT model over the training prompts and capture its OWN behaviour. *chosen* = a |
| valid `<function>` tool call; *rejected* = its real miss (rambling in `<think>` / answering with no call). |
| ~649 pairs. This rewards ACTING over stalling. |
| - **Serving:** Q8_0 GGUF on llama.cpp; a two-phase decode bounds the `<think>` separately from the action so the |
| model acts instead of looping; produced files render inline (charts, images, sandboxed live-HTML iframes). |
| |
| ## Try it |
| |
| - "Write a Python script that makes a bar chart of 30, 45, 25 (A, B, C), save chart.png, then run it." → writes + runs it; the PNG renders inline. |
| - "Write an HTML page quote.html with a button that shows a random quote each click (hard-coded, no internet)." → writes the file; renders live in a sandboxed iframe. |
| |
| It is a tiny 1B on a free CPU: expect **~4 min per simple turn**, longer for multi-step tasks (the demo video |
| shows it working end-to-end, so it can be judged even if a live run is slow). |
| |
| |
| <details><summary><b>Output examples</b></summary> |
| |
| Real single-turn outputs from the Q8_0 GGUF, generated on Modal (CPU): |
| |
| **Prompt:** Write a Python function `fib(n)` that returns the nth Fibonacci number iteratively. Print fib(10). |
| |
| ```python |
| def fib(n): |
| if n == 0: |
| return 0 |
| elif n == 1: |
| return 1 |
| a, b = 0, 1 |
| for _ in range(2, n + 1): |
| a, b = b, a + b |
| return b |
| |
| print(fib(10)) |
| ``` |
| |
| **Prompt:** Convert an integer (1-3999) to a Roman numeral; demonstrate on 1994. |
|
|
| ```python |
| def int_to_roman(num): |
| if not 1 <= num <= 3999: |
| raise ValueError("Number must be between 1 and 3999") |
| roman_map = [(1000,'M'),(900,'CM'),(500,'D'),(400,'CD'),(100,'C'),(90,'XC'), |
| (50,'L'),(40,'XL'),(10,'X'),(9,'IX'),(5,'V'),(4,'IV'),(1,'I')] |
| result = [] |
| for value, symbol in roman_map: |
| while num >= value: |
| result.append(symbol); num -= value |
| return ''.join(result) |
| |
| print(int_to_roman(1994)) # -> MCMXCIV |
| ``` |
|
|
| **Prompt:** How many $40 games can I buy with $200, and how much is left over? |
|
|
| > You can buy **5 games** with $200, and have **$0 left over**. |
| > Number of games = 200 / 40 = 5; remaining = 200 - (5 x 40) = $0. |
|
|
| </details> |
|
|
| ## Model, dataset & full reproduction |
|
|
| → **[Luminia/MiniCPM5-1B-Agent-GGUF](https://huggingface.co/Luminia/MiniCPM5-1B-Agent-GGUF)** (model card = |
| the full data mix, SFT/DPO recipe, eval, and exact reproduce commands; v4 dataset bundled under `dataset/`). |
|
|
| 💻 **Code on GitHub:** [Katehuuh/MiniCPM5-1B-Agent](https://github.com/Katehuuh/MiniCPM5-1B-Agent) (the Space + the full training pipeline; code reviewed with OpenAI Codex). |
|
|
| *Built for the Build Small Hackathon · OpenBMB + OpenAI Codex tracks.* |