LM Studioにおける統一マルチモーダル MLX エンジンアーキテクチャの紹介

LM StudioのMLXエンジン(MIT)は、Apple Silicon Mチップ上でLLMを効率的に実行するために、2つの強力なPythonパッケージを活用しています。テキスト生成にはmlx-lm(@awni、@angeloskath、Appleによる)を、画像対応言語モデルにはmlx-vlm(@Blaizzyによる)を使用しています。
mlx-engineコミット f98317e(アプリ内エンジン v0.17.0以降)から、各パッケージの基盤となるコンポーネントを織り交ぜた新しい統一アーキテクチャに移行しました。これにより、mlx-lmのテキストモデル実装が常に使用され、mlx-vlmのビジョンモデル実装は、テキストモデルが理解できる画像埋め込みを生成するための「アドオン」としてモジュール式に使用されるようになりました。

新しいmlx-engineの統一ビジョンモデルアーキテクチャ。mlx-lmテキストモデルはmlx-vlmビジョンアドオンで拡張されます。
これにより、マルチモーダルMLX VLM(例:GoogleのGemma 3)の使用時のパフォーマンスとユーザーエクスペリエンスが大幅に向上しました。例えば、VLMとのテキストのみのチャットで、以前はテキストのみのLLM専用だったプロンプトキャッシュ機能が利用できるようになり、フォローアップ応答が劇的に高速化しました。これにより、MLX VLMは、テキストタスクにおいてテキストのみのLLMとシームレスに互換性があり、さらにビジョン機能もボーナスとして提供されます。
👓 問題、解決策、そしてLM StudioのMLXエンジンでこの統一アーキテクチャをどのように実現したかについての技術的な詳細はこちらをご覧ください。
マルチモーダルLLMとは、複数の*モダリティ*の入力を受け取ることができるLLMのことです。これは、テキスト入力だけでなく、画像や音声の入力も受け入れることができることを意味します。
新しいMLXエンジンはまだ音声には対応していませんが、このアプローチは音声入力にも対応できるように計画しています。
一般的に、画像対応LLMは以下のフローで画像入力を取り込みます。

マルチモーダルビジョンLLMの一般的な動作フロー:画像をテキストモデルが理解できる埋め込みに変換し、テキストモデルで出力を生成します。
「これは何ですか?」 → [0.83, 0.40, 0.67, ...]image.png → [0.28, 0.11, 0.96, ...][0.83, 0.40, 0.67, ...] + [0.28, 0.11, 0.96, ...] → [0.83, 0.40, 0.67, ..., 0.28, 0.11, 0.96, ...]プロンプトに画像が含まれていない場合、「マージされた埋め込み」は単純にテキスト埋め込みとなります。
MLX Pythonの環境では、Apple Silicon上のLLMとの対話のためのモデル実装とインフラストラクチャを提供する2つの主要なライブラリがあります。
歴史的に、mlx-lmにはマルチモーダル機能を持たないテキスト専用モデルの実装が含まれており、一方mlx-vlmはMLX VLM実装の事実上のホームとなっています。

mlx-lmおよびmlx-vlmにおけるモデル実装コンポーネント。黄色 = テキストモデルコンポーネント。青色 = ビジョンモデルコンポーネント
LM Studioのmlx-engineは、当初、テキスト専用モデルと画像対応モデルの両方をサポートするために、シンプルな「フォーク」アーキテクチャで開発されました。

