refactor: remove face embedding architecture - single Qdrant _faces collection

- Delete FaceEmbeddingDb module (face_embedding_db.rs)
- Stub match_faces_iterative, generate_seed_embeddings, tmdb_match_handler
- Remove sync_trace_embeddings, populate_face_embeddings_to_qdrant
- Remove embedding from face.json output (face_processor.py)
- Remove embedding from PG UPDATE (store_traced_faces.py)
- Remove workspace traces staging (checkin.rs, qdrant_workspace.rs)
- Fix tests: add pose_angle to Face, hand_nodes to TkgResult

Disabled functions (need reimplement with _faces):
- match_faces_iterative (identity agent)
- generate_seed_embeddings (TMDb seeds)
- tmdb_match_handler (TMDb matching)
- cluster_face_embeddings, search_similar_faces
- merge_traces_within_cuts
This commit is contained in:
Accusys
2026-06-24 22:27:09 +08:00
parent 360cb991e1
commit 074cdcdbed
60 changed files with 657 additions and 9454 deletions
+32 -29
View File
@@ -67,11 +67,13 @@ pub async fn bind_identity(
Path(identity_uuid): Path<String>,
Json(req): Json<BindIdentityRequest>,
) -> Result<Json<ApiResponse<serde_json::Value>>, (StatusCode, Json<serde_json::Value>)> {
tracing::info!("[bind_identity] req: {:?}", req);
let table = crate::core::db::schema::table_name("face_detections");
let id_table = crate::core::db::schema::table_name("identities");
let history_table = crate::core::db::schema::table_name("identity_history");
let uuid_clean = identity_uuid.replace('-', "");
tracing::info!("[bind_identity] uuid_clean={}, expand_to_trace={:?}", uuid_clean, req.expand_to_trace);
let identity_row: Option<(i32, String)> = sqlx::query_as(&format!(
"SELECT id, name FROM {} WHERE REPLACE(uuid::text, '-', '') = $1",
id_table
@@ -188,21 +190,32 @@ pub async fn bind_identity(
})?
.flatten();
// Update Qdrant + TKG if trace_id exists
if let Some(tid) = trace_id {
// 1. Update Qdrant payload
let face_db = crate::core::db::FaceEmbeddingDb::new();
if let Err(e) = face_db
.update_identity_by_trace(&req.file_uuid, tid, &uuid_clean)
.await
{
tracing::warn!(
"[bind] Failed to update Qdrant identity_uuid for trace {}: {}",
tid, e
);
// Expand to entire trace if requested
tracing::info!("[bind_identity] trace_id={:?}, expand_to_trace={:?}", trace_id, req.expand_to_trace);
if req.expand_to_trace.unwrap_or(false) && trace_id.is_some() {
let tid = trace_id.unwrap();
tracing::info!("[bind_identity] Expanding to trace {} for file {}", tid, req.file_uuid);
let expand_result = sqlx::query(&format!(
"UPDATE {} SET identity_id = $1 WHERE file_uuid = $2 AND trace_id = $3",
table
))
.bind(identity_id)
.bind(&req.file_uuid)
.bind(tid)
.execute(state.db.pool())
.await;
if let Ok(r) = expand_result {
tracing::info!("[bind] Expanded to trace {}: {} rows", tid, r.rows_affected());
} else {
tracing::error!("[bind] Failed to expand to trace {}: {:?}", tid, expand_result.err());
}
} else {
tracing::info!("[bind_identity] NOT expanding: expand_to_trace={:?}, trace_id={:?}", req.expand_to_trace, trace_id);
}
// 2. Update TKG face_track node (dual-field design)
// Update TKG if trace_id exists
if let Some(tid) = trace_id {
// Update TKG face_track node (dual-field design)
let tkg_table = crate::core::db::schema::table_name("tkg_nodes");
let ext_id = format!("face_track_{}", tid);
let identity_ref = format!("{}:identity_{}", req.file_uuid, identity_id);
@@ -380,21 +393,9 @@ pub async fn unbind_identity(
})?
.flatten();
// Clear Qdrant + TKG if trace_id exists
// Clear TKG if trace_id exists
if let Some(tid) = trace_id {
// 1. Clear Qdrant payload
let face_db = crate::core::db::FaceEmbeddingDb::new();
if let Err(e) = face_db
.clear_identity_by_trace(&req.file_uuid, tid)
.await
{
tracing::warn!(
"[unbind] Failed to clear Qdrant identity_uuid for trace {}: {}",
tid, e
);
}
// 2. Update TKG face_track node (restore stranger_ref)
// Update TKG face_track node (restore stranger_ref)
let tkg_table = crate::core::db::schema::table_name("tkg_nodes");
let ext_id = format!("face_track_{}", tid);
let stranger_ref = format!("{}:stranger_trace_{}", req.file_uuid, tid);
@@ -2199,8 +2200,10 @@ pub async fn list_pending_persons(
let fd_table = crate::core::db::schema::table_name("face_detections");
let rows: Vec<(i32, String, String, chrono::NaiveDateTime)> = sqlx::query_as(&format!(
"SELECT id, uuid::text, name, created_at FROM {} WHERE file_uuid = $1 AND status = 'pending' ORDER BY created_at DESC",
id_table
"SELECT DISTINCT i.id, i.uuid::text, i.name, i.created_at FROM {} i \
JOIN {} fd ON fd.identity_id = i.id \
WHERE fd.file_uuid = $1 AND i.status = 'pending' ORDER BY i.created_at DESC",
id_table, fd_table
))
.bind(&file_uuid)
.fetch_all(state.db.pool())