ブログに戻る

iPhone の写真はローカルに置いたまま、Comma に探してもらう

モデルもローカルで動きます。自然な言葉で尋ねると、Comma がローカルのインデックスから写真を見つけます。

はじめるドキュメントを読む

ネットでレンタカーを予約していると、フォームが運転免許証の番号と有効期限を求めてきます。でも免許証は手元にありません。去年新しい免許証に替えたとき、表と裏の写真を撮ったことは覚えています。ただ、その 2 枚は iPhone の何万枚もの写真の中に埋もれています。Comma に自然な言葉で尋ねて、その 2 枚を見つけてほしいところです。

このガイドでは、そのための構成を 1 つ紹介します。まずローカルモデルで写真のインデックスを作り、それを Comma に検索させます。これは 1 台の Mac での構成例で、Comma の組み込み機能ではありません。

ライブラリはローカルのまま

Comma に写真のコピーは要りません。いちばん重い作業、つまり各画像の文字を読み取り、各写真をベクトルに変える処理は、ローカルモデルが行います。エージェントが受け取るのは検索の結果です。いくつかの写真 ID、その日付、画像から読み取った文字、そして選んでもらう必要があるときは、サムネイルを並べたコンタクトシート 1 枚です。最終的にあなたが選んだ写真だけがチャットに送られます。

写真の同期自体は iCloud を通ります。ここで言うローカルとは、書き出したあとの文字認識、ベクトル、インデックスのことです。Comma がクラウドのモデルを使う場合、これらの検索結果と、あなたが見るように頼んだ画像は、あなたが選んだモデルプロバイダーに送られます。運転免許証のような書類なら、読み取った文字に番号や住所が含まれます。インデックスそのものはどこにも送られません。Comma はオープンソースで、自分のマシンで動かすこともできます。

写真のインデックスを作る

インデックスは、写真がもともと通る経路の後ろにつなぎます。iPhone 側は何も変えません。

写真は iCloud 写真で iPhone から Mac に同期して書き出され、ローカルモデルがサムネイル作成、文字認識、2 種類の画像ベクトル計算、全文インデックス作成を行います 1 · Mac に持ってくる iPhone いつもどおり撮影 iCloud 写真 Mac に同期 Mac の「写真」 ライブラリは外付けドライブに置ける 元の写真を書き出す 撮影日時と場所を残す 2 · ローカルモデルで処理 サムネイル 以降の処理はこれだけを読む 文字 Apple Vision 画像ベクトル Chinese-CLIP 画像ベクトル Qwen3-VL-Embedding 全文インデックス SQLite 検索時は 2 種類のベクトルで それぞれ順位を付けて合わせる 写真は iCloud 写真で iPhone から Mac に同期して書き出され、ローカルモデルがサムネイル作成、文字認識、2 種類の画像ベクトル計算、全文インデックス作成を行います 1 · Mac に持ってくる iPhone いつもどおり撮影 iCloud 写真 Mac に同期 Mac の「写真」 ライブラリは外付けドライブに置ける 元の写真を書き出す 撮影日時と場所を残す 2 · ローカルモデルで処理 サムネイル 以降の処理はこれだけを読む 文字 Apple Vision 画像ベクトル Chinese-CLIP 画像ベクトル Qwen3-VL-Embedding 全文インデックス SQLite 検索時は 2 種類のベクトルで それぞれ順位を付けて合わせる
書き出したあとの処理はすべて Mac 上で動きます。

構成は 3 つのステップです。

  1. 写真をローカルに持ってくる。 iCloud 写真で iPhone の写真を Mac に同期し、新しい写真を毎日 1 つのフォルダに書き出します。

  2. ローカルモデルで処理する。 画像の中の文字を認識し、Chinese-CLIP と Qwen3-VL-Embedding で画像をベクトルに変えます。

  3. ローカルのインデックスに保存する。 結果をローカルのデータベースに保存し、検索用のコマンドを 1 つ用意します。この例ではそのコマンドを lpa と呼びます。

検索で返ってくるもの

ローカルでは、1 回の検索は 1 つのコマンドです。1 回の呼び出しに複数の言い方を入れられ、モデルの読み込みは 1 回で済みます。エージェントは「去年」のような言葉を日付の範囲に置き換えます。

sh
lpa search "driver license" "driver's license" "驾照" \
  --from 2025-01-01 --to 2026-01-01 --prefer text --json -n 9

各結果には、その裏にある根拠の種類が示されます。

表示意味
文字一致すべての語が画像の文字の中に見つかった。
可能性あり見た目が似ている。似たものは取り違えやすい。
低信頼度もっとよい結果がないときだけ表示される。

