取り組みの背景 — モバイルアプリでのAI統合は「全部任せる」が正解ではない
Rork をはじめとするAIアプリ開発ツールの進化により、モバイルアプリにAI機能を組み込むハードルは大きく下がりましました。しかし「AIにすべてを任せる」設計は、モバイル環境特有の制約と相性が悪いケースがあります。
IDCは「企業は決定論的とエージェント的アプローチの両方を単一フレームワークで支援するプラットフォームを求めている」と指摘しています。また Gartner は「Agentic AIプロジェクトの40%以上が2027年末までにキャンセルまたは大幅縮小される」と予測しています。
モバイルアプリにおけるAI設計の3つの課題
課題1: ネットワーク依存とレイテンシ
モバイルアプリはデスクトップと異なり、ネットワーク接続が不安定な環境で使われます。すべての処理をAI API(クラウド上のLLM)に依存すると、地下鉄や山間部でアプリが動作しなくなります。
課題2: トークンコストとバッテリー消費
LLM APIの呼び出しはトークン数に応じた課金が発生します。また、頻繁なAPI通信はバッテリー消費を増大させます。ユーザー操作のたびにAI APIを呼ぶ設計は、コストとUXの両面で非効率です。
課題3: 応答の一貫性
フォームバリデーション、数値計算、日付処理のような決定論的タスクにAIを使うと、同じ入力に対して異なる結果を返す可能性があります。ユーザーにとって「昨日と今日で入力チェックの結果が変わる」体験は混乱の原因です。
関心の分離: どこにAIを使い、どこに使わないか
AIエージェントに任せるべきタスク
- 自然言語の理解: ユーザーの曖昧な指示やフリーテキスト入力の解釈
- コンテンツ生成: テキスト・画像・レコメンデーションの生成
- 対話型インターフェース: チャットボット、音声アシスタント
- パーソナライゼーション: ユーザーの嗜好に基づく動的なUI調整
- 異常検知: 通常パターンから逸脱した入力やログの検出
決定論的ツールに委譲すべきタスク
- フォームバリデーション: メールアドレス形式、電話番号、日付のチェック
- 数値計算: 合計金額、税計算、割引率の算出
- データ変換: 通貨換算、単位変換、日時フォーマット
- ローカルストレージ操作: キャッシュ管理、オフラインデータ永続化
- ナビゲーションロジック: 画面遷移、ディープリンクのルーティング
- 認証フロー: ログイン、トークン管理、セッション制御
実践例: Rork で作るECアプリのアーキテクチャ
ECアプリを例に、AIと決定論的ツールを適切に分離した設計を考えてみましょう。
レイヤー構成
[UIレイヤー]
├── 商品検索(AI: 自然言語検索 + ローカル: フィルター/ソート)
├── 商品詳細(ローカル: データ表示 + AI: レビュー要約)
├── カート(ローカル: 金額計算・在庫チェック)
├── チャットサポート(AI: 対話・問題解決)
└── 決済(ローカル: Stripe SDK・バリデーション)
[ビジネスロジックレイヤー]
├── 価格計算エンジン(決定論的)
├── 在庫管理(決定論的)
├── レコメンデーション(AI)
└── 不正検知(AI)
[データレイヤー]
├── ローカルDB(SQLite / AsyncStorage)
├── リモートAPI(REST / GraphQL)
└── AI API(Claude / Gemini)
実装例: 商品検索の分離設計
// React Native / Expo での実装例
// 1. AIによる自然言語検索(ネットワーク必要)
async function aiSearch(query: string): Promise<Product[]> {
// "赤いワンピースで1万円以下のもの" のような自然言語を処理
const response = await fetch("/api/ai-search", {
method: "POST",
body: JSON.stringify({ query })
});
return response.json();
}
// 2. ローカルフィルター(オフライン対応・決定論的)
function localFilter(
products: Product[],
filters: { minPrice?: number; maxPrice?: number; category?: string }
): Product[] {
return products.filter(p => {
if (filters.minPrice && p.price < filters.minPrice) return false;
if (filters.maxPrice && p.price > filters.maxPrice) return false;
if (filters.category && p.category !== filters.category) return false;
return true;
});
}
// 3. ローカルソート(決定論的・高速)
function localSort(
products: Product[],
sortBy: "price_asc" | "price_desc" | "rating" | "newest"
): Product[] {
const sorted = [...products];
switch (sortBy) {
case "price_asc":
return sorted.sort((a, b) => a.price - b.price);
case "price_desc":
return sorted.sort((a, b) => b.price - a.price);
case "rating":
return sorted.sort((a, b) => b.rating - a.rating);
case "newest":
return sorted.sort((a, b) =>
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
);
}
}
// 統合: AIで検索 → ローカルでフィルター&ソート
async function searchProducts(
query: string,
filters: FilterOptions,
sortBy: SortOption
) {
// AI検索はネットワークが必要な場合のみ
const results = navigator.onLine
? await aiSearch(query)
: await localFallbackSearch(query); // オフライン時はローカル検索
// フィルターとソートは常にローカルで実行(高速・決定論的)
const filtered = localFilter(results, filters);
return localSort(filtered, sortBy);
}実装例: カート金額計算(決定論的)
// カート金額の計算は絶対にAIに任せない
// 同じ入力で同じ結果を返すことが必須
interface CartItem {
productId: string;
name: string;
price: number;
quantity: number;
taxRate: number;
}
function calculateCartTotal(items: CartItem[]) {
const subtotal = items.reduce(
(sum, item) => sum + item.price * item.quantity, 0
);
const tax = items.reduce(
(sum, item) => sum + Math.floor(item.price * item.quantity * item.taxRate),
0
);
const total = subtotal + tax;
return { subtotal, tax, total };
}
// 使用例
const cart: CartItem[] = [
{ productId: "001", name: "Tシャツ", price: 2980, quantity: 2, taxRate: 0.1 },
{ productId: "002", name: "パンツ", price: 4980, quantity: 1, taxRate: 0.1 }
];
const result = calculateCartTotal(cart);
console.log(`小計: ¥${result.subtotal} / 税: ¥${result.tax} / 合計: ¥${result.total}`);
// 出力: 小計: ¥10940 / 税: ¥1094 / 合計: ¥12034オフラインファースト設計の重要性
モバイルアプリではオフライン対応が重要です。関心の分離により、決定論的タスクをローカルに配置すれば、ネットワーク不通時もコア機能が動作します。
- カート操作: ローカルストレージで完結
- 閲覧履歴: ローカルDBに保存
- フォーム入力: バリデーションはローカル、送信はオンライン復帰後
- AI機能: ネットワーク復帰後に非同期で実行
この設計であれば、地下鉄の中でも商品の閲覧やカート操作は問題なく行えます。
コスト削減の効果
AIエージェントに全処理を任せた場合と、関心の分離を適用した場合のコスト比較を考えてみましょう。
全処理をAI APIに依存した場合(月間10万ユーザー想定):
- 商品検索: 10万回 × トークン消費
- フィルタリング: 30万回 × トークン消費
- カート計算: 20万回 × トークン消費
- レコメンデーション: 10万回 × トークン消費
関心の分離を適用した場合:
- 商品検索(AI): 10万回 × トークン消費
- フィルタリング(ローカル): 0円
- カート計算(ローカル): 0円
- レコメンデーション(AI): 10万回 × トークン消費
API呼び出し回数が約70%削減され、コストとレイテンシが大幅に改善します。
まとめ
モバイルアプリにおけるAIエージェント設計は、「すべてをAIに任せる」よりも「AIが最も効果を発揮する領域に集中させ、残りは決定論的ツールに委譲する」アプローチが効果的です。ネットワーク依存の軽減、コスト削減、応答の一貫性という3つの面で、関心の分離はモバイルアプリの品質を確実に向上させます。
Rork でアプリを構築する際は、「この処理は本当にAIでなければ解決できないか?」を自問する習慣を持つと、よりバランスの取れたアーキテクチャに近づけるでしょう。モバイルアプリの設計パターンをさらに深く