Instructions to use Nanbeige/Nanbeige4.2-3B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Nanbeige/Nanbeige4.2-3B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Nanbeige/Nanbeige4.2-3B", trust_remote_code=True) messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("Nanbeige/Nanbeige4.2-3B", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Nanbeige/Nanbeige4.2-3B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Nanbeige/Nanbeige4.2-3B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Nanbeige/Nanbeige4.2-3B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/Nanbeige/Nanbeige4.2-3B
- SGLang
How to use Nanbeige/Nanbeige4.2-3B 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 "Nanbeige/Nanbeige4.2-3B" \ --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": "Nanbeige/Nanbeige4.2-3B", "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 "Nanbeige/Nanbeige4.2-3B" \ --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": "Nanbeige/Nanbeige4.2-3B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use Nanbeige/Nanbeige4.2-3B with Docker Model Runner:
docker model run hf.co/Nanbeige/Nanbeige4.2-3B
llama.cpp silently drops valid tool calls (parser bug, not the model) - 2-line fix for your fork!
Heads-up for anyone running this model through the nanbeige42 llama.cpp fork: a chunk of its tool calls are being thrown away by the parser, not by the model. The model emits them correctly. I measured it and patched it locally, so I wanted to share, since it makes the model look meaningfully worse than it is.
Setup: nanbeige4.2-3b-Q8_0.gguf (quantized from BF16 with the fork's llama-quantize), fork at d28da86, branch nanbeige42, --jinja, and the card's agentic sampling (temp 1.0, top-p 0.95, top-k 20).
What happens
Roughly one call in six comes back with tool_calls empty and the entire reply sitting in message.content as plain text, like this:
<tool_call>
<function=bash>
<parameter=command>
ls -la /tmp
</parameter>
</function>
</tool_call>
That is a perfectly well-formed call. The only difference from the ones that parse is a single space after <tool_call>, before the newline.
It looks like a sampling artifact: in a small probe (4 samples per config, same prompt) every generation parsed at temp 0, while at temp 1.0 some configurations dropped to 2/4. That means the card's recommended agentic temp of 1.0 is where it hits -- worst-case scenario.
Why
llama.cpp's auto-parser analyzes the template and derives per_call_start = "<tool_call>\n", with the newline baked into the marker. Two places in build_tool_parser_tag_tagged (common/chat-auto-parser-generator.cpp) then require it verbatim:
- the call marker is built as an exact literal, so
<tool_call> \ndoes not match; and - the content boundary is
p.until(trigger_marker)using that same untrimmed marker.
(2) is the one that actually causes the damage. until() looks for the literal <tool_call>\n, never finds it in padded output, and consumes the whole generation as content - so the tool-call rule never even runs. That is why the failure looks like "the model declined to call a tool" rather than a parse error. Fixing (1) alone changes nothing.
Fix
Two lines, both reusing helpers already in that file:
- auto wrapped_call = format.per_call_start + p.space() + tool_choice + p.space() + format.per_call_end;
+ auto wrapped_call = p.optspace(format.per_call_start) + p.space() + tool_choice + p.space() + format.per_call_end;
- auto content_before_tools = trigger_marker.empty() ? p.eps() : p.until(trigger_marker);
+ auto content_before_tools = trigger_marker.empty() ? p.eps() : p.until(trim_whitespace(trigger_marker));
Careful if you apply by hand: that second context line appears twice in the file. The one to change is in build_tool_parser_tag_tagged. The identical line in build_tool_parser_tag_json is a different format with no test coverage, and I left it alone.
Measured effect
35-case tool-calling suite hitting the OpenAI-compatible endpoint directly (29 tool cases, 6 abstention cases), same server and sampling before and after, Q8_0:
| before | after | |
|---|---|---|
| parseable call naming a real tool | 24/29 (83%) | 29/29 (100%) |
| correct tool chosen | 23/29 (79%) | 27/29 (93%) |
| arguments satisfy the case check | 20/26 (77%) | 24/26 (92%) |
| correctly abstained when no tool applies | 6/6 | 6/6 |
All five recovered calls were already well-formed. By category, simple went 50% -> 100% and tool_choice 40% -> 100% valid.
Note on where the fix belongs
That file is unmodified from upstream in your fork, so ggml-org/llama.cpp is affected identically. Nemotron lands in the same code path with the same per_call_start = "<tool_call>\n" (asserted in llama.cpp's own test suite), and Seed-OSS renders the same marker-plus-newline shape (<seed:tool_call>\n<function=...>), though I have not run the analyzer on it to confirm. Fixing it upstream would cover your model and theirs at once. I have the patch plus a regression test ready and am happy to send it wherever is most useful; your fork has issues disabled, which is why I am posting here.
(Disclosure: the diagnosis was done with the help of AI coding agents - isolating the failing input and reading the PEG parser trace to find the until() boundary as the real culprit. The measurements above are from my own runs.)
Have you send an issus or a PR to ggml-org/llama.cpp?