--prefer text は文字一致を先に並べるので、書類、カード、スクリーンショットを探すのに向いています。--prefer picture は見た目の似た写真を先に並べるので、猫や海辺を探すのに向いています。数分のうちに撮ったほぼ同じ写真は、リストの中で 1 つの枠だけを使い、残りはその下にまとめられます。

Comma のチャット。海辺の宿の Wi-Fi パスワードを尋ねると、Comma は部屋の写真に写った小さなカードからネットワーク名とパスワードを読み取り、その写真を送ります。
文字一致の例。ネットワーク名とパスワードは、写真に写ったカードの文字から読み取っています。この写真は本例のために生成したものです。
Comma のチャット。窓辺にいる猫の写真を頼むと、Comma は窓辺の猫の写真を 3 枚返します。
画像一致の例。これらの写真には「猫」や「窓辺」という文字はどこにもなく、画像ベクトルが見つけています。

上位の結果に確信が持てないとき、エージェントは推測しません。候補のサムネイルを番号付きの 1 枚のシートにまとめ(最大 9 枚)、あなたに選んでもらいます。

番号付きの 3×3 コンタクトシート。1 と 2 は見本の運転免許証の表と裏、3 と 4 は Wi-Fi カード、残りは低信頼度の候補です。
コンタクトシートの例。免許証は見本のカードです。1 と 2 は表と裏の文字一致、3 と 4 はカードに似た画像、残りは低信頼度の候補です。「1 と 2」と返すと、エージェントが免許証の表と裏を送ります。

2 種類のベクトルの使い方は、約 5 万枚の写真がある実際のライブラリで調整して決めました。Qwen3-VL-Embedding だけを使うと、人が選んだ正解が Chinese-CLIP だけのときより下位に来てしまいました。2 つの順位を合わせると、確認したどの項目も、どちらか一方のモデルだけのときより悪くなりませんでした。「可能性あり」も、2 つのモデルの類似度がどちらも基準を超えたときだけ付きます。あるテストクエリでは、「可能性あり」の写真が 4,970 枚から 4 枚に減りました。その代わり、1 回の検索は約 3 秒から 3.5〜6 秒になります。

この例はメモリ 16 GB の MacBook Air で動いていて、Qwen3-VL-Embedding は 2B を使っています。もっと性能の高いマシンなら、より大きな Qwen のモデルを使えます。

  • より大きなベクトルモデル。 Qwen3-VL-Embedding-2B を Qwen3-VL-Embedding-8B に替えます。替えたあとは、すべての写真のベクトルを新しいモデルで計算し直す必要があります。

  • 写真に説明とタグを付ける。 Qwen3-VL-4B-Instruct か Qwen3-VL-8B-Instruct を別に動かし、写真ごとに一文の説明といくつかのタグを書いて、文字のインデックスに保存します。たとえばメモリ 24 GB の MacBook Pro なら、8B(8-bit 量子化)が動きます。生成したタグは大まかな絞り込みには向いていますが、正確さは保証されません。

英語はどうするか。 Chinese-CLIP は主に中国語の画像とテキストで学習されているので、英語のクエリには頼れません。ほかの 2 つは影響を受けません。文字認識は中国語も英語も読めますし、Qwen3-VL-Embedding も多くの言語に対応しています。そこで、先ほどのコマンドのように、検索には中国語と英語の言い方を一緒に入れます。これは Skill に書いておけます。ライブラリも質問も主に英語なら、Chinese-CLIP を元の CLIP に替えることもできます。その場合もベクトルの計算し直しが必要です。

家族や友人を探す

「写真」アプリは、もともと同じ人の顔をまとめています。インデックスはこのグループをそのまま使い、自分では顔認識をしません。

  1. まず人を確認する。 最初に使うとき、エージェントはこれらのグループから何組かの写真を選び、番号を付けて誰なのかを尋ねます。あなたが「3 番は母です」と答えて、初めて覚えます。確認していないグループは、誰としても扱われません。

  2. 人で探す。 そのあとは名前を出すと、その人が写っている写真の中だけを検索します。名前は重ねられます。2 人の名前を出すと、2 人とも写っている写真、つまり一緒に写った写真だけが返ります。

  3. ほかの条件と組み合わせる。 名前は、写っているものや時期と一緒に検索できます。たとえば「去年、母と海辺で撮った写真」なら次のとおりです。

sh
lpa search "beach" --person Me --person Mom \
  --from 2025-01-01 --to 2026-01-01 --prefer picture --json -n 9

名前がまだ確認されていないとき、または同じ名前の人が 2 人いるときは、検索は推測せずにそう伝えます。間違えた名前は直せますし、どの修正も元に戻せます。

動画の探し方

動画は写真とは別に検索します。標準の検索は写真だけを対象にします。たとえば子どもが誕生日のろうそくを吹き消す動画を探したいなら、動画を探していると Comma にはっきり伝えると、検索に --source video を付けます。

