Flux Engine 設計ノート:すべてのプロダクトに、ひとつのランタイム
私たちの端末側推論ランタイムを支えるアーキテクチャ判断と、それを形作った技術的制約をのぞき見する。
ラッパーではなく、ランタイム
オンデバイスアプリを1本作るのは難しい。5本となるとさらに難しい。5本が一貫した技術基盤を共有し、同時にアップデートを出し、電池性能を退行させないためには――これはランタイムの問題だ。
Flux Engine がその答えだ。各レーンで最強のオープンソースランタイムの上に重ねた、薄くて意見の強い層――音声(whisper.cpp / faster-whisper)、視覚(llama.cpp / mlx-vlm)、言語(llama.cpp / MLC-LLM、Android では executorch)――を、いまメモリに何があるか、ユーザは何をしているか、デバイスはどこまで耐えられるかを知っている1つのスケジューラが束ねている。
3つの制約
1. コールドスタート遅延
モデルはほとんどの時間、ディスクで眠っている。ユーザはそうではない。Flux Engine はアプリの使用パターンと小さなオンデバイス分類器に基づいて、次に呼ばれそうなモデルを先に温めておく。この分類器自体は50KBのMLPで、起床ごとに動かしても痛くない。
2. 小さなNPUでの持続スループット
同じアクセラレータを取り合う並列ワークロードを生むことはしない。スケジューラはキュー型で優先度を意識し、フォアグラウンドアプリに強制譲渡する。ASRストリームはバックグラウンド要約より優先、タップ翻訳はバックグラウンドインデックスより優先される。
3. メモリ不足下での優雅な縮退
ユーザが4Kビデオを編集している最中に要約のためにOOMする、はあり得ない。エンジンは「残り余力」のソフト信号を返し、プロダクトはそれを尊重する――機能はより小さなモデルに落ちるか、バックグラウンドに延ばすか、「冷えたら続き」と示すかのどれかになる。
Flux Engineが実際に晒しているもの
いくつかのC++抽象と、Swift / Kotlin / Rustの薄いバインディング:
FluxSession—— モデル+デバイスに紐づいた長命の推論セッション。FluxStream—— トークン途中でキャンセル可能な逐次出力。FluxBudget—— デバイスの状態を反映した容量レポート。FluxRouter—— デバイスティア、電池、サーマル状態、プロダクトの好みを見て、要求に合うモデルを選ぶ。
これだけだ。プリミティブは5つ。すべてのFlux*プロダクトはこの上に立つ。
それで得られるもの
バグ修正1件、性能改善1件、量子化改良1件で、5プロダクトが同時に良くなる。スケジューラ側の退行修正1件で、5プロダクトの電池スパイクが同時に止まる。この規模のチームに共有ランタイムを置く経済的合理性は圧倒的だ。
いままで間違えたこと
- 最初の6か月、グラフコンパイラに投資しすぎた。結局、手で調整したモデルローダが勝った。
- プロファイリングに投資が足りなかった。9か月目に作り直した。
- 全プロダクト共通の量子化スキームを仮定していた。いまはプロダクトごとに混合している。