Repository: kaito-project/kaito

Issue:
Add mistral 3 as KAITO Preset
**Is your feature request related to a problem? Please describe.**

https://huggingface.co/collections/mistralai/mistral-large-3

**Describe the solution you'd like**

**Describe alternatives you've considered**

**Additional context**

Hints from issue comments:

Solution patch:
diff --git a/api/v1beta1/workspace_validation.go b/api/v1beta1/workspace_validation.go
index 5d70a2b..f769fc7 100644
--- a/api/v1beta1/workspace_validation.go
+++ b/api/v1beta1/workspace_validation.go
@@ -553,9 +553,11 @@ func (i *InferenceSpec) validateCreate(ctx context.Context, runtime model.Runtim
 			errs = errs.Also(apis.ErrGeneric(fmt.Sprintf("Runtime validation: %v", err)))
 		}
 		// For models that require downloading at runtime, we need to check if the modelAccessSecret is provided
-		if params.DownloadAtRuntime && i.Preset.PresetOptions.ModelAccessSecret == "" {
-			errs = errs.Also(apis.ErrGeneric("This preset requires a modelAccessSecret with HF_TOKEN key under presetOptions to download the model"))
-		} else if !params.DownloadAtRuntime && i.Preset.PresetOptions.ModelAccessSecret != "" {
+		if params.DownloadAtRuntime {
+			if params.DownloadAuthRequired && i.Preset.PresetOptions.ModelAccessSecret == "" {
+				errs = errs.Also(apis.ErrGeneric("This preset requires authentication and needs a modelAccessSecret with HF_TOKEN key under presetOptions to download the model"))
+			}
+		} else if i.Preset.PresetOptions.ModelAccessSecret != "" {
 			errs = errs.Also(apis.ErrGeneric("This preset does not require a modelAccessSecret with HF_TOKEN key under presetOptions"))
 		}
 	}
diff --git a/charts/kaito/workspace/templates/supported-models-configmap.yaml b/charts/kaito/workspace/templates/supported-models-configmap.yaml
index f43f8a7..05ffa19 100644
--- a/charts/kaito/workspace/templates/supported-models-configmap.yaml
+++ b/charts/kaito/workspace/templates/supported-models-configmap.yaml
@@ -14,12 +14,14 @@ data:
         type: text-generation
         version: https://huggingface.co/meta-llama/Llama-3.1-8B-Instruct/commit/0e9e39f249a16976918f6564b8830bc894c89659
         runtime: tfs
+        downloadAuthRequired: true
         downloadAtRuntime: true
         tag: 0.2.0
       - name: llama-3.3-70b-instruct
         type: text-generation
         version: https://huggingface.co/meta-llama/Llama-3.3-70B-Instruct/commit/6f6073b423013f6a7d4d9f39144961bfbfbc386b
         runtime: tfs
+        downloadAuthRequired: true
         downloadAtRuntime: true
         tag: 0.0.1
       - name: deepseek-r1-0528
@@ -64,6 +66,30 @@ data:
         version: https://huggingface.co/mistralai/Mistral-7B-Instruct-v0.3/commit/e0bc86c23ce5aae1db576c8cca6f06f1f73af2db
         runtime: tfs
         tag: 0.2.0
+      - name: ministral-3-3b-instruct
+        type: text-generation
+        version: https://huggingface.co/mistralai/Ministral-3-3B-Instruct-2512/commit/83e15808ff6a115f18ff8e68123db3ab35035714
+        runtime: tfs
+        downloadAtRuntime: true
+        tag: 0.0.1
+      - name: ministral-3-8b-instruct
+        type: text-generation
+        version: https://huggingface.co/mistralai/Ministral-3-8B-Instruct-2512/commit/df904c183734f8760042c708d3629a4ed68b103a
+        runtime: tfs
+        downloadAtRuntime: true
+        tag: 0.0.1
+      - name: ministral-3-14b-instruct
+        type: text-generation
+        version: https://huggingface.co/mistralai/Ministral-3-14B-Instruct-2512/commit/6aa4534f7bb46d16753bd12a08b32810a06b7a14
+        runtime: tfs
+        downloadAtRuntime: true
+        tag: 0.0.1
+      - name: mistral-large-3-675b-instruct
+        type: text-generation
+        version: https://huggingface.co/mistralai/Mistral-Large-3-675B-Instruct-2512/commit/7f13ed24ab52a2a1c35bb26a749ef9d891ee98dd
+        runtime: tfs
+        downloadAtRuntime: true
+        tag: 0.0.1
       - name: phi-2
         type: text-generation
         version: https://huggingface.co/microsoft/phi-2/commit/ef382358ec9e382308935a992d908de099b64c23
