Instructions to use OculusMindAI/OculusMind-ToolCall-8B-v2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="OculusMindAI/OculusMind-ToolCall-8B-v2") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("OculusMindAI/OculusMind-ToolCall-8B-v2") model = AutoModelForCausalLM.from_pretrained("OculusMindAI/OculusMind-ToolCall-8B-v2", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0 # Run inference directly in the terminal: llama cli -hf OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0 # Run inference directly in the terminal: llama cli -hf OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0 # Run inference directly in the terminal: ./build/bin/llama cli -hf OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
Use Docker
docker model run hf.co/OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
- Llama new
- LM Studio
- Jan
- vLLM
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "OculusMindAI/OculusMind-ToolCall-8B-v2" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "OculusMindAI/OculusMind-ToolCall-8B-v2", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
- SGLang
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 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 "OculusMindAI/OculusMind-ToolCall-8B-v2" \ --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": "OculusMindAI/OculusMind-ToolCall-8B-v2", "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 "OculusMindAI/OculusMind-ToolCall-8B-v2" \ --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": "OculusMindAI/OculusMind-ToolCall-8B-v2", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Ollama
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 with Ollama:
ollama run hf.co/OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
- Unsloth Desktop
- Pi
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 with Docker Model Runner:
docker model run hf.co/OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
- Lemonade
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
Run and chat with the model
lemonade run user.OculusMind-ToolCall-8B-v2-Q8_0
List all available models
lemonade list
- Hermes Agent
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use OculusMindAI/OculusMind-ToolCall-8B-v2 with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "OculusMindAI/OculusMind-ToolCall-8B-v2:Q8_0" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
Download APPENDIX-looping.md from OculusMindAI/OculusMind-ToolCall-8B-v2: direct link, hf CLI and curl.
- Browser
- Download file 13.2 kB
-
https://huggingface.co/OculusMindAI/OculusMind-ToolCall-8B-v2/resolve/main/APPENDIX-looping.md
- Command line
-
hf download hf://OculusMindAI/OculusMind-ToolCall-8B-v2/APPENDIX-looping.md
-
curl -L -o APPENDIX-looping.md https://huggingface.co/OculusMindAI/OculusMind-ToolCall-8B-v2/resolve/main/APPENDIX-looping.md
Appendix: the tool-call loop defect, and the seed sweep against it
Every number here is measured and its artifact is kept.
What the defect is
A turn ends with the model emitting the same tool call over and over instead of stopping β sometimes the identical call, sometimes the same tool with varied arguments. The worst example we recorded ran 313 consecutive tool calls in a single turn. In production this is not a quality problem, it is an availability one: the turn never terminates, and it consumes the budget of whatever called it.
Scope of the claim β read this before quoting any number here
Everything below was measured on one checkpoint:
mistralai/Ministral-3-8B-Instruct-2512-BF16 at revision
f6fae9795746f63c9be8344932f01275f3c63734, served as Q8_0 GGUF through
llama.cpp c812c543f, on our production-derived suite.
This is not a claim about "Mistral models". A family name predicts neither the
behaviour nor the licence of its next release, and this project has an expensive
worked example: Ministral-8B-Instruct-2410 is research-licensed while
Ministral-3-8B-Instruct-2512 is apache-2.0 β same product name, opposite
answers. We have not measured any other Mistral checkpoint, so we say nothing
about them. What we can say is that our pinned base exhibits the defect, and
that fine-tuning moves the rate in both directions depending on nothing but the
seed.
The base already loops
| population | loop rate | worst response |
|---|---|---|
| full faithful set (1,133 tool-turns, 1,965 items) | π΄ 0.09 % (1 turn) | 111 calls |
select-vera (146 tool-turns) |
π΄ 0.68 % (1 turn) | 111 calls |
screen-vera (212 tool-turns) |
π΄ 0.47 % (1 turn) | 111 calls |
The first row is the number to quote, and all three rows are the same single event seen through different denominators β one looping turn, 111 calls, a single tool name repeated 108 times. On 146 tool-turns that one turn is 0.68 %; on 1,133 it is 0.09 %. Nothing about the base changed between those measurements, and quoting the largest of them because it is the most convenient would be reporting a sample size as a finding.
The scan completed 2026-10-02 over 1,965 of 1,965 collectable items (Q8_0,
temperature 0, cap 4096), and its scorer output is kept at
benchmarks/base-scans/faithful-all-q8-cap4096/scores.json. The name-repeat
histogram is the useful shape: 1,059 turns repeat a tool name once, 52 call no
tool, a thin tail reaches 10 β and then one turn sits at 108, with nothing in
between. The defect is rare and catastrophic, not a gradient, which is why a
threshold-based gate works at all and why an aggregate rate understates it: the
cost of the one turn is an unterminated production request, not 0.09 % of a
quality score.
So the defect is not introduced by fine-tuning. That matters for reading everything below: a trained arm with a non-zero rate has not necessarily been damaged, and an arm at zero has genuinely removed something the base does.
How a loop is detected
Three independent readings, any one of which condemns a turn:
| rule | threshold | what it catches |
|---|---|---|
maxIdenticalCallRepeat |
β₯ 8 | the identical (name, arguments) signature repeated |
toolCallCount |
β₯ 200 | a runaway trajectory of any shape |
maxToolNameRepeat |
β₯ 24 | the same tool NAME repeated, arguments ignored |
The third rule exists because a model that loops while varying one argument field looks like progress to a signature-based check and is the same failure.
The name threshold was calibrated against production traffic, not guessed.
At 24 it is deliberately generous: a stricter setting of 12 condemns a real
production turn that called web_search 15 times with distinct site: queries β
legitimate work. A detector that cannot tell a loop from a thorough search is
worse than none, because it teaches you to distrust it.
The sweep
Ten runs, seeds 42β51. Identical dataset (l2-3f301662871f), recipe (LoRA
rank 8, dropout 0.05, scale 1.0, attention projections only, lr 2e-5 cosine),
checkpoint (150), quantisation and scoring population. The seed is the only
difference.
A seed is not a quantity β it is the initial state of a pseudo-random generator,
and here it controls three things: LoRA A initialisation, every dropout mask,
and data order. We checked that consecutive seeds are not secretly similar:
across MLX's RNG and numpy's permutation, mean |r| between adjacent seeds (0.0037
and 0.0181) sits at or below the noise floor and is no higher than between
distant values like 1009 and 999983. 42β51 samples the same distribution that
scattered values would.
Results
validFirstToolMatchPct on select-vera, 146 tool-turns, cap 4096, temperature 0.
| seed | score | Ξ vs base | loop rate | worst response | gate |
|---|---|---|---|---|---|
| base (untrained) | 80.82 β‘ | β | π΄ 0.68 % | 272 | β |
| 46 | 96.58 | π’ +15.76 pts (+19.5 %) | 0.00 % | 13 | passes |
| 48 | 96.58 | π’ +15.76 pts (+19.5 %) | π΄ 0.68 % | 116 | excluded |
| 43 | 95.21 | π’ +14.39 pts (+17.8 %) | π΄ 0.68 % | 292 | excluded |
| 42 | 92.92 β | not comparable | 0.00 % | 13 | passes |
| 45 | 93.15 | π’ +12.33 pts (+15.3 %) | 0.00 % | β | passes |
| 50 | 93.15 | π’ +12.33 pts (+15.3 %) | π΄ 1.37 % | β | excluded |
| 49 | 92.47 | π’ +11.65 pts (+14.4 %) | π΄ 5.48 % | β | excluded |
| 44 | 91.10 | π’ +10.28 pts (+12.7 %) | π΄ 6.85 % | 313 | excluded |
| 47 | 90.41 | π’ +9.59 pts (+11.9 %) | 0.00 % | β | passes |
| 51 | 94.52 | π’ +13.70 pts (+17.0 %) | 0.00 % | 15 | passes |
β‘ The base was collected directly on these 266 items at the same cap and temperature, three times with identical results; this is the figure the card quotes. (Re-scoring the base's 404-item screen responses on this population gives 74.66 instead β a re-score of a different run, not a measurement of this one.)
β Seed 42 is not measured on this population. It was the original arm and was
scored on screen-vera β 404 items, 212 tool-turns β before the sweep standardised
on select-vera's 266, so 92.92 is its screen-vera figure and is not comparable
to the rest of this column.
Seed 42's artifact-backed figures are: report-vera-sealed 95.45 (66 turns,
tying seed 46), production temperature 0.35 95.21 (146 turns), and the
loop-provocation slice 100.0. Those are the numbers to quote for it.
Five of the ten seeds loop at least once. The rate ranges from 0.00 % to 6.85 % β ten of 146 tool-turns β from one recipe on one dataset. This is real variance in what gets trained, not measurement noise: the loop VERDICT agreed 20/20 across two collections of the same artifact (see "Is it the sampler?").
Is it the sampler, or the model?
The screen is not byte-deterministic. Re-collecting the 20 busiest items against the same artifact gave 14/20 identical tool-call sequences and 19/20 identical text; one item ran 119 calls one time and 158 the next.
That is the right alarm to raise and it does not make the gate unsound, because the gate is a binary per-item verdict and a 119-call and a 158-call runaway are the same verdict. Measured per item with the real scorer, over the same 20 items:
| fact | agreement |
|---|---|
looped |
20/20 |
firstToolMatch |
20/20 |
validFirstToolMatch |
20/20 |
Those 20 were chosen as the busiest β adversarially, where instability compounds β which makes the agreement stronger evidence than a random sample. So the difference between seed 42's zero and seed 44's 6.85 % is a property of the models, not of the sampling.
The gate, and what it cost
Looping is a gate, not a ranking dimension. Any non-zero rate excludes the seed outright; survivors are then ranked on score. There is no ranking within non-zero, because 3 loops versus 4 is noise while zero versus non-zero is not.
For most of the sweep this was free β the best score happened also to be clean. Then seed 48 scored 96.58, identical to seed 46, 141 of 146 tool-turns for both, and loops once. It is excluded and seed 46 ships. Two models indistinguishable on the ranking metric, and the tie broken by the defect rather than by noise in the third decimal.
"You ran ten and shipped the best one" β yes, and here is why the headline survives
This table invites a fair objection: ten runs were made, the one that scored
highest on select-vera is the one being published, so the published selection
score is the maximum of ten draws and is biased upward by construction. That is
correct, and it is why the headline number is not a select-vera number.
The populations have different jobs, fixed before the sweep ran:
| population | role | may inform selection? |
|---|---|---|
screen-vera, select-vera |
screening and ranking the sweep | yes β that is their purpose |
report-vera-sealed (138 items, 66 tool-turns) |
the reported figure | no β held back, scored once |
Seed 46 was chosen on select-vera at 96.58, and that figure is reported here
as what it is: the selection score, the maximum of ten, not a performance claim.
The published claim is 95.45 on report-vera-sealed against the base's 86.36,
measured after selection was already settled, on items that informed no seed or
checkpoint choice (they were part of the earlier screen on which training recipes
were compared β README Β§2).
Two consequences worth stating plainly, because they cut against us:
- The sealed figure is lower than the selection figure (95.45 against 96.58), which is the direction selection bias predicts. We report the lower one.
- Seed 42 ties on the sealed population (95.45, the same 63 of 66 tool-turns) while scoring 2 points lower on the selection population. With 66 tool-turns one turn is 1.5 points, so the sealed measurement cannot separate the top two β and the card says so rather than presenting the selection ordering as a ranking.
What a reader cannot check, and should know they cannot. Nine of the ten seeds are not published, and neither are the evaluation suites β they are built from production captures. So every row in the table above except seed 46's rests on our word. The scorer outputs for all of them are kept, and the exact code, data and artifact behind each is recorded, but that record is internal. We state the rows because omitting them while claiming "selected under a loop gate" would be the weaker position, not because a reader can independently verify them.
The runner-up, and why seed 46 was chosen anyway
Seed 42 ties this model on the reported population (95.45, 63 of 66) and on the loop-provocation slice (100.0). It was separated on three other measurements:
| seed 46 (this model) | seed 42 | Ξ (46 β 42) | |
|---|---|---|---|
report-vera-sealed, temp 0 (66 turns) |
95.45 | 95.45 | Β±0 |
| production temperature 0.35 (146 turns) | 97.26 | 95.21 | π’ +2.05 pts (+2.2 %) |
| worst response on sealed | 6 calls | 12 calls | π’ β6 calls |
| loop-provocation slice | 100.0 (worst 13) | 100.0 (worst 10) | Β±0 |
select-vera, temp 0 (146 turns) |
96.58 | never measured | β |
Seed 42 has no select-vera temperature-0 run under the published recipe: it was
the original arm, scored on screen-vera β 404 items, 212 tool-turns, 92.92 β
before the sweep standardised on select-vera's 266 items, so that row cannot be
filled with a comparable number and is left empty rather than approximated.
The reported figure alone could not choose between them. Saying so is the point: with 66 tool-turns, one turn is 1.5 points, and presenting a tie as a ranking would be presenting a coin-flip as a measurement. The separation that survives is production temperature, where the two were measured on the same 146 tool-turns.
What these numbers do not establish
- "No loop observed on 266 items" is not "never loops." A dedicated provocation slice, built from turns that actually provoked loops, is the stronger test and is reported separately.
- A gate verdict belongs to the population it was measured on. Seed 45 scored
0.00 % on
select-veraand passed, then logged 1.52 % with a 124-call response onreport-vera-sealed. "No loop observed on 266 items" is the honest wording, and this is what it was protecting against. - At production temperature 0.35, none of the three shortlisted seeds looped (worst responses 12β19 calls), against 0.00β1.52 % at temperature 0 on the same items. This is suggestive and not a finding: the base has not been run at 0.35, so whether sampling suppresses the defect or this population simply does not provoke it either way is unmeasured.
- Run-to-run variance of the aggregate score is unbounded on this evidence β 20 items were re-collected, not 266 β so a seed ordering separated by a fraction of a point is not trustworthy. It is sound for a coarse cut.
- One checkpoint, one suite, one quantisation. See "Scope of the claim".