MiniCPM5-2B on a 16GB MacBook Air: Bilingual Extraction Test and Ollama Setup

Staff requests often mix Chinese and English in one sentence. To see how MiniCPM5-2B handles that pattern on a local machine, we ran a 12-case structured-extraction test on a 16GB Apple M5 MacBook Air. This article shows the inputs and outputs, the exact-match rule, measured latency, and the Ollama steps used to reproduce a case.

MiniCPM5-2B is our compact text model for on-device assistants. In this test, it matched every required JSON key and value in 11 of 12 mixed-language requests. We also place that result alongside independent benchmark data and the model’s published instruction-following and tool-use scores.

Why bilingual staff requests are a demanding test

A workplace request may name a ticket in Chinese, specify the priority in English, and ask for a fixed JSON schema. MiniCPM5-2B must connect those details while preserving IDs, numbers, and missing values. We designed the 12-case set around these concrete extraction checks: routine updates, missing information, negation, dates, amounts, and the exact action values required by the application.

MiniCPM5-2B is a text-input, text-output model with 2,516,756,480 parameters and a native context length of 131,072 tokens, as detailed in our model card. It supports reasoning and tool-use workflows and is released under Apache 2.0. The long context limit is a model capability; the context you can run comfortably on a device depends on available memory and the serving stack.

Independent benchmarks and our published model evaluation

On October 8, 2026, Artificial Analysis listed MiniCPM5-2B at 12 on its Intelligence Index and #2 of 49 in its open-weight Tiny category, which includes models with up to 4B parameters. MiniCPM5-2B has approximately 2.5B parameters; the model above it, K2 Horizon 3.7B, is larger. This is the published Tiny-category ranking, rather than a separate under-3B ranking.

Artificial Analysis evaluates the reasoning-enabled version of MiniCPM5-2B. Our laptop extraction run below used thinking off and Q4_K_M quantization, so its 11-of-12 result is a separate measurement under different settings. Artificial Analysis does not publish an output-speed figure for this model.

Our MiniCPM5-2B model card reports 71.8 on Multi-IF for instruction following and 66.6 on BFCL v4 for tool use. These are results published in the model card. The bilingual extraction cases in this article were run separately on the laptop described below.

Choose a deployment format for the device you have

Our Ollama model page provides a direct laptop path using the Q4_K_M GGUF build. Our Ollama guide also documents a manual GGUF setup. Other supported serving paths include llama.cpp, vLLM, SGLang, Transformers, and LiteRT-LM; the steps and measurements in this article use Ollama. The model supports a 131,072-token native context, while this local test configured 4,096 tokens.

MiniCPM5-2B GGUF format

Model file size

Practical use

F16

5.04 GB

Reference-quality weights when memory allows

Q8_0

2.68 GB

A larger quantized option

Q4_K_M

1.56 GB

A compact option for laptop trials

The table shows GGUF file sizes from our deployment guide. In our 16GB MacBook Air test, Ollama reported the loaded Q4_K_M model at 1.8GB with a 4,096-token context. Model file size and loaded-model size measure different things; the setup below specifies the actual format and context used.

Run the same Q4_K_M setup through Ollama

The OpenBMB Ollama model provides the Q4_K_M build used here. With Ollama installed, pull the model and start the local service:

ollama pull openbmb/minicpm5-2b

ollama serve

In another terminal, send a mixed-language extraction request to Ollama’s local API. This example uses the same inference settings as our test: thinking off, temperature 0, JSON mode, a 4,096-token context, and a 128-token output limit. The program checks the parsed object against the required keys and values before any downstream action.

import json

import urllib.request

expected = {"ticket": "INC-204", "priority": "high", "owner": "Maya"}

payload = {

"model": "openbmb/minicpm5-2b:latest",

"messages": [

{"role": "system", "content":

"Extract only facts stated in the request. Return one JSON object, no prose. "

"Keys: ticket, priority, owner"},

{"role": "user", "content":

"请把 ticket INC-204 设为 high priority, owner is Maya. "

"Return JSON with ticket, priority, owner."}

],

"stream": False, "think": False, "format": "json",

"options": {"temperature": 0, "num_ctx": 4096, "num_predict": 128}

}

