Text Generation
MLX
Safetensors
English
minimax_m3_vl
turboquant
turboquant-plus
config-i
Mixture of Experts
apple-silicon
untested
conversational
custom_code
4-bit precision
Instructions to use thetom-ai/MiniMax-M3-ConfigI-MLX with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use thetom-ai/MiniMax-M3-ConfigI-MLX with MLX:
# Make sure mlx-lm is installed # pip install --upgrade mlx-lm # Generate text with mlx-lm from mlx_lm import load, generate model, tokenizer = load("thetom-ai/MiniMax-M3-ConfigI-MLX") prompt = "Write a story about Einstein" messages = [{"role": "user", "content": prompt}] prompt = tokenizer.apply_chat_template( messages, add_generation_prompt=True ) text = generate(model, tokenizer, prompt=prompt, verbose=True) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Pi
How to use thetom-ai/MiniMax-M3-ConfigI-MLX with Pi:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "thetom-ai/MiniMax-M3-ConfigI-MLX"
Configure the model in Pi
# Install Pi: npm install -g @mariozechner/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "mlx-lm": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "thetom-ai/MiniMax-M3-ConfigI-MLX" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Hermes Agent new
How to use thetom-ai/MiniMax-M3-ConfigI-MLX with Hermes Agent:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "thetom-ai/MiniMax-M3-ConfigI-MLX"
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 thetom-ai/MiniMax-M3-ConfigI-MLX
Run Hermes
hermes
- MLX LM
How to use thetom-ai/MiniMax-M3-ConfigI-MLX with MLX LM:
Generate or start a chat session
# Install MLX LM uv tool install mlx-lm # Interactive chat REPL mlx_lm.chat --model "thetom-ai/MiniMax-M3-ConfigI-MLX"
Run an OpenAI-compatible server
# Install MLX LM uv tool install mlx-lm # Start the server mlx_lm.server --model "thetom-ai/MiniMax-M3-ConfigI-MLX" # Calling the OpenAI-compatible server with curl curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "thetom-ai/MiniMax-M3-ConfigI-MLX", "messages": [ {"role": "user", "content": "Hello"} ] }'
File size: 7,318 Bytes
f37712f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | # Copyright 2023-2024 SGLang Team
# Licensed under the Apache License, Version 2.0 (the "License");
"""
MiniMax VL family HuggingFace-compatible VideoProcessor.
"""
import math
from typing import List, Optional, Tuple, Union
import torch
import torchvision
from torchvision.transforms import InterpolationMode
from transformers import BatchFeature
from transformers.image_utils import PILImageResampling, SizeDict
from transformers.processing_utils import (
Unpack,
VideosKwargs,
)
from transformers.utils import TensorType
from transformers.video_processing_utils import BaseVideoProcessor
from transformers.video_utils import group_videos_by_shape, reorder_videos
MAX_RATIO = 200
def round_by_factor(number: int, factor: int) -> int:
return round(number / factor) * factor
def ceil_by_factor(number: int, factor: int) -> int:
return math.ceil(number / factor) * factor
def floor_by_factor(number: int, factor: int) -> int:
return math.floor(number / factor) * factor
def smart_resize(
height: int,
width: int,
factor: int = 28,
min_pixels: int = 4 * 28 * 28,
max_pixels: int = 451584,
) -> tuple[int, int]:
if max(height, width) / min(height, width) > MAX_RATIO:
raise ValueError(
f"absolute aspect ratio must be smaller than {MAX_RATIO}, "
f"got {max(height, width) / min(height, width)}"
)
h_bar = max(factor, round_by_factor(height, factor))
w_bar = max(factor, round_by_factor(width, factor))
if h_bar * w_bar > max_pixels:
beta = math.sqrt((height * width) / max_pixels)
h_bar = floor_by_factor(height / beta, factor)
w_bar = floor_by_factor(width / beta, factor)
elif h_bar * w_bar < min_pixels:
beta = math.sqrt(min_pixels / (height * width))
h_bar = ceil_by_factor(height * beta, factor)
w_bar = ceil_by_factor(width * beta, factor)
return h_bar, w_bar
class MiniMaxM3VLVideoProcessorKwargs(VideosKwargs, total=False):
patch_size: int
temporal_patch_size: int
merge_size: int
min_pixels: int
max_pixels: int
total_pixels: int
min_frames: int
max_frames: int
fps: float | int
class MiniMaxM3VLVideoProcessor(BaseVideoProcessor):
do_resize = True
resample = PILImageResampling.BICUBIC
size = {"height": 672, "width": 672}
default_to_square = False
do_rescale = True
rescale_factor = 1 / 255
do_normalize = True
image_mean = [0.48145466, 0.4578275, 0.40821073]
image_std = [0.26862954, 0.26130258, 0.27577711]
do_convert_rgb = True
do_sample_frames = False
patch_size = 14
temporal_patch_size = 2
merge_size = 2
min_pixels = 4 * 28 * 28
max_pixels = 768 * 28 * 28 # 602,112
total_pixels = int(64000 * 28 * 28 * 0.9) # ~45M, ~64k tokens budget
fps = 1.0
min_frames = 4
max_frames = 768
valid_kwargs = MiniMaxM3VLVideoProcessorKwargs
model_input_names = ["pixel_values_videos", "video_grid_thw"]
def __init__(self, **kwargs: Unpack[MiniMaxM3VLVideoProcessorKwargs]):
super().__init__(**kwargs)
def _preprocess(
self,
videos: List[torch.Tensor],
do_convert_rgb: bool,
do_resize: bool,
size: SizeDict,
resample: PILImageResampling | InterpolationMode | int | None,
do_rescale: bool,
rescale_factor: float,
do_normalize: bool,
image_mean: float | List[float] | None,
image_std: float | List[float] | None,
patch_size: int,
temporal_patch_size: int,
merge_size: int,
min_pixels: int,
max_pixels: int,
return_tensors: str | TensorType | None = None,
**kwargs,
) -> BatchFeature:
grouped_videos, grouped_videos_index = group_videos_by_shape(videos)
resized_videos_grouped = {}
factor = patch_size * merge_size
for shape, stacked_videos in grouped_videos.items():
batch_size, num_frames, channels, height, width = stacked_videos.shape
resized_height, resized_width = height, width
if do_resize:
resized_height, resized_width = smart_resize(
height, width, factor=factor,
min_pixels=min_pixels, max_pixels=max_pixels,
)
stacked_videos = stacked_videos.view(
batch_size * num_frames, channels, height, width
)
stacked_videos = self.resize(
stacked_videos,
size=SizeDict(height=resized_height, width=resized_width),
resample=resample,
)
stacked_videos = stacked_videos.view(
batch_size,
num_frames,
channels,
resized_height,
resized_width,
)
resized_videos_grouped[shape] = stacked_videos
resized_videos = reorder_videos(resized_videos_grouped, grouped_videos_index)
grouped_videos, grouped_videos_index = group_videos_by_shape(resized_videos)
processed_videos_grouped = {}
processed_grids = {}
for shape, stacked_videos in grouped_videos.items():
resized_height, resized_width = stacked_videos.shape[-2:]
patches = self.rescale_and_normalize(
stacked_videos,
do_rescale,
rescale_factor,
do_normalize,
image_mean,
image_std,
)
if pad := -patches.shape[1] % temporal_patch_size:
repeats = patches[:, -1:].expand(-1, pad, -1, -1, -1)
patches = torch.cat([patches, repeats], dim=1)
batch_size, grid_t, channels = patches.shape[:3]
grid_t = grid_t // temporal_patch_size
grid_h, grid_w = resized_height // patch_size, resized_width // patch_size
patches = patches.view(
batch_size,
grid_t,
temporal_patch_size,
channels,
grid_h // merge_size,
merge_size,
patch_size,
grid_w // merge_size,
merge_size,
patch_size,
)
patches = patches.permute(0, 1, 4, 7, 5, 8, 3, 2, 6, 9)
flatten_patches = patches.reshape(
batch_size,
grid_t * grid_h * grid_w,
channels * temporal_patch_size * patch_size * patch_size,
)
processed_videos_grouped[shape] = flatten_patches
processed_grids[shape] = [[grid_t, grid_h, grid_w]] * batch_size
processed_videos = reorder_videos(
processed_videos_grouped, grouped_videos_index
)
processed_grids = reorder_videos(processed_grids, grouped_videos_index)
pixel_values_videos = torch.cat(processed_videos, dim=0)
video_grid_thw = torch.tensor(processed_grids, dtype=torch.long)
return BatchFeature(
data={
"pixel_values_videos": pixel_values_videos,
"video_grid_thw": video_grid_thw,
},
tensor_type=return_tensors,
)
|