旧mlx-engineのフォークビジョンモデルアーキテクチャ。黄色 = テキストモデルコンポーネント。青色 = ビジョンモデルコンポーネント
モデルが画像対応の場合、mlx-vlmモデル実装(テキスト+ビジョン)が*独占的に*使用されました。モデルがテキスト専用の場合、mlx-lmモデル実装(テキスト)が*独占的に*使用されました。
各パスでは、(mlx-lmまたはmlx-vlmからの)異なるテキストモデル実装が使用されました。
mlx-engineの単純なフォークアーキテクチャは、以下の問題に悩まされていました。
mlx-lmとmlx-vlmの機能が完全に同等でない場合や、微妙な動作の違いがある場合、どちらを使用すべきでしょうか?mlx-lmとmlx-vlmのどちらを使用するかをどのように一貫して選択できるでしょうか?リクエストに応じてロードを切り替えるべきでしょうか(複雑)?
同じテキストモデルの2つの別々のバージョンが存在します。
すべてのMLX LLMおよびVLM向けの「統一」(フォークなし)推論エンジンを作成するために、mlx-lmとmlx-vlmのコアコンポーネントを組み合わせることを目指しました。
@awniおよび@Blaizzyとの貴重な議論を経て、以下の貢献を通じてこれを実現しました。
mlx-lmmlx-vlm
新しいmlx-engineの統一ビジョンモデルアーキテクチャ。mlx-lmテキストモデルはmlx-vlmビジョンアドオンで拡張されます。
この統一アーキテクチャでは、マルチモーダルLLMのコアテキストモデルは常にmlx-lm(2)からロードされ、わずかに異なるテキストモデルがmlx-vlmからロードされることはなくなりました。
次に、mlx-lmテキストモデルが理解できる画像埋め込みを生成するために、mlx-vlmの機能を使用するVisionAddOnを条件付きでロードします(mlx-engineのGemma3VisionAddOn実装を参照)。
このセットアップにより、マルチモーダルモデルを効率的で単一パスのファッションで推論できるようになりました。これにより、よりクリーンで保守性の高いLM Studio MLXエンジンを、パフォーマンスを向上させてリリースできます。
Gemma 3 12B QAT、M3 MacBook Pro上のMLX 4ビット。統一アーキテクチャにより、フォローアップTTFTが約25倍高速化。
mlx-engineのVisionAddOnsLM Studioの新しいmlx-engine統一アーキテクチャの要点は、すべてのマルチモーダルモデルに対してmlx-lmからのテキストモデル実装を使用できることであり、同時にmlx-vlmからのビジョンモデルコンポーネントを活用して、テキストモデルが理解できる画像埋め込みを生成できることです。
これは、マルチモーダルモデルの画像埋め込みを生成するために使用できるモジュール式コンポーネントであるVisionAddOns(ソース)を導入することで達成されます。これらのVisionAddOnsは、例えばBaseVisionAddOn抽象クラスによって定義された共通インターフェースを実装しています。
class BaseVisionAddOn: """ Base class that defines the interface for a VisionAddOn. """ @abstractmethod def __init__(self): """ Where load of vision model components is intended to occur. """ @abstractmethod def compute_embeddings( self, text_model: nn.Module, prompt_tokens: mx.array, images_b64: List[str], ) → mx.array: """ Returns input embeddings for the language model after text/image merging of the prompt """
VisionAddOnsは、mlx-lmのstream_generate()関数の新しいinput_embeddings引数に入力できる画像埋め込みを生成します(mlx-lmに行われたコミットを参照)。
現在、Gemma 3(Gemma3VisionAddOn)とPixtral(PixtralVisionAddOn)の2つのモデルのみが統一アーキテクチャに移行されました。しかし、このアーキテクチャは、より多くのVisionAddOnsをmlx-engineのvision_add_onsディレクトリに簡単に追加し、ModelKitのこちらで配線できるように設計されています。
VISION_ADD_ON_MAP = { "gemma3": Gemma3VisionAddOn, "pixtral": PixtralVisionAddOn, }
私たちのオープンソースリポジトリhttps://github.com/lmstudio-ai/mlx-engineでこのパターンを拡張するための貢献を歓迎します!例えば、mlx-engineイシューExtend VisionAddOn Pattern to Qwen2.5VL #167を参照してください。
mlx-engineリポジトリについては、https://github.com/lmstudio-ai/mlx-engineでご覧いただくか、貢献してください。