アンドロイドオートメーションにトークンを無駄にしないで
ほとんどのLLM(大規模言語モデル)駆動型アンドロイドオートメーションは、まずモデルに画面を表示して始まります
それは合理的に聞こえます。人間が電話を見て、タップするものを決め、タップします。モデルに同じ視点を与えます
問題は「同じ視点」がコストが高いということです
フルスクリーンショットはコストが高い。生のAndroid UI XMLダンプも静かにそれに近いコストがかかる。モデルはレイアウトの機械構造の数千のトークンを読み取った後、重要な少数のラベルに到達するまでに至る:
Email
Password
Continue
一つのステップでは、その無駄は簡単に無視できる。50ステップのモバイルエージェントの軌跡では、それが請求書となる。
ループ
アンドロイドエージェントは通常こんなことをします:
- 現在の画面を読み取ります。
- 何をするか決定します。
- タップ、タイプ、またはスワイプします。
- 次の画面を待ちます。
- 繰り返します。
最初のステップがトークン漏洩の始まりです。
uiautomator dumpを使用すると、モデルはこのようなXMLを取得します:
<node index="0" text="" resource-id=""
class="android.widget.FrameLayout"
package="com.google.android.apps.nexuslauncher"
content-desc=""
checkable="false" checked="false"
clickable="false" enabled="true"
focusable="false" focused="false"
scrollable="false" long-clickable="false"
password="false" selected="false"
bounds="[0,0][1440,3120]">
それは一つのレイアウトノードです。エージェントが行動できることについてほとんど何も言っていません
それはUIAutomatorのバグではありません。XMLはアクセシビリティツリーの忠実なシリアライズです。忠実であることは有用であることとは同じではありません
数値
いくつかの普通のAndroid画面では、差はこのように見えます
| 画面 | UIAutomator XML | 携帯電話hs ui -i
|
削減 |
|---|---|---|---|
| 起動画面ホーム | 3,153トークン | 246トークン | 12.8x |
| 設定画面ホーム | 5,762トークン | 729トークン | 7.9x |
| 設定 ->アプリ | 4,050トークン | 320トークン | 12.7倍 |
トークン数はtiktokenでGPT-4エンコーディングを使用して計算されました。詳細な説明はAn Android UI Dump for LLMsです。
簡単な説明:典型的なスクリーンはXMLで4,000-6,000トークンのコストがかかる場合、アクションテーブルで数百トークンで表現できることが多いです。
50歩分、それはスクリーン状態の約25万トークンを送信するのと、約2万5千~4万トークンを送信するのとで差がある.
エージェントはどちらの場合も同じ決定を下す.
モデルが実際に必要なもの
UI自動化のために、モデルはDOM形の木構造は必要ない.
それには、行動できるもののリストが必要である.
fill EditText "Email" #email 540,540
fill EditText "Password" #password 540,640 [password]
tap Button "Continue" #continue 540,860
そのテーブルはモデルに役立つ事実を与えます:
- どのようなアクションが利用可能ですか。
- 人間がどのようなラベルを見ますか。
- どのようなコントロールですか。
- ツールがタップまたはタイプする場所はどこですか。
モデルは現在答えることができます:
tap "Continue"
レイアウトの祖先をパースしたり、ネガティブブーリアンや完全修飾クラス名、四つの数字の境界矩形を解析する必要はありません.
ルール
LLMツールの出力に対する最適化ルールは単純です.
モデルが次のアクションで使用できない事実をシリアライズしない.
Android XMLはこのルールを常に違反します.
-
clickable="false"エージェントが絶対にクリックしないノードで。 -
enabled="true"はほぼすべてのノードで繰り返されます。 FrameLayoutとLinearLayoutコンテナは空です。android.widget.TextViewのような完全なクラス名。- エージェントがタップポイントのみが必要な場合に境界矩形を設定します。
- 言語モデルが読者である場合、パーサーではなく、JSONスタイルのキー繰り返し。
デフォルトを外し、名前を短くし、中心点を計算し、ラベルを保持します.
結果は小さなXMLファイルではありません。それは異なるインターフェースです.
hs ui
hs tap "Continue"
hs wait "Dashboard"
スクリーンショットはまだ役立ちます
これはスクリーンショットに対する議論ではありません。
レイアウトが重要な場合、ビジュアル状態が重要な場合、またはアプリがアクセシブルなラベルなしで重要な情報をレンダリングする場合、スクリーンショットは役立ちます
しかし、スクリーンショットはすべてのステップのデフォルトには適していません。それらは大きく、動きが遅く、しばしばモデルが既にAndroidが表示しているテキストのOCRのような作業を強制します
より良いループは次のとおりです
hs ui > /tmp/screen.txt
hs see --size 768 /tmp/screen.jpg # only when visual context matters
まずモデルにテキストUIを与える。テキストが不十分な場合にのみ画像を追加する。
これにより通常はトークンを節約でき、アクションの監査が容易になる。
なぜエージェントにとってはテストよりも重要なのか
従来のモバイルテストはトークン数にはあまり関心が持っていない。テストランナーはXMLを読むために費用を払っているわけではない。
LLMエージェントは異なる。各ループステップにはコンテキスト予算とコストがある。プロンプトの半分がUIツリーに満ちた死んだレイアウトノードであれば、モデルは無駄なことに注意を費やしている。
これは三つの箇所に現れる:
- コスト:繰り返される画面状態が長い軌跡を支配する。
- レイテンシ:大きなプロンプトは送信と処理に長い時間がかかる。
- 信頼性:行動指向的な文脈が短いと、モデルが無関係な構造に引っかかる余地が減少します。
エージェントにとって最適なツールの出力は、システムの最も完全な表現ではありません。次に正しい行動を保持する最小の表現です。
実用的なパターン
Androidの場合、パターンはこのようになります:
hs use
hs ui
hs tap "Sign in"
hs fill "Email" "you@example.com"
hs fill "Password" "$PASSWORD"
hs tap "Continue"
hs wait "Dashboard"
LLMの場合、重要な引き継ぎはさらに小さいです:
Here is the current Android UI. Pick the next action by label.
fill EditText "Email" #email 540,540
fill EditText "Password" #password 540,640 [password]
tap Button "Continue" #continue 540,860
モデルはこれらのノードが3つのネストされたFrameLayout内に存在することを知る必要はありません。それには「続行」がボタンであることを知る必要があります.
関連ガイド
https://handsets.dev/blog/stop-wasting-tokens-on-android-automation/











