Image-Text-to-Text
MLX
Safetensors
inkling_mm_model
inkling
Mixture of Experts
multimodal
text-generation
apple-silicon
conversational
Instructions to use mlx-community/Inkling-Small-mlx-2bit with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use mlx-community/Inkling-Small-mlx-2bit with MLX:
# Make sure mlx-vlm is installed # pip install --upgrade mlx-vlm from mlx_vlm import load, generate from mlx_vlm.prompt_utils import apply_chat_template from mlx_vlm.utils import load_config # Load the model model, processor = load("mlx-community/Inkling-Small-mlx-2bit") config = load_config("mlx-community/Inkling-Small-mlx-2bit") # Prepare input image = ["http://images.cocodataset.org/val2017/000000039769.jpg"] prompt = "Describe this image." # Apply chat template formatted_prompt = apply_chat_template( processor, config, prompt, num_images=1 ) # Generate output output = generate(model, processor, formatted_prompt, image) print(output) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Pi
How to use mlx-community/Inkling-Small-mlx-2bit with Pi:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "mlx-community/Inkling-Small-mlx-2bit"
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": "mlx-community/Inkling-Small-mlx-2bit" } ] } } }Run Pi
# Start Pi in your project directory: pi
- OpenClaw new
How to use mlx-community/Inkling-Small-mlx-2bit with OpenClaw:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "mlx-community/Inkling-Small-mlx-2bit"
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 "mlx-community/Inkling-Small-mlx-2bit" \ --custom-provider-id mlx-lm \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
- Hermes Agent
How to use mlx-community/Inkling-Small-mlx-2bit 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 "mlx-community/Inkling-Small-mlx-2bit"
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 mlx-community/Inkling-Small-mlx-2bit
Run Hermes
hermes
| """Configuration for the Inkling multimodal model (MLX port). | |
| Mirrors ``thinkingmachines/Inkling`` ``config.json`` and the transformers PR #47347 | |
| reference (``InklingConfig`` / ``InklingTextConfig`` / ``InklingVisionConfig`` / | |
| ``InklingAudioConfig``). We parse the *checkpoint* config layout (top-level | |
| ``text_config`` / ``vision_config`` / ``audio_config`` / ``mtp_config``), not the | |
| flattened transformers layout. | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import dataclass, field | |
| from typing import Any | |
| def _get(d: dict, *names, default=None): | |
| for n in names: | |
| if n in d and d[n] is not None: | |
| return d[n] | |
| return default | |
| class TextConfig: | |
| hidden_size: int = 6144 | |
| num_hidden_layers: int = 66 | |
| vocab_size: int = 201024 | |
| unpadded_vocab_size: int | None = 200058 | |
| # global (full) attention | |
| num_attention_heads: int = 64 | |
| num_key_value_heads: int = 8 | |
| head_dim: int = 128 | |
| # sliding-window attention | |
| swa_num_attention_heads: int = 64 | |
| swa_num_key_value_heads: int = 16 | |
| swa_head_dim: int = 128 | |
| sliding_window_size: int = 512 | |
| # relative-position logits | |
| d_rel: int = 16 | |
| rel_extent: int = 1024 | |
| log_scaling_n_floor: int | None = 128000 | |
| log_scaling_alpha: float = 0.1 | |
| rms_norm_eps: float = 1e-6 | |
| use_embed_norm: bool = True | |
| # short convolution | |
| sconv_kernel_size: int = 4 | |
| # dense vs MoE MLP | |
| dense_mlp_idx: int = 2 | |
| dense_intermediate_size: int = 24576 # dense MLP intermediate | |
| moe_intermediate_size: int = 3072 # per-expert intermediate | |
| # MoE routing | |
| n_routed_experts: int = 256 | |
| num_experts_per_tok: int = 6 | |
| n_shared_experts: int = 2 | |
| shared_expert_sink: bool = True | |
| route_scale: float = 8.0 | |
| use_gate_bias: bool = True | |
| norm_after_topk: bool = True | |
| use_global_scale: bool = True | |
| logits_mup_width_multiplier: float = 24.0 | |
| hidden_act: str = "silu" | |
| max_position_embeddings: int = 1048576 | |
| # which layer indices use sliding-window ("local") attention | |
| local_layer_ids: list[int] = field(default_factory=list) | |
| # MTP head (dropped for inference) | |
| num_mtp_layers: int | None = None | |
| def layer_types(self) -> list[str]: | |
| local = set(self.local_layer_ids) | |
| return [ | |
| "hybrid_sliding" if i in local else "hybrid" | |
| for i in range(self.num_hidden_layers) | |
| ] | |
| def mlp_layer_types(self) -> list[str]: | |
| return [ | |
| "dense" if i < self.dense_mlp_idx else "sparse" | |
| for i in range(self.num_hidden_layers) | |
| ] | |
| def from_dict(cls, tc: dict) -> "TextConfig": | |
| return cls( | |
| hidden_size=_get(tc, "hidden_size", default=6144), | |
| num_hidden_layers=_get(tc, "num_hidden_layers", default=66), | |
| vocab_size=_get(tc, "vocab_size", default=201024), | |
| unpadded_vocab_size=_get(tc, "unpadded_vocab_size"), | |
| num_attention_heads=_get(tc, "num_attention_heads", default=64), | |
| num_key_value_heads=_get(tc, "num_key_value_heads", default=8), | |
| head_dim=_get(tc, "head_dim", default=128), | |
| swa_num_attention_heads=_get(tc, "swa_num_attention_heads", default=64), | |
| swa_num_key_value_heads=_get(tc, "swa_num_key_value_heads", default=16), | |
| swa_head_dim=_get(tc, "swa_head_dim", default=128), | |
| sliding_window_size=_get(tc, "sliding_window_size", default=512), | |
| d_rel=_get(tc, "d_rel", default=16), | |
| rel_extent=_get(tc, "rel_extent", default=1024), | |
| log_scaling_n_floor=_get(tc, "log_scaling_n_floor"), | |
| log_scaling_alpha=_get(tc, "log_scaling_alpha", default=0.1), | |
| rms_norm_eps=_get(tc, "rms_norm_eps", default=1e-6), | |
| use_embed_norm=_get(tc, "use_embed_norm", default=True), | |
| sconv_kernel_size=_get(tc, "sconv_kernel_size", default=4), | |
| dense_mlp_idx=_get(tc, "dense_mlp_idx", default=2), | |
| dense_intermediate_size=_get(tc, "dense_intermediate_size", default=24576), | |
| # checkpoint labels the *MoE* intermediate as `intermediate_size` | |
| moe_intermediate_size=_get(tc, "intermediate_size", default=3072), | |
| n_routed_experts=_get(tc, "n_routed_experts", default=256), | |
| num_experts_per_tok=_get(tc, "num_experts_per_tok", default=6), | |
| n_shared_experts=_get(tc, "n_shared_experts", default=2), | |
| shared_expert_sink=_get(tc, "shared_expert_sink", default=True), | |
| route_scale=_get(tc, "route_scale", default=8.0), | |
| use_gate_bias=_get(tc, "use_gate_bias", default=True), | |
| norm_after_topk=_get(tc, "norm_after_topk", default=True), | |
| use_global_scale=_get(tc, "use_global_scale", default=True), | |
| logits_mup_width_multiplier=_get(tc, "logits_mup_width_multiplier", default=24.0), | |
| max_position_embeddings=_get(tc, "model_max_length", "max_position_embeddings", default=1048576), | |
| local_layer_ids=list(_get(tc, "local_layer_ids", default=[]) or []), | |
| ) | |
| class VisionConfig: | |
| text_hidden_size: int = 6144 | |
| patch_size: int = 40 | |
| temporal_patch_size: int = 2 | |
| num_channels: int = 3 | |
| n_layers: int = 4 | |
| rms_norm_eps: float = 1e-6 | |
| use_vision_norm: bool = True | |
| def from_dict(cls, vc: dict, text_hidden: int) -> "VisionConfig": | |
| return cls( | |
| text_hidden_size=text_hidden, | |
| patch_size=_get(vc, "patch_size", default=40), | |
| temporal_patch_size=_get(vc, "temporal_patch_size", default=2), | |
| num_channels=_get(vc, "n_channels", "num_channels", default=3), | |
| n_layers=_get(vc, "n_layers", "num_hidden_layers", default=4), | |
| rms_norm_eps=_get(vc, "rms_norm_eps", default=1e-6), | |
| use_vision_norm=_get(vc, "use_vision_norm", default=True), | |
| ) | |
| class AudioConfig: | |
| text_hidden_size: int = 6144 | |
| n_mel_bins: int = 80 | |
| mel_vocab_size: int = 16 | |
| rms_norm_eps: float = 1e-6 | |
| def from_dict(cls, ac: dict, text_hidden: int) -> "AudioConfig": | |
| return cls( | |
| text_hidden_size=text_hidden, | |
| n_mel_bins=_get(ac, "n_mel_bins", default=80), | |
| mel_vocab_size=_get(ac, "mel_vocab_size", default=16), | |
| rms_norm_eps=_get(ac, "rms_norm_eps", default=1e-6), | |
| ) | |
| class InklingConfig: | |
| text: TextConfig | |
| vision: VisionConfig | |
| audio: AudioConfig | |
| image_token_id: int = 200054 | |
| audio_token_id: int = 200053 | |
| image_bos_token_id: int = 200005 | |
| audio_bos_token_id: int = 200020 | |
| eos_token_id: int = 200006 | |
| model_type: str = "inkling_mm_model" | |
| def from_dict(cls, cfg: dict) -> "InklingConfig": | |
| tc = dict(cfg.get("text_config", {})) | |
| mtp = cfg.get("mtp_config") or {} | |
| if mtp.get("num_nextn_predict_layers") is not None: | |
| tc.setdefault("num_mtp_layers", mtp.get("num_nextn_predict_layers")) | |
| text = TextConfig.from_dict(tc) | |
| vision = VisionConfig.from_dict(cfg.get("vision_config", {}) or {}, text.hidden_size) | |
| audio = AudioConfig.from_dict(cfg.get("audio_config", {}) or {}, text.hidden_size) | |
| return cls( | |
| text=text, | |
| vision=vision, | |
| audio=audio, | |
| image_token_id=_get(cfg, "image_token_id", default=200054), | |
| audio_token_id=_get(cfg, "audio_token_id", default=200053), | |
| image_bos_token_id=_get(cfg, "image_bos_token_id", default=200005), | |
| audio_bos_token_id=_get(cfg, "audio_bos_token_id", default=200020), | |
| eos_token_id=_get(cfg, "eos_token_id", default=200006), | |
| model_type=_get(cfg, "model_type", default="inkling_mm_model"), | |
| ) | |
| def raw(self) -> dict[str, Any]: | |
| return {"model_type": self.model_type} | |