◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/AIモデル
◉ AIモデル/2026-04-30上級

Rork で『AI が自動でアルバム化する写真整理アプリ』を作る実装ガイド — Vision × CLIP × pgvector で本番品質のパイプラインを設計する

Rork で写真ライブラリを AI が自動分類するアプリを本気で作るための完全実装ガイドです。Vision で顔・物体・テキストを抽出し、CLIP 埋め込みで意味検索を実現し、Supabase pgvector で類似画像検索を可能にする本番運用パイプラインを、コード付きで一から設計します。

Rork585AI32写真整理CLIPVisionpgvector3Supabase37PhotoKitベクトル検索

✦ プレミアム記事

import { Callout } from '@/components/ui/callout';

iPhone を 5 年も使い続けると、写真ライブラリは平気で 3 万枚を超えます。私自身、過去のアプリ素材や旅行写真を探すたびに「あの夕焼けの写真、どのフォルダに入れたっけ」とスクロールに 10 分溶かすことがあり、ずっと「写真整理アプリは AI 前提で作り直すべき領域だな」と感じてきました。実際、App Store の上位写真整理アプリの大半は 2024 年以降に AI 機能を主軸に作り変わっており、ここから新規参入する余地はまだ十分に残っています。

Rork で「写真ライブラリを AI が自動で分類してくれるアプリ」を組むとき、難所は Vision の呼び出し方ではありませんでした。難所は、5 万枚という数がパイプラインのあちこちで静かに前提を壊していくところにあったのです。ここでは、その前提が壊れた場所と、私がどう線を引き直したかを、コードと一緒に書き残します。

5 万枚を捌くための 3 層アーキテクチャ

写真整理アプリでよくある失敗は、起動時に全画像を一気に解析してしまい、メモリも電池も食い尽くす実装です。私も最初の試作では、ユーザーが起動してから「処理中...」が 30 分続くアプリを作ってしまいました。本番品質に持っていくには、解析を 3 層に分けて非同期パイプライン化する必要があります。

設計の骨格は次の 3 層です。

  • Layer 1 (端末側・即時): PhotoKit から PHAsset を列挙し、Vision で軽量な物体検出 / OCR / 顔検出を実施します。CoreML CLIP モデルで 512 次元の埋め込みを生成します。
  • Layer 2 (端末側・バックグラウンド): 端末がアイドル状態のときに BGProcessingTask で残りの画像を順次処理します。SQLite に解析結果と埋め込みをキャッシュします。
  • Layer 3 (サーバー側): 端末ストレージに収まらない検索用ベクトルインデックスは Supabase pgvector に保存し、類似検索は HNSW インデックスで高速化します。

ローカル CLIP 埋め込みをそのまま pgvector に同期できるよう、端末とサーバーで同じ埋め込み空間を共有することが鍵です。これを最初に決めておかないと、後からアーキテクチャを総取り替えする羽目になります。

なぜ CLIP を使うのか — Vision との役割分担

Vision フレームワークは「これは犬」「これは車」「これはテキスト」というカテゴリ判定は得意ですが、「夕焼けの海辺で犬と一緒に写っている写真」のような意味的な類似性は扱えません。一方 CLIP(OpenAI が公開し、Apple が CoreML 形式に最適化したモデルが利用可能)は、画像とテキストを同じベクトル空間に射影できるため、自然言語クエリでの類似検索が可能になります。

実装では両方を併用します。Vision で「タグ」を付け、CLIP で「意味埋め込み」を付けておきます。検索時に両方を組み合わせるやり方がいちばん精度が高く、私が試した中でも最終的にこのハイブリッドだけが残りました。片方に寄せたほうが実装は軽くなるのですが、軽くしたぶんだけ「探せない写真」が増えていくのだと気づいたのは、自分のライブラリで半年ほど使い込んだあとでした。

Step 1: PhotoKit で写真ライブラリにアクセスする

最初の関門は、ユーザーから写真ライブラリへのアクセス許可をどう取るかです。iOS 14 以降、PHPickerViewController が推奨されていますが、写真整理アプリのように「全画像を解析したい」場合は PHPhotoLibrary の addOnlyAccess ではなく readWriteAccess を要求する必要があります。