sh
lpa search "blowing out candles" "birthday cake" --source video --json -n 9

裏では 3 つのステップがあります。

  1. フレームを切り出す。 動画そのものはモデルに入りません。インデックスのプログラムは動画から 5 秒ごとに 1 フレームを切り出し、1 本につき最大 12 フレームです。

  2. フレームで検索する。 切り出したフレームは写真と同じ処理を通ります。文字を認識し、2 種類のベクトルを計算します。検索はこれらのフレームを比べ、どれか 1 つが一致すれば動画全体が見つかったことになり、結果の中では 1 件だけを占めます。

  3. 動画を送る。 あなたが選んだら、エージェントが lpa video で動画を送ります。

Comma のチャット。陽朔で撮った竹いかだの動画を頼むと、Comma は堰を滑り降りるいかだの 12 秒の動画を 1 本返します。
動画検索の例。一致したフレームは 1 本の動画のものなので、その動画は 1 件の結果になります。

今は映像だけを見ていて、音は聞いていません。動画の中で話された言葉はまだ検索できず、動画に写った人もまだ認識できません。切り出すフレームの数には上限があるので、長い動画で一瞬だけ映るものは見つからないことがあります。

LocalPhotoAgent のしくみ

このガイドの lpa は、私たちが自分で書いたインデックスのプログラム LocalPhotoAgent から来ています。今後オープンソースにする予定です。インデックス作りの部分は前に説明したので、ここでは 2 点を補足します。

  • いつでも止められる。 各写真の各ステップを個別に記録するので、途中で止めても次回はその続きから進みます。設定を変えたときは、影響を受けるステップだけをやり直します。処理中はメモリ、温度、ディスクの空きを見ていて、上限を超えたらいったん止まります。

  • エージェントにいくつかのコマンドを渡す。 lpa search は検索、lpa sheet はコンタクトシートの作成、lpa preview は写真の送信、lpa video は動画の送信です。エージェントは写真を探すとき、次の順に呼び出します。

Comma のエージェントは Connector を通じて lpa search を実行し、確信がなければ lpa sheet、続いて lpa preview か lpa video で送ります。外付けドライブを読むのはシート作成と送信のときだけです Comma のエージェント Connector を通じてコマンドを実行 lpa search データベースだけを検索 lpa sheet 確信がないときにシートを作る lpa preview / video 写真か動画を送る 外付けドライブ サムネイルと元の写真。 読むのはシート作成と 送信のときだけ Comma のエージェントは Connector を通じて lpa search を実行し、確信がなければ lpa sheet、続いて lpa preview か lpa video で送ります。外付けドライブを読むのはシート作成と送信のときだけです Comma のエージェント Connector を通じてコマンドを実行 lpa search データベースだけを検索 lpa sheet 確信がないときにシートを作る lpa preview / video 写真か動画を送る 外付けドライブ サムネイルと元の写真。 読むのはシート作成と 送信のときだけ

Comma をつなぐ

LocalPhotoAgent がすでに Mac で動いていることが前提です。接続は 4 つのステップです。

  1. デバイスを追加する。 Comma の Settings > Devices で Add device をクリックし、インストール用のコマンドを受け取ります。

  2. コマンドを実行する。 ライブラリを置いた Mac のターミナルでそれを実行し、Comma Connector を入れます。

  3. 権限をオンにする。 新しいデバイスは最初 Off です。これを Full に変えると、エージェントが lpa を実行できるようになります。

  4. Skill を書く。 まず検索し、確信がなければコンタクトシートを送り、あなたが選んでから写真を送るよう、エージェントに伝えます。Comma に「Skill を作って」と頼むだけでもかまいません。

あとはいつものチャットと同じように尋ねるだけです。「去年撮った運転免許証の写真を探して。表と裏の両方。」

Comma のチャット。去年撮った運転免許証の写真を表と裏の両方頼むと、Comma は見本の免許証の写真を 2 枚送ります。
冒頭の質問への答えです。免許証は見本のカードです。

信頼と制限

インデックスは元の写真を読むだけで、移動、編集、削除はしません。検索は外付けドライブにまったく触れず、コンタクトシートを作るときと写真を送るときだけ読みます。写真の移動や削除はこの構成の範囲外です。ただし Full の権限にすると、エージェントがこの Mac で実行できるコマンドは lpa に限られません。

文字一致は、その文字が見つかったという意味でしかなく、それが欲しい写真だとは限りません。「可能性あり」は候補にすぎません。Comma が依頼を完了にしたら、送られてきた写真を確認してください。

最初に試すときは、こう言ってみてください。「去年撮った運転免許証の写真を探して。先にコンタクトシートを見せて、何も送ったり、移動したり、削除したりしないで。」

Try Comma, Now.

はじめる