AI・機械学習
OUI-1: 世界初の生成UIモデル
OUI-1: world's first model for Generative UI (openui.com)
要約
OpenUIは、OpenUI-Langでユーザーインターフェースを生成する、世界初の生成UIモデル「OUI-1」を発表しました。このモデルは、消費者向けGPUで実行可能であり、従来のソフトウェアと同等の速度で信頼性の高いインターフェースをローカル生成することを目指しています。
全文翻訳
OUI-1は、openui-langでユーザーインターフェースを記述する、ファインチューニングされたDiffusionGemmaモデルです。これは26Bパラメータのモデルで、消費者向けGPU(FP8でRTX 5090)で実行可能であり、重みはGemma利用規約の下でHugging Faceで公開されています。
なぜOUI-1を構築したのか
エージェント駆動型インターフェースはソフトウェアの未来です。しかし、そこに至るには3つの制約があります。インターフェースは1秒未満で生成されなければなりません。ソフトウェアとして使用できるほど信頼性がなければなりません。そして、モデルは消費者向けハードウェアでローカル実行できるほど小さくなければなりません。
AppLessでは、Cerebras上のGemma 4を使用してその体験を模索しました。しかし、それはクラウド上の専用ハードウェアに依存していました。それをデバイス上に移行するということは、より難しい問題を解決することを意味します。品質や生成されたインターフェースの正確性を犠牲にすることなく、計算リソースが大幅に少ない状態で応答性を維持することです。OUI-1は、その問題解決に向けた私たちの最初のステップです。消費者向けハードウェアで信頼性の高いインターフェースを生成するために構築された、オープンウェイトモデルです。野心は、従来のソフトウェアの速度でローカル生成される、信頼性の高いエージェント駆動型インターフェースです。
制約に合うモデルを見つける
プロトコルはすでに確立されていました。OpenUI LangはJSONよりも最大67%少ないトークンで、ストリーミングも可能なため、モデルが生成を完了する前にインターフェースが表示され始めます。より難しい部分は、適切な速度とハードウェアプロファイルを持つモデルを見つけることでした。だからこそ、DiffusionGemmaを選択しました。
自己回帰モデルは一度に1つのトークンを生成し、メモリ帯域幅がボトルネックになります。DiffusionGemmaは、ノイズから開始し、確信した瞬間に各トークンをコミットすることで、一度に256トークンのブロックを書き込みます。Googleによると、単一のH100で毎秒1,000トークン以上、RTX 5090で700トークン以上を処理できます[1]。DiffusionGemmaは私たちが求めていた速度を提供してくれました。しかし、速度だけではソフトウェアは作れません。インターフェースも機能しなければなりません。それが私たちが埋める必要があったギャップでした。
ギャップが北極星になった
ベンチマークにより、ギャップが具体的になりました。DiffusionGemmaは、Generative UI Benchmarkで13.0%のスコアでした。求めていた速度とハードウェアプロファイルはありましたが、信頼性はありませんでした。OpenUI Langパーサーにより、それらのエラーは容易に可視化されました。
スキーマエラーは、間違った列挙型、必須プロパティの欠落、または発明されたコンポーネントです。配線エラーは、使用されたが定義されていない名前、または定義されたがルートにアタッチされていないセクションです。
header = CardHeader("Spending", "last 7 days")
total = Heading("$24,180", "h9")
// schema: h9 is not a heading level
chart = AreaChart(days, [spend], "wavy")
// schema: "wavy" is not a curve type
footer = TextContent("Updated today")
// wiring: defined, never attached to root
root = Card([header, total, chart, summary])
// wiring: summary is never defined
それが私たちの北極星になりました。速度を犠牲にすることなく、両方の種類のエラーを削減することです。
どのようにトレーニングしたか
トレーニングは2段階で展開されました。まず、教師ありファインチューニングを通じてDiffusionGemmaにOpenUI Langを記述することを教えました。次に、自己蒸留を使用して速度を回復し、信頼性を向上させました。それが1つのコンポーネントライブラリで機能した後、27のライブラリ全体でプロセスを繰り返しました。
フェーズ1: 教師ありファインチューニング
約700のOpenUI Langの例(より大きなモデルによって書かれたもの)から始め、7つのコンポーネントライブラリにまたがるもので、1つのA100でLoRAファインチューンを実行しました。損失は低下しました。しかし、ベンチマークスコアもそれに伴って低下しました。モデルはより長く、より密なプログラムを書くことを学びましたが、そのほとんどはきれいに解析されませんでした。
問題を単一のコンポーネントライブラリに絞り込みました。ベンチマークで使用されているライブラリです。スコアは13.0%から28.8%に上昇しましたが、進歩にはトレードオフが伴いました。ある実行では配線エラーを減らし、スキーマエラーを増やしました。次の実行ではその逆でした。
エラーの行方
2802 DiffusionGemma 24/184回の実行完了 100ステートメントあたり35.3の欠陥
1263 ファインチューニング後 53/184回の実行完了 100ステートメントあたり16.4の欠陥
203 13.8倍少ない OUI-1 132/184回の実行完了 100ステートメントあたり3.8の欠陥
スキーマエラー
配線エラー: 未定義の名前と孤立したセクション
2つのエラータイプはシーソーのように動きました。私たちはベースモデルよりもはるかに進んでいましたが、どちらの実行も両方を同時に減らすことはできませんでした。LoRAの容量限界に達したと仮定しました。一度に1つの規律しか学べず、後でフルファインチューンでトレードオフが解決されるだろうと考えました。
次に2番目の問題が見つかりました。モデルが遅くなっていたのです。ファインチューニングで速くなることを期待していました。サンプラーは、エントロピーがしきい値を下回るとトークンをコミットするため、言語を知っているモデルはより早く確信できるようになるはずです。それどころか、同じ20の軽いブリーフで、生成時間は出力あたり1.6秒から4.3秒に増加しました。ベースモデルは、出力が短く一般的で、ステートメントあたり平均22トークンだったため、高速でした。ファインチューニングされたモデルは、実際の名前と値を記述し、ステートメントあたり平均32トークンで、各トークンをコミットするためにより多くのデノイズステップを必要としました。より有用なインターフェースを生成することを教えましたが、DiffusionGemmaを興味深いものにしていた速度を失ってしまいました。
出力あたりの秒数、ファインチューニング前と後
同じ20の軽いブリーフ、一度に1つのリクエスト、両方の行で同じサービング設定: vLLM, FP8, 1つのA100。
DiffusionGemma 1.6s
ファインチューニング後 4.3s
ファインチューニングされたモデルはより長い出力を記述し、トークンあたりのデノイズステップが約2倍必要になります。DiffusionGemmaが短く一般的なものをコミットするのに対し、実際の名前と値をコミットしています。
フェーズ2: 自己蒸留
ブレークスルーは、OpenUI Langには検証可能な報酬があることに気づいたことでした。パーサーは、インターフェースが構造的に有効かどうかを判断し、無効な場合は正確なスキーマまたは配線エラーを特定できます。それは、モデルが自身の教師になることができることを意味しました。プログラムを生成し、パーサーからのフィードバックを使用して保持または修正し、結果から学習することです。
自己蒸留は、拡散言語モデルで使用されるデノイズステップを削減する既知の方法であるため、速度を回復する道も提供しました[2][3]。私たちのバージョンは、リジェクションサンプリングされた自己トレーニングと修正を使用します。モデルは数百のOpenUI Langプログラムを生成し、パーサーは受け入れたものを保持します。ニアミスは修正パスを通過し、パーサーが報告した欠陥のみを修正します。書き換えたり発明したりする編集は拒否します。中央値の修正は1つのステートメントを変更します。次に、ジャッジが各生存プログラムがブリーフに一致するかどうかを確認します。それらのプログラムが次の実行のトレーニングセットになります。500ステップで、A100 1台で1〜2時間かかります。結果のモデルは次のバッチを生成し、ループが再び始まります。
自己蒸留: 生成、検証、再トレーニング
1. 生成: モデルが数百のopenui-langプログラムを記述
2. 検証: パーサーがクリーンに通過したものを保持。ジャッジが各プログラムをブリーフに対してチェック。
3. 修正: ニアミスはLLMによって修正。リストされた欠陥のみ、書き換えは拒否。
4. 再トレーニング: 生存者が次のトレーニングセットになる。
各パスは次のバッチを記述するモデルをトレーニングします。
速度が戻ってきました。同じ20の軽いブリーフで、生成時間は出力あたり4.3秒から1.9秒に減少しました。それにもかかわらず、出力にはDiffusionGemmaの出力よりも28%多くのトークンが含まれていました。そしてシーソーは止まりました。ベンチマークスコアは57.1%に達し、スキーマエラーは292から76に減少し、配線エラーは同じモデルで971から484に減少しました。以前のすべての実行は一方のエラータイプをもう一方と交換していましたが、自己蒸留は両方を改善しました。実質的に、これは最も単純な形の強化学習です。パーサーを報酬とするリジェクションサンプリングです。私たちの仮説(まだ分離していませんが)は、モデル自身のテキストでトレーニングすることにより、ほとんどすべての場所で損失が低く保たれ、勾配が変更された少数のものに集中することです。修正されたステートメントとモードに向かってプッシュされたサンプリングされた選択です。前者は配線修正を教え、後者はエントロピーしきい値がトークンをより早くコミットできるようにモデルをシャープにします。教師が書いたデータは、まったく異なる書き方のスタイル全体にその勾配を広げます。
フェーズ3: 27のコンポーネントライブラリ全体での一般化
単一ライブラリの結果により、もう1つの疑問が残りました。モデルは学習したのか?