Text Classification
PEFT
lora
document-question-answering
structured-decisions
calibration
synthetic-evaluation
Instructions to use botp/Solomon with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use botp/Solomon with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
| """BF16 Metal execution with instance-owned adaptation and isolated question caches.""" | |
| import copy | |
| import json | |
| import threading | |
| import time | |
| from pathlib import Path | |
| import mlx.core as mx | |
| import numpy as np | |
| from mlx import nn | |
| from PIL import Image | |
| from ._vendor.prompts import PAGE, SYSTEM | |
| from .artifacts import ADAPTER_SHA, BASE_REVISION, HEADS_SHA, SOLOMON_REVISION, runtime_identity, sha256 | |
| class SwitchLoRA(nn.Module): | |
| def __init__(self, linear, a, b, context): | |
| super().__init__() | |
| self.linear, self.lora_a, self.lora_b = linear, a, b | |
| self._context = context | |
| def __call__(self, x): | |
| y = self.linear(x) | |
| start = self._context["start"] | |
| if start is None or start >= x.shape[1]: | |
| return y | |
| delta = (2.0 * ((x[:, start:].astype(mx.float32) @ self.lora_a) @ self.lora_b)).astype(y.dtype) | |
| return y + delta if start == 0 else mx.concatenate([y[:, :start], y[:, start:] + delta], axis=1) | |
| def fork_cache(caches): | |
| """New cache containers and array handles; MLX owns copy-on-write storage. | |
| mx.array creates a distinct handle, so slice updates cannot change a prefix's | |
| Python array. Recurrent/window updates replace the branch's private slots. | |
| """ | |
| from mlx_vlm.models.cache import ArraysCache, KVCache | |
| result = [] | |
| for original in caches: | |
| if isinstance(original, ArraysCache): | |
| branch = ArraysCache(len(original.cache)) | |
| branch.cache = [None if x is None else mx.array(x) for x in original.cache] | |
| elif isinstance(original, KVCache): | |
| branch = KVCache() | |
| branch.state = tuple(None if x is None else mx.array(x) for x in original.state) | |
| else: | |
| raise TypeError(f"Unsupported prefix cache: {type(original).__name__}") | |
| result.append(branch) | |
| return result | |
| class Engine: | |
| def __init__(self, directory, *, chunk_size=2048, max_tokens=40960): | |
| from mlx_vlm.models.qwen3_vl.processing_qwen3_vl import Qwen3VLProcessor | |
| from mlx_vlm.utils import load_model | |
| self.directory = Path(directory).resolve() | |
| self.binding = json.loads((self.directory / "binding.json").read_text()) | |
| if ( | |
| self.binding.get("schema") != "solomon-mlx-binding-v1" | |
| or self.binding.get("base_revision") != BASE_REVISION | |
| or self.binding.get("solomon_revision") != SOLOMON_REVISION | |
| ): | |
| raise ValueError("Unrecognized or unpinned Solomon MLX binding") | |
| if self.binding["profile"] != "quality" or self.binding["dtype"] != "bfloat16": | |
| raise ValueError("This runtime currently accepts only the BF16 quality profile") | |
| for name, expected in self.binding["files"].items(): | |
| path = (self.directory / name).resolve() | |
| if not path.is_relative_to(self.directory) or sha256(path) != expected: | |
| raise ValueError(f"Model artifact checksum mismatch: {name}") | |
| adapter, heads = self.directory / "adapter.safetensors", self.directory / "heads.npz" | |
| if sha256(adapter) != ADAPTER_SHA or sha256(heads) != HEADS_SHA: | |
| raise ValueError("Solomon checkpoint identity mismatch") | |
| if not 1 <= chunk_size <= 2048 or not 1 <= max_tokens <= 40960: | |
| raise ValueError("Invalid chunk size or context ceiling") | |
| weight_bytes = sum( | |
| (self.directory / name).stat().st_size | |
| for name in self.binding["files"] | |
| if name.endswith((".safetensors", ".npz")) | |
| ) | |
| if weight_bytes + 4 * 2**30 > mx.device_info()["max_recommended_working_set_size"]: | |
| raise MemoryError( | |
| "Full BF16 weights and minimum workspace exceed this Mac’s recommended Metal working set" | |
| ) | |
| self.chunk_size, self.max_tokens = chunk_size, max_tokens | |
| self.lock = threading.RLock() | |
| self.context = {"start": None} | |
| self.model = load_model(self.directory / "backbone", lazy=True, strict=True) | |
| self.processor = Qwen3VLProcessor.from_pretrained( | |
| str(self.directory / "backbone"), trust_remote_code=False | |
| ) | |
| self.lm, self.t = self.model.language_model, self.processor.tokenizer | |
| self.pad = self.t.convert_tokens_to_ids("<|image_pad|>") | |
| weights = mx.load(str(adapter)) | |
| for name in sorted({key.rsplit(".", 1)[0] for key in weights}): | |
| parts = name.split(".") | |
| if parts[:2] != ["model", "layers"]: | |
| raise ValueError(f"Unexpected adapter target: {name}") | |
| owner = self.lm.model.layers[int(parts[2])] | |
| for part in parts[3:-1]: | |
| owner = getattr(owner, part) | |
| linear = getattr(owner, parts[-1]) | |
| a, b = weights[name + ".lora_a"].astype(mx.float32), weights[name + ".lora_b"].astype(mx.float32) | |
| if a.shape != (linear.weight.shape[1], 64) or b.shape != (64, linear.weight.shape[0]): | |
| raise ValueError(f"Adapter orientation/shape mismatch: {name}") | |
| setattr(owner, parts[-1], SwitchLoRA(linear, a, b, self.context)) | |
| with np.load(heads, allow_pickle=False) as archive: | |
| keys = {k[:-7] for k in archive.files if k.endswith("/weight")} | |
| required_heads = { | |
| "boolean/state4", | |
| "entity/state4", | |
| "multilabel/state4", | |
| "ordered/threshold4", | |
| "single/choiceR", | |
| "single/choiceS", | |
| "single/sufficiency3", | |
| "ordered/choiceR", | |
| "ordered/choiceS", | |
| "ordered/sufficiency3", | |
| } | |
| if keys != required_heads: | |
| raise ValueError("All ten semantic heads are required") | |
| self.heads = {} | |
| for key in keys: | |
| w, b = archive[key + "/weight"], archive[key + "/bias"] | |
| if ( | |
| w.shape != (10, 5120) | |
| or b.shape != (10,) | |
| or not np.isfinite(w).all() | |
| or not np.isfinite(b).all() | |
| ): | |
| raise ValueError("Invalid semantic head") | |
| self.heads[key] = (mx.array(w, mx.float32), mx.array(b, mx.float32)) | |
| self.model.freeze() | |
| self.model.eval() | |
| mx.eval(self.model.parameters(), self.heads) | |
| self.identity = runtime_identity(self.binding, chunk_size=self.chunk_size, max_tokens=self.max_tokens) | |
| def render(self, parts, block): | |
| content = "" | |
| for i, p in enumerate(parts): | |
| if "text" in p: | |
| content += ("\n" if i and "image" in parts[i - 1] else "") + p["text"] | |
| else: | |
| content += ("\n" if i and "text" in parts[i - 1] else "") + PAGE | |
| return self.t.apply_chat_template( | |
| [ | |
| {"role": "system", "content": SYSTEM}, | |
| {"role": "user", "content": "Document:\n" + content + "\n\n" + block}, | |
| ], | |
| tokenize=False, | |
| add_generation_prompt=True, | |
| enable_thinking=False, | |
| ) | |
| def expand(self, ids, counts): | |
| out, index = [], 0 | |
| for token in ids: | |
| if token == self.pad: | |
| if index >= len(counts): | |
| raise ValueError("Unexpected image placeholder in document text") | |
| out.extend([token] * counts[index]) | |
| index += 1 | |
| else: | |
| out.append(token) | |
| if index != len(counts): | |
| raise ValueError("Image placeholder count mismatch") | |
| return out | |
| def positions(self, start, count): | |
| return mx.broadcast_to(mx.arange(start, start + count)[None, None, :], (3, 1, count)) | |
| def admit(self, count): | |
| if count < 1 or count > self.max_tokens: | |
| raise ValueError(f"{count} tokens exceeds the {self.max_tokens}-token scope ceiling") | |
| # Conservative allowance: BF16 attention KV + FP32 recurrent states and | |
| # chunk intermediates. This supplements the token ceiling, not a promise | |
| # of availability in the presence of other processes. | |
| temporary = 4 * 2**30 + count * 16 * 2 * 4 * 256 * 2 | |
| limit = mx.device_info()["max_recommended_working_set_size"] | |
| if mx.get_active_memory() + temporary > limit: | |
| raise MemoryError("Insufficient recommended Metal working set for this request") | |
| def forward(self, ids, positions, cache, *, embeds=None, adapter_from=None, taps=()): | |
| hidden, captured = None, {} | |
| try: | |
| for start in range(0, len(ids), self.chunk_size): | |
| end = min(start + self.chunk_size, len(ids)) | |
| self.context["start"] = None if adapter_from is None else max(0, adapter_from - start) | |
| last = end == len(ids) | |
| out = self.lm( | |
| mx.array([ids[start:end]]), | |
| cache=cache, | |
| position_ids=positions[:, :, start:end], | |
| inputs_embeds=None if embeds is None else embeds[:, start:end], | |
| skip_logits=True, | |
| return_hidden=last, | |
| capture_layer_ids=list(taps) if last else None, | |
| ) | |
| if last: | |
| hidden = out.hidden_states[-1][0, -1].astype(mx.float32) | |
| captured = { | |
| str(i): self.lm.model.norm(h[:, -1:])[0, -1].astype(mx.float32) | |
| for i, h in zip(sorted(set(taps)), out.hidden_states[:-1]) | |
| } | |
| mx.eval(hidden, captured) | |
| mx.eval([c.state for c in cache]) | |
| return hidden, captured | |
| finally: | |
| self.context["start"] = None | |
| def prefill(self, parts): | |
| with self.lock: | |
| prefill_started = time.perf_counter() | |
| text = self.render(parts, "X") | |
| boundary = text.rfind("\n\nX") | |
| if boundary < 0: | |
| raise ValueError("Missing document boundary") | |
| raw = self.t.encode(text[:boundary], add_special_tokens=False) | |
| if "text" in parts[-1]: | |
| raw = raw[:-1] | |
| vision_started = time.perf_counter() | |
| counts, grids, features = [], [], [] | |
| for part in parts: | |
| if "image" not in part: | |
| continue | |
| with Image.open(part["image"]) as image: | |
| processed = self.processor.image_processor(images=[image.convert("RGB")]) | |
| grid_np = np.asarray(processed["image_grid_thw"]) | |
| count = int(grid_np.prod()) // self.model.config.vision_config.spatial_merge_size**2 | |
| self.admit(len(raw) + sum(counts) + count - len(counts) - 1) | |
| grid = mx.array(grid_np) | |
| pixels = mx.array(np.asarray(processed["pixel_values"])).astype( | |
| self.model.vision_tower.patch_embed.proj.weight.dtype | |
| ) | |
| feature, _ = self.model.vision_tower(pixels, grid) | |
| mx.eval(feature) | |
| counts.append(count) | |
| grids.append(grid) | |
| features.append(feature) | |
| vision_seconds = time.perf_counter() - vision_started if counts else 0.0 | |
| ids = self.expand(raw, counts) | |
| self.admit(len(ids)) | |
| embeds, delta, feats, grid = None, 0, None, None | |
| if counts: | |
| feats, grid = mx.concatenate(features), mx.concatenate(grids) | |
| f = self.model.get_input_embeddings( | |
| mx.array([ids]), mx.zeros((1,)), image_grid_thw=grid, cached_image_features=feats | |
| ) | |
| embeds, positions = f.inputs_embeds, f.position_ids | |
| delta = int(np.asarray(f.rope_deltas).reshape(-1)[0]) | |
| if delta != int(mx.max(positions).item()) + 1 - len(ids): | |
| raise ValueError("Multimodal RoPE offset mismatch") | |
| else: | |
| positions = self.positions(0, len(ids)) | |
| cache = self.lm.make_cache() | |
| started = time.perf_counter() | |
| self.forward(ids, positions, cache, embeds=embeds) | |
| return { | |
| "parts": copy.deepcopy(parts), | |
| "prefix_ids": ids, | |
| "cache": cache, | |
| "counts": counts, | |
| "rope_delta": delta, | |
| "features": feats, | |
| "grid": grid, | |
| "positions": positions, | |
| "prefill_seconds": time.perf_counter() - prefill_started, | |
| "language_prefill_seconds": time.perf_counter() - started, | |
| "vision_seconds": vision_seconds, | |
| } | |
| def ask(self, state, block, width, head, *, execution="cached", taps=()): | |
| with self.lock: | |
| if head not in self.heads or not 2 <= width <= 10: | |
| raise ValueError("Unknown semantic head or invalid width") | |
| ids = self.expand( | |
| self.t.encode(self.render(state["parts"], block), add_special_tokens=False), state["counts"] | |
| ) | |
| self.admit(len(ids)) | |
| p = len(state["prefix_ids"]) | |
| if ids[:p] != state["prefix_ids"]: | |
| raise ValueError("Question token prefix differs from cached document") | |
| started = time.perf_counter() | |
| if execution == "cached": | |
| hidden, captured = self.forward( | |
| ids[p:], | |
| self.positions(p + state["rope_delta"], len(ids) - p), | |
| fork_cache(state["cache"]), | |
| adapter_from=0, | |
| taps=taps, | |
| ) | |
| elif execution == "full": | |
| embeds = None | |
| if state["counts"]: | |
| f = self.model.get_input_embeddings( | |
| mx.array([ids]), | |
| mx.zeros((1,)), | |
| image_grid_thw=state["grid"], | |
| cached_image_features=state["features"], | |
| ) | |
| embeds, positions = f.inputs_embeds, f.position_ids | |
| else: | |
| positions = self.positions(0, len(ids)) | |
| hidden, captured = self.forward( | |
| ids, positions, self.lm.make_cache(), embeds=embeds, adapter_from=p, taps=taps | |
| ) | |
| else: | |
| raise ValueError("Execution must be cached or full") | |
| w, b = self.heads[head] | |
| logits = (w @ hidden + b)[:width] | |
| mx.eval(logits) | |
| values = np.asarray(logits) | |
| if not np.isfinite(values).all(): | |
| raise ValueError("Nonfinite trained-head output") | |
| result = { | |
| "letter_logits": values.tolist(), | |
| "head_key": head, | |
| "prompt_tokens": len(ids), | |
| "branch_tokens": len(ids) - p, | |
| "reused_prefix_tokens": p if execution == "cached" else 0, | |
| "seconds": time.perf_counter() - started, | |
| } | |
| if taps: | |
| result.update( | |
| hidden=np.asarray(hidden).tolist(), | |
| taps={k: np.asarray(v).tolist() for k, v in captured.items()}, | |
| token_ids=ids, | |
| ) | |
| return result | |