権限取得は次のように書きます。Rork のネイティブモジュール(または Expo Modules API)から呼び出せるよう、Swift 側のヘルパーとしてまとめておくのが運用しやすい構造です。

import Photos
 
enum PhotoLibraryAuthError: Error {
  case denied
  case restricted
  case limited
}
 
func requestPhotoLibraryAccess() async throws -> [PHAsset] {
  let status = await PHPhotoLibrary.requestAuthorization(for: .readWrite)
  switch status {
  case .authorized:
    return fetchAllAssets()
  case .limited:
    // ユーザーが選択した画像だけが返る。UI で「フルアクセスへの誘導」を表示する。
    throw PhotoLibraryAuthError.limited
  case .denied:
    throw PhotoLibraryAuthError.denied
  case .restricted:
    throw PhotoLibraryAuthError.restricted
  case .notDetermined:
    throw PhotoLibraryAuthError.denied
  @unknown default:
    throw PhotoLibraryAuthError.denied
  }
}
 
private func fetchAllAssets() -> [PHAsset] {
  let options = PHFetchOptions()
  options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
  options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
  let result = PHAsset.fetchAssets(with: options)
  var assets: [PHAsset] = []
  result.enumerateObjects { asset, _, _ in assets.append(asset) }
  return assets
}

期待する動作は、初回起動時に許可ダイアログが出て、許可されればすべての画像 PHAsset が降順で返ります。limited を返すユーザーは、設定アプリでアクセスを「すべての写真」に変更しないと AI 整理機能が使えないことを画面内で丁寧に説明する必要があります。私は「ライブラリ全体をスキャンしないと類似検索ができないため、フルアクセスをお願いしています」と一行で説明する画面を別途作りました。

PHAsset から実画像を取り出すときの落とし穴

PHImageManager で画像を取得するとき、requestImage のオプション設定を間違えると iCloud から都度ダウンロードが走り、月のモバイル通信を食い尽くすことになります。これは私が初回リリース後にユーザーから本気で苦情をもらったポイントなので、必ず以下の設定にしてください。

let options = PHImageRequestOptions()
options.isNetworkAccessAllowed = false  // ローカルキャッシュのみ使用
options.deliveryMode = .opportunistic
options.resizeMode = .fast
options.isSynchronous = false

isNetworkAccessAllowed = false にしておくと、「最適化済み(クラウド保存)」の画像だけはスキップされます。これらは別キューで「オフライン解析待ち」にしておき、Wi-Fi 接続時にまとめて取得する設計にします。後述するバックグラウンドジョブで処理します。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦5 万枚の写真の中から『あの夕焼けの 1 枚』を 0.3 秒で探せる、CLIP 埋め込みベースの類似検索パイプラインを Rork アプリに組み込めるようになる
✦PhotoKit から数万枚の画像を取り出し、バックグラウンドで Vision 解析と埋め込み計算をジョブ化する本番運用パターンを習得できる
✦Vision の物体検出・OCR・顔ベクトルと CLIP のセマンティック埋め込みを併用するハイブリッド検索設計を、自分のアプリに転用できる
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

◉ AI モデル2026-04-22
Rork で作る AI 読書アシスタントアプリ実装 — 本棚スキャン、進捗管理、章別要約の設計と運用
本棚を写真で撮るだけで蔵書を登録し、Claude が章別に要約と問いを生成する読書アプリを Rork で実装します。Vision と Claude の二系統マージ、トークン単価の実測、ネタバレ抑止の後処理、課金設計までを扱います。
◉ AI モデル2026-10-14
プロンプトをアプリから外して Edge Function に置く。守りは入力側でなく、出力側に作りました
アプリに入れた AI の指示文は、配信した日から読める側に回ります。プロンプトを Supabase Edge Function に寄せ、クライアントにはタスク名だけを言わせ、守りを出力の許可リストに置く構成を、テスト付きのコードで整理しました。
◉ AI モデル2026-09-28
続きで直すか、復元ポイントへ戻して言い換えるか。Rork で同じ不具合を両方の道で直して分かった境目
Rork の修正依頼が三度目にはまったとき、続きで頼むか、Restore で戻して言い換えるか。同じ不具合を両方で直した往復回数と残ったコードを並べ、私が引いた線をお伝えします。