Parent: #612
Depends on: #615, #617, #620
背景
現行CCIPはmediaごとに1 embeddingを持ち、全体画像同士だけを検索する。人物crop単位で抽出・検索しながら、結果はユーザーが扱う親mediaへ集約する必要がある。また「同一人物」のthresholdを裸の定数にすると、model・前処理・metric更新時に意味が変わる。
設計方針
- 全体画像は
kind=full、cropはbbox付きregionとして同じembedding基盤を使う
- 検索scopeは原則
full → full と crop → 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の追跡
非スコープ
受け入れ条件
主な参照
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検索を利用可能にする。
追加受け入れ条件
Parent: #612
Depends on: #615, #617, #620
背景
現行CCIPはmediaごとに1 embeddingを持ち、全体画像同士だけを検索する。人物crop単位で抽出・検索しながら、結果はユーザーが扱う親mediaへ集約する必要がある。また「同一人物」のthresholdを裸の定数にすると、model・前処理・metric更新時に意味が変わる。
設計方針
kind=full、cropはbbox付きregionとして同じembedding基盤を使うfull → fullとcrop → cropに分けるスコープ
非スコープ
受け入れ条件
主な参照
packages/application/src/services/ccip-vector-service.ts:153packages/application/src/ports/ccip-vector-store.ts:1apps/server/src/infrastructure/ai/rust-ai-client.ts:247apps/server/src/infrastructure/api/routers/media-router.ts:56packages/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でその基盤を使用して実装する。
再開条件
次を満たすまで実装を開始しない。
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を追加する。
Rollout
実装後もexperimental flag配下で開始し、既定検索はfull → fullのまま維持する。評価セット、capacity gate、server/Tauri parityを満たしてからcrop検索を利用可能にする。
追加受け入れ条件