Skip to content

[Crop][CCIP] 画像領域単位の特徴量抽出・類似検索を実装する #618

Description

@hmjn023

Parent: #612

Depends on: #615, #617, #620

背景

現行CCIPはmediaごとに1 embeddingを持ち、全体画像同士だけを検索する。人物crop単位で抽出・検索しながら、結果はユーザーが扱う親mediaへ集約する必要がある。また「同一人物」のthresholdを裸の定数にすると、model・前処理・metric更新時に意味が変わる。

設計方針

  • 全体画像は kind=full、cropはbbox付きregionとして同じembedding基盤を使う
  • 検索scopeは原則 full → fullcrop → crop に分ける
  • pgvector cosineで候補取得後、既存Rust CCIP distanceで再rankingする
  • 同じ親mediaの複数regionは最良distanceの1件へ集約し、重複排除後にtopKを適用する
  • responseへmatched region/bbox、cosine distance、CCIP distanceを含める
  • boolean判定を行う場合、thresholdをmodel・embedding version・region kind・render profile・policy versionと一緒に管理する

スコープ

  • region対応の抽出/status/stale判定/API schema
  • full/crop類似検索、親media集約、検索UI
  • model/version/revision別の再抽出
  • version付きthreshold policyと適用policyの追跡

非スコープ

受け入れ条件

  • full検索とcrop検索のscopeが混在しない
  • 同一親mediaの複数cropは最良match 1件になる
  • bbox・元画像・model更新後はembeddingがstaleになる
  • responseからmatched regionと使用policyを追跡できる
  • 既存の全体画像検索とRust再rankingを維持する
  • server/Tauri共通の検索状態・UI契約を維持する

主な参照

  • packages/application/src/services/ccip-vector-service.ts:153
  • packages/application/src/ports/ccip-vector-store.ts:1
  • apps/server/src/infrastructure/ai/rust-ai-client.ts:247
  • apps/server/src/infrastructure/api/routers/media-router.ts:56
  • packages/ui/src/hooks/use-search-page.ts:176

評価反映(2026-07-18)

Status・依存関係

本IssueはDeferred / Experimentalとし、今回のPostgres + pgvector移行およびLanceDB cutoverの完了条件には含めない。

#620ではregionを対象にできるprocessing-state基盤、revision、claim token、retry/fencingを先に確立する。crop CCIPの実際の抽出・検索を#620の初期完了条件にはせず、本Issueでその基盤を使用して実装する。

再開条件

次を満たすまで実装を開始しない。

  • #617のregion lifecycle、idempotency、source revision更新時の扱いが実データで安定している
  • #620でregion taskのatomic claim、heartbeat、retry、requested/completed revision、lost-lease fencingが利用できる
  • 誤検出、小領域、遮蔽、複数人物を含む評価セットが用意されている
  • region kind、coverage、score、model/version、render profile別の抽出対象とthreshold評価方法が定義されている
  • 同じ親mediaに属する複数regionの集約・tie・topK規則が固定されている

full embeddingは置換せず維持する。crop embeddingは、複数人物またはfull画像と十分異なるなど、評価で有用と判断されたregionだけを対象にする。

Capacity / performance gate

2026-07-18時点では画像mediaが88,184件あり、768次元vectorをfull画像へ1件ずつ保存した場合でもvector payloadだけで概算約259MiBとなる。cropは1 media対複数件となるため、bulk抽出を有効にする前に件数・容量・検索性能を再計測する。

再開時に次のgateを追加する。

  • mediaあたりregion数の分布と、抽出対象policy適用後の総embedding件数を見積もる
  • exact cosineについてsource/kind/model/version filter込みのp50/p95/p99、同時実行時のDB負荷、WAL・storage増加を計測する
  • bulk抽出throughputと再抽出時の所要時間を計測する
  • 合意したSLOをexact検索で満たさない場合だけHNSW/IVFFlatを比較し、top-K recallと親media集約後の結果を評価する
  • 最大region数、topK、検索scope、bulk concurrencyに運用上限を設ける

Rollout

実装後もexperimental flag配下で開始し、既定検索はfull → fullのまま維持する。評価セット、capacity gate、server/Tauri parityを満たしてからcrop検索を利用可能にする。

追加受け入れ条件

  • #620のregion processing-stateを使用し、generic jobへ新たに依存しない
  • full embeddingを維持し、有用性policyを満たすcropだけを抽出する
  • 評価セット上で抽出policy・threshold・親media集約の指標を記録する
  • bulk有効化前にcapacity/performance gateを通過する
  • experimental flag無効時は既存full検索の挙動が変化しない
  • server/Tauriで検索scope・結果集約・matched region表示が一致する

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions