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.)