request = urllib.request.Request(

"http://127.0.0.1:11434/api/chat",

data=json.dumps(payload, ensure_ascii=False).encode(),

headers={"Content-Type": "application/json"})

with urllib.request.urlopen(request) as response:

reply = json.load(response)

actual = json.loads(reply["message"]["content"])

assert isinstance(actual, dict) and actual == expected

print(actual)

Measured MiniCPM5-2B speed on a 16GB MacBook Air

We ran openbmb/minicpm5-2b:latest (Ollama model ID 71a44e98400f, Q4_K_M) with Ollama 0.33.2 on an Apple M5 MacBook Air with 16GB unified memory, macOS Darwin 25.6, one request at a time, thinking off, temperature 0, JSON mode, num_ctx=4096, and num_predict=128. Across cases 2–12, median request time was 0.321 seconds, measured on the client from immediately before the local HTTP POST until the complete JSON response arrived. Median generation rate was 76.5 tokens per second, calculated for each request as Ollama’s generated-token count divided by its reported generation duration, then taking the median. Those 11 warm requests include the failed exact-match case 4; only case 1 was excluded from the warm timing median because it loaded the model (1.541 seconds of reported load time). Inputs ranged from 66 to 84 prompt tokens and outputs from 12 to 37 generated tokens. The complete case log is summarized in the appendix below.

What our small bilingual test showed

We tested 12 synthetic staff requests that mixed Chinese and English. For each request, the system message listed the required keys; the model returned JSON with thinking off, temperature 0, and a 4,096-token context. We parsed the response and counted a pass only when it was an object with exactly the expected keys and values, with no additional keys. Key order did not matter; synonyms or normalized variants did not count. Eleven of 12 cases passed. Case 4 failed exact-match validation because the model returned the action value "cancelled" instead of the required "cancel".

Three requests from the test set

Each case below shows the original mixed-language input, the required JSON object, and the model output. The full 12-case set follows in the appendix.

A routine ticket update (case 1).

Original input: 请把 ticket INC-204 设为 high priority, owner is Maya. Return JSON with ticket, priority, owner.

Expected JSON: {"ticket":"INC-204","priority":"high","owner":"Maya"}

Model output: {"ticket":"INC-204","priority":"high","owner":"Maya"}

Exact-match result: Pass

A missing value represented as null (case 9).

Original input: 客户要更新 address, but the new address is missing. Return JSON with action, new_address. Use null when missing.

Expected JSON: {"action":"update_address","new_address":null}

Model output: {"action":"update_address","new_address":null}

Exact-match result: Pass

An exact-schema mismatch (case 4).

Original input: Customer asks to cancel 订单 B-52, but no reason was provided. Return JSON with order, action, reason. Use null for missing reason.

Expected JSON: {"order":"B-52","action":"cancel","reason":null}

Model output: {"order":"B-52","action":"cancelled","reason":null}

Exact-match result: Fail

That difference matters if an application expects a fixed action enum. Validate the parsed object against the function schema before executing an action, and map or reject values that fall outside the allowed set. The three examples above show a normal update, a request with missing information, and the failed exact-match case.

How to decide whether MiniCPM5-2B fits your workflow

For a workflow pilot, assemble representative, permissioned requests that preserve the original language switching. Define the exact action and required fields before testing, then include routine requests, missing information, and costly-error cases. The 12 cases here demonstrate the method and give a transparent starting set.

MiniCPM5-2B is a strong candidate for compact local text extraction and structured output. The 11-of-12 result on mixed-language requests, its published benchmark scores, and the Ollama path give teams a concrete basis for a matched trial on their own tasks. For image input or a smaller device budget, select the appropriate model in our MiniCPM family.

The practical next step is to run the same exact-schema check on the requests and device that matter to the application. The complete sample set below makes this laptop result inspectable and reproducible.

Frequently asked questions

Can MiniCPM5-2B run without sending staff requests to a cloud API?

Yes. The Ollama setup above runs inference locally, so staff requests can be processed without sending them to a cloud inference API.

What is the minimum machine required?

The test in this article ran the Q4_K_M build on a 16GB Apple M5 MacBook Air with a 4,096-token context and one request at a time. Our GGUF guide lists the Q4_K_M model file at 1.56GB; actual capacity depends on the runtime, context length, and concurrent load.

Does a strong index score guarantee bilingual task success?

