diff --git a/mobile/lib/services/machine_learning/face_ml/face_ml_service.dart b/mobile/lib/services/machine_learning/face_ml/face_ml_service.dart index d88b8f041..6d3f8eec7 100644 --- a/mobile/lib/services/machine_learning/face_ml/face_ml_service.dart +++ b/mobile/lib/services/machine_learning/face_ml/face_ml_service.dart @@ -27,6 +27,7 @@ import "package:photos/models/file/extensions/file_props.dart"; import "package:photos/models/file/file.dart"; import "package:photos/models/file/file_type.dart"; import "package:photos/models/ml/ml_versions.dart"; +import "package:photos/service_locator.dart"; import 'package:photos/services/machine_learning/face_ml/face_clustering/face_clustering_service.dart'; import "package:photos/services/machine_learning/face_ml/face_clustering/face_info_for_clustering.dart"; import 'package:photos/services/machine_learning/face_ml/face_detection/detection.dart'; @@ -537,7 +538,8 @@ class FaceMlService { for (final f in chunk) { fileIds.add(f.uploadedFileID!); } - final EnteWatch? w = kDebugMode ? EnteWatch("face_em_fetch") : null; + final EnteWatch? w = + flagService.internalUser ? EnteWatch("face_em_fetch") : null; w?.start(); w?.log('starting remote fetch for ${fileIds.length} files'); final res = @@ -566,6 +568,16 @@ class FaceMlService { remoteFileIdToVersion[fileMl.fileID] = fileMl.faceEmbedding.version; } + if (res.noEmbeddingFileIDs.isNotEmpty) { + _logger.info( + 'No embeddings found for ${res.noEmbeddingFileIDs.length} files', + ); + for (final fileID in res.noEmbeddingFileIDs) { + faces.add(Face.empty(fileID, error: false)); + remoteFileIdToVersion[fileID] = faceMlVersion; + } + } + await FaceMLDataDB.instance.bulkInsertFaces(faces); w?.logAndReset('stored embeddings'); for (final entry in remoteFileIdToVersion.entries) { diff --git a/mobile/lib/services/machine_learning/file_ml/files_ml_data_response.dart b/mobile/lib/services/machine_learning/file_ml/files_ml_data_response.dart index 665e89b7e..475f52d0a 100644 --- a/mobile/lib/services/machine_learning/file_ml/files_ml_data_response.dart +++ b/mobile/lib/services/machine_learning/file_ml/files_ml_data_response.dart @@ -2,11 +2,18 @@ import 'package:photos/services/machine_learning/file_ml/file_ml.dart'; class FilesMLDataResponse { final Map mlData; - final Set notIndexedFileIds; - final Set fetchErrorFileIds; + // fileIDs that were indexed but they don't contain any meaningful embeddings + // and hence should be discarded for re-indexing + final Set noEmbeddingFileIDs; + // fetchErrorFileIDs are the fileIDs for whom we failed failed to fetch embeddings + // from the storage + final Set fetchErrorFileIDs; + // pendingIndexFileIDs are the fileIDs that were never indexed + final Set pendingIndexFileIDs; FilesMLDataResponse( this.mlData, { - required this.notIndexedFileIds, - required this.fetchErrorFileIds, + required this.noEmbeddingFileIDs, + required this.fetchErrorFileIDs, + required this.pendingIndexFileIDs, }); } diff --git a/mobile/lib/services/machine_learning/file_ml/remote_fileml_service.dart b/mobile/lib/services/machine_learning/file_ml/remote_fileml_service.dart index 95db6c381..3a8e383be 100644 --- a/mobile/lib/services/machine_learning/file_ml/remote_fileml_service.dart +++ b/mobile/lib/services/machine_learning/file_ml/remote_fileml_service.dart @@ -72,7 +72,8 @@ class RemoteFileMLService { }, ); final remoteEmb = res.data['embeddings'] as List; - final noFileIds = res.data['noDataFileIDs'] as List; + final pendingIndexFiles = res.data['pendingIndexFileIDs'] as List; + final noEmbeddingFiles = res.data['noEmbeddingFileIDs'] as List; final errFileIds = res.data['errFileIDs'] as List; final List remoteEmbeddings = []; @@ -81,13 +82,14 @@ class RemoteFileMLService { remoteEmbeddings.add(embedding); } - final notIndexedFileIds = Set.from(noFileIds.map((x) => x as int)); - final fetchErrorFileIds = Set.from(errFileIds.map((x) => x as int)); final fileIDToFileMl = await decryptFileMLData(remoteEmbeddings); return FilesMLDataResponse( fileIDToFileMl, - notIndexedFileIds: notIndexedFileIds, - fetchErrorFileIds: fetchErrorFileIds, + noEmbeddingFileIDs: + Set.from(noEmbeddingFiles.map((x) => x as int)), + fetchErrorFileIDs: Set.from(errFileIds.map((x) => x as int)), + pendingIndexFileIDs: + Set.from(pendingIndexFiles.map((x) => x as int)), ); } catch (e, s) { _logger.severe("Failed to get embeddings", e, s);