Unsloth Dynamic 2.0 achieves superior accuracy & outperforms other leading quants.
Ministral 3 8B Reasoning 2512
A balanced model in the Ministral 3 family, Ministral 3 8B is a powerful, efficient tiny language model with vision capabilities.
This model is the reasoning post-trained version, trained for reasoning tasks, making it ideal for math, coding and stem related use cases.
The Ministral 3 family is designed for edge deployment, capable of running on a wide range of hardware. Ministral 3 8B can even be deployed locally, capable of fitting in 24GB of VRAM in BF16, and less than 12GB of RAM/VRAM when quantized.
Key Features
Ministral 3 8B consists of two main architectural components:
8.4B Language Model
0.4B Vision Encoder
The Ministral 3 8B Reasoning model offers the following capabilities:
Vision: Enables the model to analyze images and provide insights based on visual content, in addition to text.
Multilingual: Supports dozens of languages, including English, French, Spanish, German, Italian, Portuguese, Dutch, Chinese, Japanese, Korean, Arabic.
System Prompt: Maintains strong adherence and support for system prompts.
Agentic: Offers best-in-class agentic capabilities with native function calling and JSON outputting.
Reasoning: Excels at complex, multi-step reasoning and dynamic problem-solving.
Edge-Optimized: Delivers best-in-class performance at a small scale, deployable anywhere.
Apache 2.0 License: Open-source license allowing usage and modification for both commercial and non-commercial purposes.
Large Context Window: Supports a 256k context window.
Use Cases
Perfect for balanced performance in local or embedded systems, combining versatility with efficiency.
Chat interfaces in constrained environments
Local daily-driver AI assistant
Image/document description and understanding
Translation and content generation
Specialized agentic use cases
Fine-tuning and specialization
And more...
Bringing advanced AI capabilities to resource-constrained environments.
Recommended Settings
We recommend deploying with the following best practices:
System Prompt: Use our provided system prompt, and append it to your custom system prompt to define a clear environment and use case, including guidance on how to effectively leverage tools in agentic systems.
Multi-turn Traces: We highly recommend keeping the reasoning traces in context.
Sampling Parameters: Use a temperature of 0.7 for most environments ; Different temperatures may be explored for different use cases - developers are encouraged to experiment with alternative settings.
Tools: Keep the set of tools well-defined and limit their number to the minimum required for the use case - Avoiding overloading the model with an excessive number of tools.
Vision: When deploying with vision capabilities, we recommend maintaining an aspect ratio close to 1:1 (width-to-height) for images. Avoiding the use of overly thin or wide images - crop them as needed to ensure optimal performance.
enable-auto-tool-choice: Required when enabling tool usage.
tool-call-parser mistral: Required when enabling tool usage.
reasoning-parser mistral: Required when enabling reasoning.
Additional flags:
You can set --max-model-len to preserve memory. By default it is set to 262144 which is quite large but not necessary for most scenarios.
You can set --max-num-batched-tokens to balance throughput and latency, higher means higher throughput but higher latency.
Usage of the model
Here we assume that the model mistralai/Ministral-3-8B-Reasoning-2512 is served and you can ping it to the domain localhost with the port 8000 which is the default for vLLM.
Vision Reasoning
Let's see if the Ministral 3 model knows when to pick a fight !
python
1from typing import Any
23from openai import OpenAI
4from huggingface_hub import hf_hub_download
56# Modify OpenAI's API key and API base to use vLLM's API server.7openai_api_key ="EMPTY"8openai_api_base ="http://localhost:8000/v1"910TEMP =0.711TOP_P =0.9512MAX_TOK =26214413client = OpenAI(14 api_key=openai_api_key,15 base_url=openai_api_base,16)1718models = client.models.list()19model = models.data[0].id202122defload_system_prompt(repo_id:str, filename:str)->dict[str, Any]:23 file_path = hf_hub_download(repo_id=repo_id, filename=filename)24withopen(file_path,"r")asfile:25 system_prompt =file.read()2627 index_begin_think = system_prompt.find("[THINK]")28 index_end_think = system_prompt.find("[/THINK]")2930return{31"role":"system",32"content":[33{"type":"text","text": system_prompt[:index_begin_think]},34{35"type":"thinking",36"thinking": system_prompt[37 index_begin_think +len("[THINK]"): index_end_think
38],39"closed":True,40},41{42"type":"text",43"text": system_prompt[index_end_think +len("[/THINK]"):],44},45],46}474849SYSTEM_PROMPT = load_system_prompt(model,"SYSTEM_PROMPT.txt")5051image_url ="https://static.wikia.nocookie.net/essentialsdocs/images/7/70/Battle.png/revision/latest?cb=20220523172438"5253messages =[54 SYSTEM_PROMPT,55{56"role":"user",57"content":[58{59"type":"text",60"text":"What action do you think I should take in this situation? List all the possible actions and explain why you think they are good or bad.",61},62{"type":"image_url","image_url":{"url": image_url}},63],64},65]666768stream = client.chat.completions.create(69 model=model,70 messages=messages,71 stream=True,72 temperature=TEMP,73 top_p=TOP_P,74 max_tokens=MAX_TOK,75)7677print("client: Start streaming chat completions...:\n")78printed_reasoning_content =False79answer =[]8081for chunk in stream:82 reasoning_content =None83 content =None84# Check the content is reasoning_content or content85ifhasattr(chunk.choices[0].delta,"reasoning_content"):86 reasoning_content = chunk.choices[0].delta.reasoning_content
87ifhasattr(chunk.choices[0].delta,"content"):88 content = chunk.choices[0].delta.content
8990if reasoning_content isnotNone:91ifnot printed_reasoning_content:92 printed_reasoning_content =True93print("Start reasoning:\n", end="", flush=True)94print(reasoning_content, end="", flush=True)95elif content isnotNone:96# Extract and print the content97ifnot reasoning_content and printed_reasoning_content:98 answer.extend(content)99print(content, end="", flush=True)100101if answer:102print("\n\n=============\nAnswer\n=============\n")103print("".join(answer))104else:105print("\n\n=============\nNo Answer\n=============\n")106print(107"No answer was generated by the model, probably because the maximum number of tokens was reached."108)
Now we'll make it compute some maths !
python
1from typing import Any
23from openai import OpenAI
4from huggingface_hub import hf_hub_download
56# Modify OpenAI's API key and API base to use vLLM's API server.7openai_api_key ="EMPTY"8openai_api_base ="http://localhost:8000/v1"910TEMP =0.711TOP_P =0.9512MAX_TOK =26214413client = OpenAI(14 api_key=openai_api_key,15 base_url=openai_api_base,16)1718models = client.models.list()19model = models.data[0].id202122defload_system_prompt(repo_id:str, filename:str)->dict[str, Any]:23 file_path = hf_hub_download(repo_id=repo_id, filename=filename)24withopen(file_path,"r")asfile:25 system_prompt =file.read()2627 index_begin_think = system_prompt.find("[THINK]")28 index_end_think = system_prompt.find("[/THINK]")2930return{31"role":"system",32"content":[33{"type":"text","text": system_prompt[:index_begin_think]},34{35"type":"thinking",36"thinking": system_prompt[37 index_begin_think +len("[THINK]"): index_end_think
38],39"closed":True,40},41{42"type":"text",43"text": system_prompt[index_end_think +len("[/THINK]"):],44},45],46}474849SYSTEM_PROMPT = load_system_prompt(model,"SYSTEM_PROMPT.txt")5051image_url ="https://i.ytimg.com/vi/5Y3xLHeyKZU/hqdefault.jpg"5253messages =[54 SYSTEM_PROMPT,55{56"role":"user",57"content":[58{59"type":"text",60"text":"Solve the equations. If they contain only numbers, use your calculator, else only think. Answer in the language of the image.",61},62{"type":"image_url","image_url":{"url": image_url}},63],64},65]6667stream = client.chat.completions.create(68 model=model,69 messages=messages,70 stream=True,71 temperature=TEMP,72 top_p=TOP_P,73 max_tokens=MAX_TOK,74)7576print("client: Start streaming chat completions...:\n")77printed_reasoning_content =False78answer =[]7980for chunk in stream:81 reasoning_content =None82 content =None83# Check the content is reasoning_content or content84ifhasattr(chunk.choices[0].delta,"reasoning_content"):85 reasoning_content = chunk.choices[0].delta.reasoning_content
86ifhasattr(chunk.choices[0].delta,"content"):87 content = chunk.choices[0].delta.content
8889if reasoning_content isnotNone:90ifnot printed_reasoning_content:91 printed_reasoning_content =True92print("Start reasoning:\n", end="", flush=True)93print(reasoning_content, end="", flush=True)94if content isnotNone:95# Extract and print the content96ifnot reasoning_content and printed_reasoning_content:97 answer.extend(content)98print(content, end="", flush=True)99100if answer:101print("\n\n=============\nAnswer\n=============\n")102print("".join(answer))103else:104print("\n\n=============\nNo Answer\n=============\n")105print(106"No answer was generated by the model, probably because the maximum number of tokens was reached."107)
Text-Only Request
Let's do more maths and leave it up to the model to figure out how to achieve a result.
python
1from typing import Any
2from openai import OpenAI
3from huggingface_hub import hf_hub_download
45# Modify OpenAI's API key and API base to use vLLM's API server.6openai_api_key ="EMPTY"7openai_api_base ="http://localhost:8000/v1"89TEMP =0.710TOP_P =0.9511MAX_TOK =26214412client = OpenAI(13 api_key=openai_api_key,14 base_url=openai_api_base,15)1617models = client.models.list()18model = models.data[0].id192021defload_system_prompt(repo_id:str, filename:str)->dict[str, Any]:22 file_path = hf_hub_download(repo_id=repo_id, filename=filename)23withopen(file_path,"r")asfile:24 system_prompt =file.read()2526 index_begin_think = system_prompt.find("[THINK]")27 index_end_think = system_prompt.find("[/THINK]")2829return{30"role":"system",31"content":[32{"type":"text","text": system_prompt[:index_begin_think]},33{34"type":"thinking",35"thinking": system_prompt[36 index_begin_think +len("[THINK]"): index_end_think
37],38"closed":True,39},40{41"type":"text",42"text": system_prompt[index_end_think +len("[/THINK]"):],43},44],45}464748SYSTEM_PROMPT = load_system_prompt(model,"SYSTEM_PROMPT.txt")4950query ="Use each number in 2,5,6,3 exactly once, along with any combination of +, -, ×, ÷ (and parentheses for grouping), to make the number 24."5152messages =[53 SYSTEM_PROMPT,54{"role":"user","content": query}55]56stream = client.chat.completions.create(57 model=model,58 messages=messages,59 stream=True,60 temperature=TEMP,61 top_p=TOP_P,62 max_tokens=MAX_TOK,63)6465print("client: Start streaming chat completions...:\n")66printed_reasoning_content =False67answer =[]6869for chunk in stream:70 reasoning_content =None71 content =None72# Check the content is reasoning_content or content73ifhasattr(chunk.choices[0].delta,"reasoning_content"):74 reasoning_content = chunk.choices[0].delta.reasoning_content
75ifhasattr(chunk.choices[0].delta,"content"):76 content = chunk.choices[0].delta.content
7778if reasoning_content isnotNone:79ifnot printed_reasoning_content:80 printed_reasoning_content =True81print("Start reasoning:\n", end="", flush=True)82print(reasoning_content, end="", flush=True)83if content isnotNone:84# Extract and print the content85ifnot reasoning_content and printed_reasoning_content:86 answer.extend(content)87print(content, end="", flush=True)8889if answer:90print("\n\n=============\nAnswer\n=============\n")91print("".join(answer))92else:93print("\n\n=============\nNo Answer\n=============\n")94print("No answer was generated by the model, probably because the maximum number of tokens was reached.")
Transformers
You can also use Ministral 3 3B Reasoning 2512 with Transformers !
Make sure to install Transformers from its first v5 release candidate or from "main":
pip install transformers==5.0.0rc0
To make the best use of our model with Transformers make sure to have installedmistral-common >= 1.8.6 to use our tokenizer.
pip install mistral-common --upgrade
Then load our tokenizer along with the model and generate:
Python snippet
python
1import torch
2from transformers import Mistral3ForConditionalGeneration, MistralCommonBackend
34model_id ="mistralai/Ministral-3-8B-Reasoning-2512"56tokenizer = MistralCommonBackend.from_pretrained(model_id)7model = Mistral3ForConditionalGeneration.from_pretrained(8 model_id, torch_dtype=torch.bfloat16, device_map="auto"9)1011image_url ="https://static.wikia.nocookie.net/essentialsdocs/images/7/70/Battle.png/revision/latest?cb=20220523172438"1213messages =[14{15"role":"user",16"content":[17{18"type":"text",19"text":"What action do you think I should take in this situation? List all the possible actions and explain why you think they are good or bad.",20},21{"type":"image_url","image_url":{"url": image_url}},22],23},24]2526tokenized = tokenizer.apply_chat_template(messages, return_tensors="pt", return_dict=True)2728tokenized["input_ids"]= tokenized["input_ids"].to(device="cuda")29tokenized["pixel_values"]= tokenized["pixel_values"].to(dtype=torch.bfloat16, device="cuda")30image_sizes =[tokenized["pixel_values"].shape[-2:]]3132output = model.generate(33**tokenized,34 image_sizes=image_sizes,35 max_new_tokens=8092,36)[0]3738decoded_output = tokenizer.decode(output[len(tokenized["input_ids"][0]):])39print(decoded_output)
You must not use this model in a manner that infringes, misappropriates, or otherwise violates any third party’s rights, including intellectual property rights.