diff --git a/docs/proposals/20251205-mistral-3.md b/docs/proposals/20251205-mistral-3.md
new file mode 100644
index 0000000..d363d13
--- /dev/null
+++ b/docs/proposals/20251205-mistral-3.md
@@ -0,0 +1,50 @@
+---
+title: Proposal for New Mistral Model Support
+authors:
+  - "KAITO Contributor"
+reviewers:
+  - "KAITO Maintainers"
+creation-date: 2025-12-05
+last-updated: 2025-12-05
+status: provisional
+---
+
+# Title
+Add support for Ministral-3 and Mistral-Large-3 models.
+
+## Glossary
+N/A
+
+## Summary
+
+This proposal aims to add support for the following Mistral models to KAITO:
+- `mistralai/Ministral-3-3B-Instruct-2512`
+- `mistralai/Ministral-3-14B-Instruct-2512`
+- `mistralai/Ministral-3-8B-Instruct-2512`
+- `mistralai/Mistral-Large-3-675B-Instruct-2512`
+
+These models offer a range of sizes and capabilities, from efficient edge-ready models to large-scale reasoning models.
+
+## Requirements
+
+The following table describes the basic model characteristics and the resource requirements.
+
+| Field | Ministral-3-3B | Ministral-3-8B | Ministral-3-14B | Mistral-Large-3 |
+|---|---|---|---|---|
+| Family name | Mistral | Mistral | Mistral | Mistral |
+| Type | `text generation` | `text generation` | `text generation` | `text generation` |
+| Download site | Hugging Face | Hugging Face | Hugging Face | Hugging Face |
+| Version | TBD | TBD | TBD | TBD |
+| Storage size | ~6GB | ~16GB | ~28GB | ~1350GB |
+| GPU count | 1 | 1 | 1 | 8+ |
+
+## Runtimes
+
+| Options | Notes|
+|----|----|
+| Runtime | Huggingface Transformer / vLLM |
+| Distributed Inference| False (True for Large) |
+
+# History
+
+- [x] 12/05/2025: Open proposal PR.
diff --git a/examples/inference/kaito_workspace_deepseek_r1.yaml b/examples/inference/kaito_workspace_deepseek_r1.yaml
index a55a05c..b8de4ea 100644
--- a/examples/inference/kaito_workspace_deepseek_r1.yaml
+++ b/examples/inference/kaito_workspace_deepseek_r1.yaml
@@ -12,16 +12,6 @@ inference:
   config: "ds-inference-params"
   preset:
     name: "deepseek-r1-0528"
-    presetOptions:
-      modelAccessSecret: hf-token
----
-apiVersion: v1
-kind: Secret
-metadata:
-  name: hf-token
-type: Opaque
-data:
-  HF_TOKEN: <base64-encoded-huggingface-token>
 ---
 apiVersion: v1
 kind: ConfigMap
diff --git a/examples/inference/kaito_workspace_deepseek_v3.yaml b/examples/inference/kaito_workspace_deepseek_v3.yaml
index cd3ebad..b369cf9 100644
--- a/examples/inference/kaito_workspace_deepseek_v3.yaml
+++ b/examples/inference/kaito_workspace_deepseek_v3.yaml
@@ -12,16 +12,6 @@ inference:
   config: "ds-inference-params"
   preset:
     name: "deepseek-v3-0324"
-    presetOptions:
-      modelAccessSecret: hf-token
----
-apiVersion: v1
-kind: Secret
-metadata:
-  name: hf-token
-type: Opaque
-data:
-  HF_TOKEN: <base64-encoded-huggingface-token>
 ---
 apiVersion: v1
 kind: ConfigMap
