# MiniCPM5-2B: A 2.5B Model That Beats Larger Models on Agentic Tasks

OpenBMB released **MiniCPM5-2B** on September 7, 2026, a 2.52-billion-parameter dense model that performs unusually well for its size. In OpenBMB’s own 34-benchmark comparison, it averages **53.9**, ahead of Qwen3.5-4B at 51.1 despite using roughly half as many parameters.

The more interesting result is on **SWE-bench Verified**, where MiniCPM5-2B scores 46.4. That compares with 5 for Qwen3.5-2B and 33.6 for the larger Qwen3.5-4B, making its coding performance one of the strongest reasons to pay attention to the model.

There is one important caveat. **The quantized GGUF builds can fall into repetition loops more than 90% of the time when run with the documented settings.** The good news is that the problem has a simple workaround: one additional flag is enough to stop the behavior.

This article looks at **what makes MiniCPM5-2B interesting, how to run it on Apple Silicon, how to enable tool use with llama.cpp, and how to avoid the repetition bug**.

The model is released under **Apache 2.0**, with its training datasets available openly. You can find the weights at [huggingface.co/openbmb/MiniCPM5-2B](https://huggingface.co/openbmb/MiniCPM5-2B) and the source code at [github.com/OpenBMB/MiniCPM](https://github.com/OpenBMB/M)

<iframe class="aspect-video h-auto" width="100%" height="315" src="https://www.youtube.com/embed/Wik_JQ-enUA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


## Why it outperforms larger models on certain tasks

The performance inversion on agentic benchmarks isn't accidental. Three deliberate choices explain it.

### Standard Llama architecture

MiniCPM4 used custom sparse attention and multi-token prediction. Innovative, but those features required custom support in every runtime (MLX, llama.cpp, vLLM, Ollama), which severely limited adoption and compatibility.

![A comparison slide showing MiniCPM4's reliance on custom features versus MiniCPM5-2B's compatibility with standard runtimes like MLX, llama.cpp, and WebLLM.](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/bb568987-2c16-4465-ef3d-a61f7f56e300/orig =1920x1080)

MiniCPM5-2B uses the standard `LlamaForCausalLM` class with 42 layers and grouped-query attention (16 query heads, 2 key-value heads). It loads out of the box in Transformers, vLLM, SGLang, llama.cpp, Ollama, LM Studio, and MLX with no custom code. The context window is 131,072 tokens.

### Agent-first training

The training pipeline was built around agentic behavior rather than adding it as fine-tuning after the fact.

![A diagram illustrating the multi-stage training pipeline for MiniCPM5-2B.](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/a55c83d3-b28b-4669-abc4-89ced7da6b00/lg2x =1920x1080)

The three stages: SFT on 500,000 agent trajectories from `UltraData-SFT-Agent-2609`; reinforcement learning using the critic-based JustRL II algorithm on 80,000+ samples from `UltraData-RL-2609`; and OPD (Optimal Policy Distillation), a novel final stage that merges 16 expert models produced by RL training into a single checkpoint. At each response position, OPD computes full-vocabulary reverse KL divergence between the student and each expert to produce the advantage estimate. OpenBMB reports that RL + OPD adds 10.96 points on average to reasoning and general capabilities, and 6.96 points on agentic capabilities.

### Benchmark performance: where it leads and where it doesn't

![A bar chart comparing the SWE-bench Verified scores of MiniCPM5-2B against other small and large models, highlighting its superior performance.](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/a1907daf-d075-4de4-5c5d-e7765e8e8600/lg1x =1920x1080)

The strongest results are in code and math: LiveCodeBench v6 at 69.1, AIME 2025 and AIME 2026 both at 86.5, MATH-500 at 94.6, and SWE-bench Verified at 46.4. On tool-use benchmarks it similarly leads its weight class.

On long-horizon agent tasks, the picture reverses. Terminal-Bench v2.1: 8.6 for MiniCPM5-2B versus 25.8 for Qwen3.5-4B. SWE-bench Pro: 14.4 versus 28.2. The model is good at picking the next step in an agent loop and substantially weaker at holding a multi-step plan together across dozens of turns.

One gap in the release: no inference speed or memory figures for any named device. For a model positioned around on-device deployment, the model card doesn't tell you how much RAM the 4-bit build needs or how many tokens per second it produces on a MacBook Air.

## Running on Apple Silicon with MLX

Create a virtual environment and install `mlx-lm`. Version 0.3.1 or newer is required; older versions misidentified the model's end-of-sequence tokens and caused it to run indefinitely.

```command
python3 -m venv .venv
```

```command
source .venv/bin/activate
```

```command
pip install "mlx-lm>=0.3.1" openai
```

Run a generation:

```command
mlx_lm.generate --model openbmb/MiniCPM5-2B-MLX \
    --prompt "<im_start>user
Write a one-sentence explanation of grouped-query attention.<im_end>
<im_start>assistant
" \
    --max-tokens 300 \
    --temp 1.0 \
    --top-p 0.95
```

The model outputs a `<think>` block before the final answer, showing its internal reasoning. This is expected behavior from the agent-first training.

![Terminal output showing the model's response, with the "think" block clearly highlighted, revealing its internal reasoning process before generating the final sentence.](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/762201f0-987c-429f-2eda-bf58c75d1200/orig =1920x1080)

For an interactive chat session, replace `mlx_lm.generate` with `mlx_lm.chat` using the same model path.

## Tool use via llama.cpp

The MLX path handles text generation and chat. Tool calling requires llama.cpp as a server because the MLX package doesn't yet expose the function-calling API surface.

Download a GGUF build (Q8 is recommended; Q4_K_M has the repetition bug covered below):

```command
huggingface-cli download openbmb/MiniCPM5-2B-GGUF MiniCPM5-2B-Q8_0.gguf
```

Start the server with the critical sampler flags applied:

```command
llama-server \
    --model MiniCPM5-2B-Q8_0.gguf \
    --port 8080 \
    --repeat-penalty 1.15 \
    --min-p 0.0 \
    --temp 1.0 \
    --top-p 0.95
```

With the server running, use the OpenAI client to send a tool-calling request:

```python
[label main.py]
import openai

client = openai.OpenAI(
    base_url="http://127.0.0.1:8080/v1",
    api_key="sk-no-key-required"
)

messages = [
    {"role": "system", "content": "Use tools when you need live data. Do not invent weather."},
    {"role": "user", "content": "What is the weather in San Francisco?"}
]

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get the current weather in a given location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "City and country/state, e.g., San Francisco, CA"
                    }
                },
                "required": ["location"]
            }
        }
    }
]

resp = client.chat.completions.create(
    model="MiniCPM5-2B",
    messages=messages,
    tools=tools,
    tool_choice="auto",
    temperature=1.0,
    top_p=0.95,
)

print(resp.choices[0].message)
```

The model correctly identifies the need for the tool and generates a structured tool call with the right arguments rather than fabricating an answer:

```text
[output]
ChatCompletionMessage(
    content=None,
    role='assistant',
    tool_calls=[
        ChatCompletionMessageToolCall(
            id='call_AbcdeFghijKlmnoPqrsT',
            function=Function(
                arguments='{"location": "San Francisco, CA"}',
                name='get_current_weather'
            ),
            type='function'
        )
    ]
)
```

In a real application, your code would execute the function, get the actual weather data, pass it back as a tool result, and make a second API call to get the final user-facing response.

## The repetition bug and the fix

A GitHub issue investigation found that running the Q4_K_M GGUF model with the default documented settings (which omitted `repeat-penalty`) produced a 92.1% runaway rate: the model loops indefinitely on the same tokens.

![A screenshot of the GitHub issue summary table showing the HumanEval+ results. It displays a low Q4_K_M score of 6.1 and a staggering runaway rate of 92.1% with the default settings.](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/b02a83d3-f3d2-46f4-f72b-abd4ec081300/lg2x =1920x1080)

With `--repeat-penalty 1.15` added: HumanEval+ score jumps from 6.1 to 71.3, runaway rate drops from 92.1% to 11.0%. A 14x performance swing from one flag.

The full set of sampler settings required for reliable output with quantized GGUF builds:

| Parameter | Value |
| :--- | :--- |
| `--repeat-penalty` | `1.15` |
| `--min-p` | `0.0` |
| `--temp` | `1.0` |
| `--top-p` | `0.95` |

All four are required. The `--min-p 0.0` flag matters because the default mlx-lm `min_p` value (typically 0.05) clips the probability distribution in a way that interacts badly with this model's sampling. Setting it to zero effectively disables `min_p` filtering and allows `top_p` and `repeat_penalty` to work as intended.

The training datasets (Ultra-FineWeb, UltraData-Code, UltraData-SFT-Agent-2609, UltraData-RL-2609) were released alongside the model, which is unusual and genuinely useful for teams that want to fine-tune for specific domains.

## When to use it

MiniCPM5-2B is worth testing if you need an on-device coding agent or tool-using chatbot and are working within the constraints of a MacBook Air or a single consumer GPU. Its 46.4 on SWE-bench Verified is competitive with models that cost far more to run, and it loads without custom runtime code.

The cases where it doesn't hold up: multi-step long-horizon agent tasks (Terminal-Bench), tasks that require broad general knowledge rather than focused reasoning, and any deployment where you haven't verified the sampler settings produce stable output on your specific quantization level and runtime. The Q8 GGUF is noticeably more stable than Q4_K_M as a starting point.