diff --git a/src/api/agent_search.rs b/src/api/agent_search.rs index 64cedbc..e33d536 100644 --- a/src/api/agent_search.rs +++ b/src/api/agent_search.rs @@ -91,6 +91,7 @@ const SYSTEM_PROMPT: &str = r#"你是 Momentry 影片分析助手。回答用戶 ## 引導規則 - 如果用戶沒說片名 → 用 find_file 搜尋,如果名稱不明確就反問 - 反問時提供 suggestions,例如演員名、年代 +- **如果影片的 has_data 為 false,代表尚未完成處理,不要推薦用戶使用。引導用戶選擇 has_data=true 的影片** - 不要輸出 JSON,用自然語言回答 - 引用資料時附上具體數字(frame 編號、時間秒數) @@ -175,10 +176,14 @@ fn make_tools(pool: &sqlx::PgPool) -> Vec { async fn exec_find_file(pool: &sqlx::PgPool, args: &serde_json::Value) -> Result { let query = args.get("query").and_then(|v| v.as_str()).unwrap_or(""); let videos = schema::table_name("videos"); + let fd_table = schema::table_name("face_detections"); let like = format!("%{}%", query); - let rows: Vec<(String, String)> = sqlx::query_as(&format!( - "SELECT file_uuid::text, file_name FROM {} WHERE file_name ILIKE $1 ORDER BY created_at DESC LIMIT 10", - videos + let rows: Vec<(String, String, bool)> = sqlx::query_as(&format!( + "SELECT v.file_uuid::text, v.file_name, \ + (SELECT COUNT(*) FROM {} fd WHERE fd.file_uuid = v.file_uuid) > 0 AS has_data \ + FROM {} v WHERE v.file_name ILIKE $1 \ + ORDER BY v.created_at DESC LIMIT 10", + fd_table, videos )) .bind(&like) .fetch_all(pool) @@ -188,8 +193,8 @@ async fn exec_find_file(pool: &sqlx::PgPool, args: &serde_json::Value) -> Result if rows.is_empty() { return Ok(serde_json::json!({"found": false, "message": "No files match the query. Try different keywords."}).to_string()); } - let files: Vec = rows.into_iter().map(|(u, n)| { - serde_json::json!({"file_uuid": u, "file_name": n}) + let files: Vec = rows.into_iter().map(|(u, n, hd)| { + serde_json::json!({"file_uuid": u, "file_name": n, "has_data": hd}) }).collect(); Ok(serde_json::json!({"found": true, "files": files}).to_string()) } @@ -197,17 +202,20 @@ async fn exec_find_file(pool: &sqlx::PgPool, args: &serde_json::Value) -> Result async fn exec_list_files(pool: &sqlx::PgPool, args: &serde_json::Value) -> Result { let limit = args.get("limit").and_then(|v| v.as_i64()).unwrap_or(10); let videos = schema::table_name("videos"); - let rows: Vec<(String, String)> = sqlx::query_as(&format!( - "SELECT file_uuid::text, file_name FROM {} ORDER BY created_at DESC LIMIT $1", - videos + let fd_table = schema::table_name("face_detections"); + let rows: Vec<(String, String, bool)> = sqlx::query_as(&format!( + "SELECT v.file_uuid::text, v.file_name, \ + (SELECT COUNT(*) FROM {} fd WHERE fd.file_uuid = v.file_uuid) > 0 AS has_data \ + FROM {} v ORDER BY v.created_at DESC LIMIT $1", + fd_table, videos )) .bind(limit) .fetch_all(pool) .await .map_err(|e| e.to_string())?; - let files: Vec = rows.into_iter().map(|(u, n)| { - serde_json::json!({"file_uuid": u, "file_name": n}) + let files: Vec = rows.into_iter().map(|(u, n, hd)| { + serde_json::json!({"file_uuid": u, "file_name": n, "has_data": hd}) }).collect(); Ok(serde_json::json!({"files": files}).to_string()) }