diff --git a/examples/inference/kaito_workspace_ministral_3_14b_instruct.yaml b/examples/inference/kaito_workspace_ministral_3_14b_instruct.yaml
new file mode 100644
index 0000000..ccc81b3
--- /dev/null
+++ b/examples/inference/kaito_workspace_ministral_3_14b_instruct.yaml
@@ -0,0 +1,12 @@
+apiVersion: kaito.sh/v1beta1
+kind: Workspace
+metadata:
+  name: workspace-ministral-3-14b-instruct
+resource:
+  instanceType: "Standard_NC24ads_A100_v4"
+  labelSelector:
+    matchLabels:
+      apps: ministral-3-14b-instruct
+inference:
+  preset:
+    name: "ministral-3-14b-instruct"
diff --git a/examples/inference/kaito_workspace_ministral_3_3b_instruct.yaml b/examples/inference/kaito_workspace_ministral_3_3b_instruct.yaml
new file mode 100644
index 0000000..c4ee05a
--- /dev/null
+++ b/examples/inference/kaito_workspace_ministral_3_3b_instruct.yaml
@@ -0,0 +1,12 @@
+apiVersion: kaito.sh/v1beta1
+kind: Workspace
+metadata:
+  name: workspace-ministral-3-3b-instruct
+resource:
+  instanceType: "Standard_NV36ads_A10_v5"
+  labelSelector:
+    matchLabels:
+      apps: ministral-3-3b-instruct
+inference:
+  preset:
+    name: "ministral-3-3b-instruct"
diff --git a/examples/inference/kaito_workspace_ministral_3_8b_instruct.yaml b/examples/inference/kaito_workspace_ministral_3_8b_instruct.yaml
new file mode 100644
index 0000000..2c34bb0
--- /dev/null
+++ b/examples/inference/kaito_workspace_ministral_3_8b_instruct.yaml
@@ -0,0 +1,12 @@
+apiVersion: kaito.sh/v1beta1
+kind: Workspace
+metadata:
+  name: workspace-ministral-3-8b-instruct
+resource:
+  instanceType: "Standard_NC24ads_A100_v4"
+  labelSelector:
+    matchLabels:
+      apps: ministral-3-8b-instruct
+inference:
+  preset:
+    name: "ministral-3-8b-instruct"
diff --git a/examples/inference/kaito_workspace_mistral_large_3_675b_instruct.yaml b/examples/inference/kaito_workspace_mistral_large_3_675b_instruct.yaml
new file mode 100644
index 0000000..de05739
--- /dev/null
+++ b/examples/inference/kaito_workspace_mistral_large_3_675b_instruct.yaml
@@ -0,0 +1,13 @@
+apiVersion: kaito.sh/v1beta1
+kind: Workspace
+metadata:
+  name: workspace-mistral-large-3-675b-instruct
+resource:
+  count: 6
+  instanceType: "Standard_NC80adis_H100_v5"
+  labelSelector:
+    matchLabels:
+      apps: mistral-large-3-675b-instruct
+inference:
+  preset:
+    name: "mistral-large-3-675b-instruct"
diff --git a/hack/compare_model_configs.sh b/hack/compare_model_configs.sh
index 7db4b0f..2edd236 100755
--- a/hack/compare_model_configs.sh
+++ b/hack/compare_model_configs.sh
@@ -96,7 +96,7 @@ extract_configmap_models() {
         found=1; 
         next 
     } 