The index and the laptop test measure different things. Artificial Analysis reports broad performance for the reasoning-enabled model. The local run here measures exact-schema extraction with thinking off and Q4_K_M quantization: 11 of 12 requests passed, with the one failed value shown above.

Sources and test setup: Benchmark details were checked on October 8, 2026 against Artificial Analysis and our model card. Deployment details come from our Ollama model page and our Ollama guide. The local results come from the 12-case script; the complete case set is in the appendix below.

Appendix: Complete 12-case bilingual extraction set

The list below preserves each original input, expected object, actual object, and exact-match verdict. Case 4 is the only mismatch.

Case 1 — Pass

Original input: 请把 ticket INC-204 设为 high priority, owner is Maya. Return JSON with ticket, priority, owner.

Expected JSON: {"ticket":"INC-204","priority":"high","owner":"Maya"}

Model output: {"ticket":"INC-204","priority":"high","owner":"Maya"}

Case 2 — Pass

Original input: For ticket INC-205, 负责人是 Leo,优先级 low。Return JSON with ticket, priority, owner.

Expected JSON: {"ticket":"INC-205","priority":"low","owner":"Leo"}

Model output: {"ticket":"INC-205","priority":"low","owner":"Leo"}

Case 3 — Pass

Original input: 请将 order A-17 的 delivery date 改为 2026-10-03, status pending. Return JSON with order, date, status.

Expected JSON: {"order":"A-17","date":"2026-10-03","status":"pending"}

Model output: {"order":"A-17","date":"2026-10-03","status":"pending"}

Case 4 — Fail

Original input: Customer asks to cancel 订单 B-52, but no reason was provided. Return JSON with order, action, reason. Use null for missing reason.

Expected JSON: {"order":"B-52","action":"cancel","reason":null}

Model output: {"order":"B-52","action":"cancelled","reason":null}

Case 5 — Pass

Original input: 请为客户 Ava 写英文回复。The package is delayed by two days. Return JSON with language and delay_days only.

Expected JSON: {"language":"English","delay_days":2}

Model output: {"language":"English","delay_days":2}

Case 6 — Pass

Original input: Ticket INC-210 已解决, but customer needs an English summary. Return JSON with ticket, status, output_language.

Expected JSON: {"ticket":"INC-210","status":"resolved","output_language":"English"}

Model output: {"ticket":"INC-210","status":"resolved","output_language":"English"}

Case 7 — Pass

Original input: 把 invoice INV-88 标为 unpaid; due date 是 2026-10-15. Return JSON with invoice, payment_status, due_date.

Expected JSON: {"invoice":"INV-88","payment_status":"unpaid","due_date":"2026-10-15"}

Model output: {"invoice":"INV-88","payment_status":"unpaid","due_date":"2026-10-15"}

Case 8 — Pass

Original input: Route request R-71 to sales, not support; 优先级为 medium。Return JSON with request, team, priority.

Expected JSON: {"request":"R-71","team":"sales","priority":"medium"}

Model output: {"request":"R-71","team":"sales","priority":"medium"}

Case 9 — Pass

Original input: 客户要更新 address, but the new address is missing. Return JSON with action, new_address. Use null when missing.

Expected JSON: {"action":"update_address","new_address":null}

Model output: {"action":"update_address","new_address":null}

Case 10 — Pass

Original input: Please schedule meeting M-12 on 2026-10-08 at 14:30, 时区是 Asia/Shanghai. Return JSON with meeting, date, time, timezone.

Expected JSON: {"meeting":"M-12","date":"2026-10-08","time":"14:30","timezone":"Asia/Shanghai"}

Model output: {"meeting":"M-12","date":"2026-10-08","time":"14:30","timezone":"Asia/Shanghai"}

Case 11 — Pass

Original input: 订单 C-90 要 refund 25 USD, not 52 USD. Return JSON with order, action, amount, currency.

Expected JSON: {"order":"C-90","action":"refund","amount":25,"currency":"USD"}

Model output: {"order":"C-90","action":"refund","amount":25,"currency":"USD"}

Case 12 — Pass

Original input: For task T-6, 输出中文还是英文? User says: reply in English. Return JSON with task and reply_language.

Expected JSON: {"task":"T-6","reply_language":"English"}

Model output: {"task":"T-6","reply_language":"English"}