-    found && /^[[:space:]]*[a-zA-Z]/ && !/^[[:space:]]*models:/ && !/^[[:space:]]*-/ && !/^[[:space:]]*name:/ && !/^[[:space:]]*type:/ && !/^[[:space:]]*version:/ && !/^[[:space:]]*runtime:/ && !/^[[:space:]]*downloadAtRuntime:/ && !/^[[:space:]]*deprecated:/ && !/^[[:space:]]*tag:/ && !/^[[:space:]]*resources:/ && !/^[[:space:]]*instanceType:/ && !/^[[:space:]]*labelSelector:/ && !/^[[:space:]]*preferredInstance:/ { 
+    found && /^[[:space:]]*[a-zA-Z]/ && !/^[[:space:]]*models:/ && !/^[[:space:]]*-/ && !/^[[:space:]]*name:/ && !/^[[:space:]]*type:/ && !/^[[:space:]]*version:/ && !/^[[:space:]]*runtime:/ && !/^[[:space:]]*downloadAtRuntime:/ && !/^[[:space:]]*downloadAuthRequired:/ && !/^[[:space:]]*deprecated:/ && !/^[[:space:]]*tag:/ && !/^[[:space:]]*resources:/ && !/^[[:space:]]*instanceType:/ && !/^[[:space:]]*labelSelector:/ && !/^[[:space:]]*preferredInstance:/ { 
         found=0 
     } 
     found { 
diff --git a/pkg/model/interface.go b/pkg/model/interface.go
index e9a8dea..9e3ede9 100644
--- a/pkg/model/interface.go
+++ b/pkg/model/interface.go
@@ -87,6 +87,10 @@ type Metadata struct {
 	// +optional
 	DownloadAtRuntime bool `yaml:"downloadAtRuntime,omitempty"`
 
+	// DownloadAuthRequired indicates whether the model requires authentication to download.
+	// +optional
+	DownloadAuthRequired bool `yaml:"downloadAuthRequired,omitempty"`
+
 	// Tag is the tag of the container image used to run the model.
 	// If the model uses the KAITO base image, the tag field can be ignored
 	// +optional
@@ -104,8 +108,8 @@ type Metadata struct {
 
 // Validate checks if the Metadata is valid.
 func (m *Metadata) Validate() error {
-	// Some private models may not have a version URL, so we allow it to be empty until
-	// we remove support for private preset models.
+	// Some models requiring authentication may not have a version URL, so we allow it to be empty until
+	// we remove support for preset models requiring authentication.
 	if m.Version == "" {
 		return nil
 	}
diff --git a/pkg/workspace/inference/preset_inferences.go b/pkg/workspace/inference/preset_inferences.go
index d99eefb..38b0d3d 100644
--- a/pkg/workspace/inference/preset_inferences.go
+++ b/pkg/workspace/inference/preset_inferences.go
@@ -414,21 +414,23 @@ func GenerateInferencePodSpec(gpuConfig *sku.GPUConfig, numNodes int) func(*gene
 
 func SetModelDownloadInfo(ctx *generator.WorkspaceGeneratorContext, spec *corev1.PodSpec) error {
 	if ctx.Model.GetInferenceParameters().DownloadAtRuntime {
-		envvar := corev1.EnvVar{
-			Name: "HF_TOKEN",
-			ValueFrom: &corev1.EnvVarSource{
-				SecretKeyRef: &corev1.SecretKeySelector{
-					LocalObjectReference: corev1.LocalObjectReference{
-						Name: ctx.Workspace.Inference.Preset.PresetOptions.ModelAccessSecret,
+		if accessSecret := ctx.Workspace.Inference.Preset.PresetOptions.ModelAccessSecret; accessSecret != "" {
+			envvar := corev1.EnvVar{
+				Name: "HF_TOKEN",
+				ValueFrom: &corev1.EnvVarSource{
+					SecretKeyRef: &corev1.SecretKeySelector{
+						LocalObjectReference: corev1.LocalObjectReference{
+							Name: ctx.Workspace.Inference.Preset.PresetOptions.ModelAccessSecret,
+						},
+						Key: "HF_TOKEN",
 					},
-					Key: "HF_TOKEN",
 				},
-			},
-		}
+			}
 
-		for i := range spec.Containers {
-			// add HF_TOKEN env var to all containers
-			spec.Containers[i].Env = append(spec.Containers[i].Env, envvar)
+			for i := range spec.Containers {
+				// add HF_TOKEN env var to all containers
+				spec.Containers[i].Env = append(spec.Containers[i].Env, envvar)
+			}
 		}
 		return nil
 	}
diff --git a/presets/workspace/models/deepseek/model.go b/presets/workspace/models/deepseek/model.go
index 5a869d9..7af4e4c 100644
--- a/presets/workspace/models/deepseek/model.go
+++ b/presets/workspace/models/deepseek/model.go
@@ -175,8 +175,10 @@ func (*deepseekR1) GetInferenceParameters() *model.PresetParam {
 		DiskStorageRequirement:  "800Gi",
 		GPUCountRequirement:     "1",
 		TotalSafeTensorFileSize: "641.3Gi", // at least 8 H100
-		BytesPerToken:           1748992,
-		ModelTokenLimit:         163840, // max_position_embeddings from DeepSeek-R1-0528 config
+		// According to Multi-Head Latent Attention (MLA).
+		// BytesPerToken = 2 * (kv_lora_rank + qk_rope_head_dim) * num_hidden_layers
+		BytesPerToken:   70272,
+		ModelTokenLimit: 163840, // max_position_embeddings from DeepSeek-R1-0528 config
 		RuntimeParam: model.RuntimeParam{
 			Transformers: model.HuggingfaceTransformersParam{
 				BaseCommand:       baseCommandPresetDeepseekInference,
@@ -215,8 +217,10 @@ func (*deepseekV3) GetInferenceParameters() *model.PresetParam {
 		DiskStorageRequirement:  "800Gi",
 		GPUCountRequirement:     "1",
 		TotalSafeTensorFileSize: "641.3Gi", // at least 8 H100
-		BytesPerToken:           1748992,
-		ModelTokenLimit:         163840, // max_position_embeddings from DeepSeek-V3-0324 config
+		// According to Multi-Head Latent Attention (MLA).
+		// BytesPerToken = 2 * (kv_lora_rank + qk_rope_head_dim) * num_hidden_layers
+		BytesPerToken:   70272,
+		ModelTokenLimit: 163840, // max_position_embeddings from DeepSeek-V3-0324 config
 		RuntimeParam: model.RuntimeParam{
 			Transformers: model.HuggingfaceTransformersParam{
 				BaseCommand:       baseCommandPresetDeepseekInference,
diff --git a/presets/workspace/models/mistral/model.go b/presets/workspace/models/mistral/model.go
index dd75277..502e723 100644
--- a/presets/workspace/models/mistral/model.go
+++ b/presets/workspace/models/mistral/model.go
@@ -31,11 +31,32 @@ func init() {
 		Name:     PresetMistral7BInstructModel,
 		Instance: &mistralB,
 	})
+	plugin.KaitoModelRegister.Register(&plugin.Registration{
+		Name:     PresetMinistral33BInstructModel,
+		Instance: &ministral3_3bInst,
+	})
+	plugin.KaitoModelRegister.Register(&plugin.Registration{
+		Name:     PresetMinistral38BInstructModel,
+		Instance: &ministral3_8bInst,
+	})
+	plugin.KaitoModelRegister.Register(&plugin.Registration{
+		Name:     PresetMinistral314BInstructModel,
+		Instance: &ministral3_14bInst,
+	})
+	plugin.KaitoModelRegister.Register(&plugin.Registration{
+		Name:     PresetMistralLarge3675BInstructModel,
+		Instance: &mistralLarge3_675bInst,
+	})
 }
 
 const (
 	PresetMistral7BModel         = "mistral-7b"
 	PresetMistral7BInstructModel = PresetMistral7BModel + "-instruct"
+
+	PresetMinistral33BInstructModel      = "ministral-3-3b-instruct"
+	PresetMinistral38BInstructModel      = "ministral-3-8b-instruct"
+	PresetMinistral314BInstructModel     = "ministral-3-14b-instruct"
+	PresetMistralLarge3675BInstructModel = "mistral-large-3-675b-instruct"
 )
 
 var (
@@ -51,6 +72,14 @@ var (
 		"tool-call-parser":        "mistral",
 		"enable-auto-tool-choice": "",
 	}
+	mistral3RunParamsVLLM = map[string]string{
+		"dtype":                   "float16",
+		"tool-call-parser":        "mistral",
+		"tokenizer_mode":          "mistral",
+		"config_format":           "mistral",
+		"load_format":             "mistral",
+		"enable-auto-tool-choice": "",
+	}
 )
 
 var mistralA mistral7b
@@ -144,3 +173,132 @@ func (*mistral7bInst) SupportDistributedInference() bool {
 func (*mistral7bInst) SupportTuning() bool {
 	return false
 }
+
+var ministral3_3bInst ministral3_3bInstruct
+var ministral3_8bInst ministral3_8bInstruct
+var ministral3_14bInst ministral3_14bInstruct
+var mistralLarge3_675bInst mistralLarge3_675bInstruct
+
+type ministral3_3bInstruct struct{}
+
+func (*ministral3_3bInstruct) GetInferenceParameters() *model.PresetParam {
+	return &model.PresetParam{
+		Metadata:                metadata.MustGet(PresetMinistral33BInstructModel),
+		DiskStorageRequirement:  "50Gi",
+		GPUCountRequirement:     "1",
+		TotalSafeTensorFileSize: "8.70Gi",
+		BytesPerToken:           106496,
+		ModelTokenLimit:         262144,
+		RuntimeParam: model.RuntimeParam{
+			Transformers: model.HuggingfaceTransformersParam{
+				AccelerateParams:  inference.DefaultAccelerateParams,
+				ModelRunParams:    mistralRunParams,
+				BaseCommand:       baseCommandPresetMistralInference,
+				InferenceMainFile: inference.DefaultTransformersMainFile,
+			},
+			VLLM: model.VLLMParam{
+				BaseCommand:    inference.DefaultVLLMCommand,
+				ModelName:      PresetMinistral33BInstructModel,
+				ModelRunParams: mistral3RunParamsVLLM,
+			},
+		},
+		ReadinessTimeout: time.Duration(30) * time.Minute,
+	}
+}
+func (*ministral3_3bInstruct) GetTuningParameters() *model.PresetParam { return nil }
+func (*ministral3_3bInstruct) SupportDistributedInference() bool       { return false }
+func (*ministral3_3bInstruct) SupportTuning() bool                     { return false }
+
+type ministral3_8bInstruct struct{}
+
+func (*ministral3_8bInstruct) GetInferenceParameters() *model.PresetParam {
+	return &model.PresetParam{
+		Metadata:                metadata.MustGet(PresetMinistral38BInstructModel),
+		DiskStorageRequirement:  "100Gi",
+		GPUCountRequirement:     "1",
+		TotalSafeTensorFileSize: "19.41Gi",
+		BytesPerToken:           139264,
+		ModelTokenLimit:         262144,
+		RuntimeParam: model.RuntimeParam{
+			Transformers: model.HuggingfaceTransformersParam{
+				AccelerateParams:  inference.DefaultAccelerateParams,
+				ModelRunParams:    mistralRunParams,
+				BaseCommand:       baseCommandPresetMistralInference,
+				InferenceMainFile: inference.DefaultTransformersMainFile,
+			},
+			VLLM: model.VLLMParam{
+				BaseCommand:    inference.DefaultVLLMCommand,
+				ModelName:      PresetMinistral38BInstructModel,
+				ModelRunParams: mistral3RunParamsVLLM,
+			},
+		},
+		ReadinessTimeout: time.Duration(30) * time.Minute,
+	}
+}
+func (*ministral3_8bInstruct) GetTuningParameters() *model.PresetParam { return nil }
+func (*ministral3_8bInstruct) SupportDistributedInference() bool       { return false }
+func (*ministral3_8bInstruct) SupportTuning() bool                     { return false }
+
+type ministral3_14bInstruct struct{}
+
+func (*ministral3_14bInstruct) GetInferenceParameters() *model.PresetParam {
+	return &model.PresetParam{
+		Metadata:                metadata.MustGet(PresetMinistral314BInstructModel),
+		DiskStorageRequirement:  "100Gi",
+		GPUCountRequirement:     "1",
+		TotalSafeTensorFileSize: "29.29Gi",
+		BytesPerToken:           163840,
+		ModelTokenLimit:         262144,
+		RuntimeParam: model.RuntimeParam{
+			Transformers: model.HuggingfaceTransformersParam{
+				AccelerateParams:  inference.DefaultAccelerateParams,
+				ModelRunParams:    mistralRunParams,
+				BaseCommand:       baseCommandPresetMistralInference,
+				InferenceMainFile: inference.DefaultTransformersMainFile,
+			},
+			VLLM: model.VLLMParam{
+				BaseCommand:    inference.DefaultVLLMCommand,
+				ModelName:      PresetMinistral314BInstructModel,
+				ModelRunParams: mistral3RunParamsVLLM,
+			},
+		},
+		ReadinessTimeout: time.Duration(30) * time.Minute,
+	}
+}
+func (*ministral3_14bInstruct) GetTuningParameters() *model.PresetParam { return nil }
+func (*ministral3_14bInstruct) SupportDistributedInference() bool       { return false }
+func (*ministral3_14bInstruct) SupportTuning() bool                     { return false }
+
+type mistralLarge3_675bInstruct struct{}
+
+func (*mistralLarge3_675bInstruct) GetInferenceParameters() *model.PresetParam {
+	return &model.PresetParam{
+		Metadata:                metadata.MustGet(PresetMistralLarge3675BInstructModel),
+		DiskStorageRequirement:  "800Gi",
+		GPUCountRequirement:     "1",
+		TotalSafeTensorFileSize: "634.70Gi",
+		// According to Multi-Head Latent Attention (MLA).
+		// BytesPerToken = 2 * (kv_lora_rank + qk_rope_head_dim) * num_hidden_layers
+		BytesPerToken:   70272,
+		ModelTokenLimit: 262144,
+		RuntimeParam: model.RuntimeParam{
+			Transformers: model.HuggingfaceTransformersParam{
+				AccelerateParams:  inference.DefaultAccelerateParams,
+				ModelRunParams:    mistralRunParams,
+				BaseCommand:       baseCommandPresetMistralInference,
+				InferenceMainFile: inference.DefaultTransformersMainFile,
+			},
+			VLLM: model.VLLMParam{
+				BaseCommand:          inference.DefaultVLLMCommand,
+				ModelName:            PresetMistralLarge3675BInstructModel,
+				ModelRunParams:       mistral3RunParamsVLLM,
+				RayLeaderBaseCommand: inference.DefaultVLLMRayLeaderBaseCommand,
+				RayWorkerBaseCommand: inference.DefaultVLLMRayWorkerBaseCommand,
+			},
+		},
+		ReadinessTimeout: time.Duration(60) * time.Minute,
+	}
+}
+func (*mistralLarge3_675bInstruct) GetTuningParameters() *model.PresetParam { return nil }
+func (*mistralLarge3_675bInstruct) SupportDistributedInference() bool       { return true }
+func (*mistralLarge3_675bInstruct) SupportTuning() bool                     { return false }
diff --git a/presets/workspace/models/supported_models.yaml b/presets/workspace/models/supported_models.yaml
index 62ded4f..b8a0b72 100644
--- a/presets/workspace/models/supported_models.yaml
+++ b/presets/workspace/models/supported_models.yaml
@@ -21,6 +21,7 @@ models:
     type: text-generation
     version: https://huggingface.co/meta-llama/Llama-3.1-8B-Instruct/commit/0e9e39f249a16976918f6564b8830bc894c89659
     runtime: tfs
+    downloadAuthRequired: true
     downloadAtRuntime: true
     tag: 0.2.0
     # Tag history:
@@ -30,6 +31,7 @@ models:
     type: text-generation
     version: https://huggingface.co/meta-llama/Llama-3.3-70B-Instruct/commit/6f6073b423013f6a7d4d9f39144961bfbfbc386b
     runtime: tfs
+    downloadAuthRequired: true
     downloadAtRuntime: true
     tag: 0.0.1
     # Tag history:
@@ -122,6 +124,38 @@ models:
     # 0.0.2 - Inference API Cleanup (#233)
     # 0.0.1 - Initial Release
 
+  - name: ministral-3-3b-instruct
+    type: text-generation
+    version: https://huggingface.co/mistralai/Ministral-3-3B-Instruct-2512/commit/83e15808ff6a115f18ff8e68123db3ab35035714
+    runtime: tfs
+    downloadAtRuntime: true
+    tag: 0.0.1
+    # Tag history:
+    # 0.0.1 - New Model!
+  - name: ministral-3-8b-instruct
+    type: text-generation
+    version: https://huggingface.co/mistralai/Ministral-3-8B-Instruct-2512/commit/df904c183734f8760042c708d3629a4ed68b103a
+    runtime: tfs
+    downloadAtRuntime: true
+    tag: 0.0.1
+    # Tag history:
+    # 0.0.1 - New Model!
+  - name: ministral-3-14b-instruct
+    type: text-generation
+    version: https://huggingface.co/mistralai/Ministral-3-14B-Instruct-2512/commit/6aa4534f7bb46d16753bd12a08b32810a06b7a14
+    runtime: tfs
+    downloadAtRuntime: true
+    tag: 0.0.1
+    # Tag history:
+    # 0.0.1 - New Model!
+  - name: mistral-large-3-675b-instruct
+    type: text-generation
+    version: https://huggingface.co/mistralai/Mistral-Large-3-675B-Instruct-2512/commit/7f13ed24ab52a2a1c35bb26a749ef9d891ee98dd
+    runtime: tfs
+    downloadAtRuntime: true
+    tag: 0.0.1
+    # Tag history:
+    # 0.0.1 - New Model!
   # Phi-2
   - name: phi-2
     type: text-generation



Test patch:
diff --git a/api/v1beta1/workspace_validation_test.go b/api/v1beta1/workspace_validation_test.go
index e5eaa09..39775f1 100644
--- a/api/v1beta1/workspace_validation_test.go
+++ b/api/v1beta1/workspace_validation_test.go
@@ -98,8 +98,9 @@ type testModelDownload struct{}
 func (*testModelDownload) GetInferenceParameters() *model.PresetParam {
 	return &model.PresetParam{
 		Metadata: model.Metadata{
-			Version:           "https://huggingface.co/test-repo/test-model/commit/test-revision",
-			DownloadAtRuntime: true,
+			Version:              "https://huggingface.co/test-repo/test-model/commit/test-revision",
+			DownloadAtRuntime:    true,
+			DownloadAuthRequired: true,
 		},
 		GPUCountRequirement:     "2",
 		TotalSafeTensorFileSize: "32Gi",
@@ -1169,7 +1170,7 @@ func TestInferenceSpecValidateCreate(t *testing.T) {
 					},
 				},
 			},
-			errContent: "This preset requires a modelAccessSecret with HF_TOKEN key under presetOptions to download the model",
+			errContent: "This preset requires authentication and needs a modelAccessSecret with HF_TOKEN key under presetOptions to download the model",
 			expectErrs: true,
 		},
 		{
diff --git a/test/e2e/preset_test.go b/test/e2e/preset_test.go
index f0890e6..09d807c 100644
--- a/test/e2e/preset_test.go
+++ b/test/e2e/preset_test.go
@@ -54,6 +54,7 @@ const (
 	PresetGemma3_27BInstructModel       = "gemma-3-27b-instruct"
 	PresetGPT_OSS_20BModel              = "gpt-oss-20b"
 	PresetGPT_OSS_120BModel             = "gpt-oss-120b"
+	PresetMinistral33BInstructModel     = "ministral-3-3b-instruct"
 	WorkspaceHashAnnotation             = "workspace.kaito.io/hash"
 	// WorkspaceRevisionAnnotation represents the revision number of the workload managed by the workspace
 	WorkspaceRevisionAnnotation = "workspace.kaito.io/revision"
diff --git a/test/e2e/preset_vllm_test.go b/test/e2e/preset_vllm_test.go
index 56ad555..adee51a 100644
--- a/test/e2e/preset_vllm_test.go
+++ b/test/e2e/preset_vllm_test.go
@@ -384,6 +384,28 @@ var _ = Describe("Workspace Preset on vllm runtime", func() {
 		validateModelsEndpoint(workspaceObj)
 		validateCompletionsEndpoint(workspaceObj)
 	})
+
+	It("should create a ministral-3-3b-instruct workspace with preset public mode successfully", func() {
+		numOfNode := 1
+		workspaceObj := createMinistral3_3BInstructWorkspaceWithPresetPublicModeAndVLLM(numOfNode)
+
+		defer cleanupResources(workspaceObj)
+		time.Sleep(30 * time.Second)
+
+		validateCreateNode(workspaceObj, numOfNode)
+		validateResourceStatus(workspaceObj)
+
+		time.Sleep(30 * time.Second)
+
+		validateAssociatedService(workspaceObj)
+		validateInferenceConfig(workspaceObj)
+
+		validateInferenceResource(workspaceObj, int32(numOfNode), false)
+
+		validateWorkspaceReadiness(workspaceObj)
+		validateModelsEndpoint(workspaceObj)
+		validateCompletionsEndpoint(workspaceObj)
+	})
 })
 
 func createDeepSeekLlama8BWorkspaceWithPresetPublicModeAndVLLM(numOfNode int) *kaitov1beta1.Workspace {
@@ -591,6 +613,20 @@ func createGPTOss120BWorkspaceWithPresetPublicModeAndVLLM(numOfNode int) *kaitov
 	return workspaceObj
 }
 
+func createMinistral3_3BInstructWorkspaceWithPresetPublicModeAndVLLM(numOfNode int) *kaitov1beta1.Workspace {
+	workspaceObj := &kaitov1beta1.Workspace{}
+	By("Creating a workspace CR with Ministral 3 3B Instruct preset public mode and vLLM", func() {
+		uniqueID := fmt.Sprint("preset-ministral-3-3b-", rand.Intn(1000))
+		workspaceObj = utils.GenerateInferenceWorkspaceManifestWithVLLM(uniqueID, namespaceName, "", numOfNode, "Standard_NV36ads_A10_v5",
+			&metav1.LabelSelector{
+				MatchLabels: map[string]string{"kaito-workspace": "public-preset-e2e-test-ministral-3-3b-instruct-vllm"},
+			}, nil, PresetMinistral33BInstructModel, nil, nil, nil, "")
+
+		createAndValidateWorkspace(workspaceObj)
+	})
+	return workspaceObj
+}
+
 func validateGatewayAPIInferenceExtensionResources(iObj *kaitov1alpha1.InferenceSet) {
 	// Only validate if the Inference Preset is set
 	if iObj.Spec.Template.Inference.Preset == nil {