Inline
This commit is contained in:
parent
0a713eb98f
commit
a4981ec244
5 changed files with 188 additions and 198 deletions
|
@ -7,6 +7,7 @@ import HTTPService from "@ente/shared/network/HTTPService";
|
|||
import { getEndpoint } from "@ente/shared/network/api";
|
||||
import localForage from "@ente/shared/storage/localForage";
|
||||
import { getToken } from "@ente/shared/storage/localStorage/helpers";
|
||||
import { FileML } from "services/machineLearning/machineLearningService";
|
||||
import type {
|
||||
Embedding,
|
||||
EmbeddingModel,
|
||||
|
@ -15,11 +16,6 @@ import type {
|
|||
PutEmbeddingRequest,
|
||||
} from "types/embedding";
|
||||
import { EnteFile } from "types/file";
|
||||
import {
|
||||
getLatestVersionEmbeddings,
|
||||
getLatestVersionFileEmbeddings,
|
||||
} from "utils/embedding";
|
||||
import { FileML } from "utils/machineLearning/mldataMappers";
|
||||
import { getLocalCollections } from "./collectionService";
|
||||
import { getAllLocalFiles } from "./fileService";
|
||||
import { getLocalTrashedFiles } from "./trashService";
|
||||
|
@ -241,6 +237,40 @@ export const syncFileEmbeddings = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const getLatestVersionEmbeddings = (embeddings: Embedding[]) => {
|
||||
const latestVersionEntities = new Map<number, Embedding>();
|
||||
embeddings.forEach((embedding) => {
|
||||
if (!embedding?.fileID) {
|
||||
return;
|
||||
}
|
||||
const existingEmbeddings = latestVersionEntities.get(embedding.fileID);
|
||||
if (
|
||||
!existingEmbeddings ||
|
||||
existingEmbeddings.updatedAt < embedding.updatedAt
|
||||
) {
|
||||
latestVersionEntities.set(embedding.fileID, embedding);
|
||||
}
|
||||
});
|
||||
return Array.from(latestVersionEntities.values());
|
||||
};
|
||||
|
||||
const getLatestVersionFileEmbeddings = (embeddings: FileML[]) => {
|
||||
const latestVersionEntities = new Map<number, FileML>();
|
||||
embeddings.forEach((embedding) => {
|
||||
if (!embedding?.fileID) {
|
||||
return;
|
||||
}
|
||||
const existingEmbeddings = latestVersionEntities.get(embedding.fileID);
|
||||
if (
|
||||
!existingEmbeddings ||
|
||||
existingEmbeddings.updatedAt < embedding.updatedAt
|
||||
) {
|
||||
latestVersionEntities.set(embedding.fileID, embedding);
|
||||
}
|
||||
});
|
||||
return Array.from(latestVersionEntities.values());
|
||||
};
|
||||
|
||||
export const getEmbeddingsDiff = async (
|
||||
sinceTime: number,
|
||||
model: EmbeddingModel,
|
||||
|
|
|
@ -7,6 +7,10 @@ import downloadManager from "services/download";
|
|||
import { putEmbedding } from "services/embeddingService";
|
||||
import { getLocalFiles } from "services/fileService";
|
||||
import {
|
||||
ClipEmbedding,
|
||||
Face,
|
||||
FaceDetection,
|
||||
Landmark,
|
||||
MLSyncContext,
|
||||
MLSyncFileContext,
|
||||
MLSyncResult,
|
||||
|
@ -14,7 +18,6 @@ import {
|
|||
} from "services/ml/types";
|
||||
import { EnteFile } from "types/file";
|
||||
import { getMLSyncConfig } from "utils/machineLearning/config";
|
||||
import { LocalFileMlDataToServerFileMl } from "utils/machineLearning/mldataMappers";
|
||||
import mlIDbStorage from "utils/storage/mlIDbStorage";
|
||||
import FaceService from "./faceService";
|
||||
import { MLFactory } from "./machineLearningFactory";
|
||||
|
@ -445,3 +448,152 @@ class MachineLearningService {
|
|||
}
|
||||
|
||||
export default new MachineLearningService();
|
||||
|
||||
export interface FileML extends ServerFileMl {
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
class ServerFileMl {
|
||||
public fileID: number;
|
||||
public height?: number;
|
||||
public width?: number;
|
||||
public faceEmbedding: ServerFaceEmbeddings;
|
||||
public clipEmbedding?: ClipEmbedding;
|
||||
|
||||
public constructor(
|
||||
fileID: number,
|
||||
faceEmbedding: ServerFaceEmbeddings,
|
||||
clipEmbedding?: ClipEmbedding,
|
||||
height?: number,
|
||||
width?: number,
|
||||
) {
|
||||
this.fileID = fileID;
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.faceEmbedding = faceEmbedding;
|
||||
this.clipEmbedding = clipEmbedding;
|
||||
}
|
||||
}
|
||||
|
||||
class ServerFaceEmbeddings {
|
||||
public faces: ServerFace[];
|
||||
public version: number;
|
||||
public client?: string;
|
||||
public error?: boolean;
|
||||
|
||||
public constructor(
|
||||
faces: ServerFace[],
|
||||
version: number,
|
||||
client?: string,
|
||||
error?: boolean,
|
||||
) {
|
||||
this.faces = faces;
|
||||
this.version = version;
|
||||
this.client = client;
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
|
||||
class ServerFace {
|
||||
public faceID: string;
|
||||
public embeddings: number[];
|
||||
public detection: ServerDetection;
|
||||
public score: number;
|
||||
public blur: number;
|
||||
|
||||
public constructor(
|
||||
faceID: string,
|
||||
embeddings: number[],
|
||||
detection: ServerDetection,
|
||||
score: number,
|
||||
blur: number,
|
||||
) {
|
||||
this.faceID = faceID;
|
||||
this.embeddings = embeddings;
|
||||
this.detection = detection;
|
||||
this.score = score;
|
||||
this.blur = blur;
|
||||
}
|
||||
}
|
||||
|
||||
class ServerDetection {
|
||||
public box: ServerFaceBox;
|
||||
public landmarks: Landmark[];
|
||||
|
||||
public constructor(box: ServerFaceBox, landmarks: Landmark[]) {
|
||||
this.box = box;
|
||||
this.landmarks = landmarks;
|
||||
}
|
||||
}
|
||||
|
||||
class ServerFaceBox {
|
||||
public xMin: number;
|
||||
public yMin: number;
|
||||
public width: number;
|
||||
public height: number;
|
||||
|
||||
public constructor(
|
||||
xMin: number,
|
||||
yMin: number,
|
||||
width: number,
|
||||
height: number,
|
||||
) {
|
||||
this.xMin = xMin;
|
||||
this.yMin = yMin;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
function LocalFileMlDataToServerFileMl(
|
||||
localFileMlData: MlFileData,
|
||||
): ServerFileMl {
|
||||
if (
|
||||
localFileMlData.errorCount > 0 &&
|
||||
localFileMlData.lastErrorMessage !== undefined
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const imageDimensions = localFileMlData.imageDimensions;
|
||||
|
||||
const faces: ServerFace[] = [];
|
||||
for (let i = 0; i < localFileMlData.faces.length; i++) {
|
||||
const face: Face = localFileMlData.faces[i];
|
||||
const faceID = face.id;
|
||||
const embedding = face.embedding;
|
||||
const score = face.detection.probability;
|
||||
const blur = face.blurValue;
|
||||
const detection: FaceDetection = face.detection;
|
||||
const box = detection.box;
|
||||
const landmarks = detection.landmarks;
|
||||
const newBox = new ServerFaceBox(box.x, box.y, box.width, box.height);
|
||||
const newLandmarks: Landmark[] = [];
|
||||
for (let j = 0; j < landmarks.length; j++) {
|
||||
newLandmarks.push({
|
||||
x: landmarks[j].x,
|
||||
y: landmarks[j].y,
|
||||
} as Landmark);
|
||||
}
|
||||
|
||||
const newFaceObject = new ServerFace(
|
||||
faceID,
|
||||
Array.from(embedding),
|
||||
new ServerDetection(newBox, newLandmarks),
|
||||
score,
|
||||
blur,
|
||||
);
|
||||
faces.push(newFaceObject);
|
||||
}
|
||||
const faceEmbeddings = new ServerFaceEmbeddings(
|
||||
faces,
|
||||
1,
|
||||
localFileMlData.lastErrorMessage,
|
||||
);
|
||||
return new ServerFileMl(
|
||||
localFileMlData.fileId,
|
||||
faceEmbeddings,
|
||||
undefined,
|
||||
imageDimensions.height,
|
||||
imageDimensions.width,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
import { Embedding } from "types/embedding";
|
||||
import { FileML } from "./machineLearning/mldataMappers";
|
||||
|
||||
export const getLatestVersionEmbeddings = (embeddings: Embedding[]) => {
|
||||
const latestVersionEntities = new Map<number, Embedding>();
|
||||
embeddings.forEach((embedding) => {
|
||||
if (!embedding?.fileID) {
|
||||
return;
|
||||
}
|
||||
const existingEmbeddings = latestVersionEntities.get(embedding.fileID);
|
||||
if (
|
||||
!existingEmbeddings ||
|
||||
existingEmbeddings.updatedAt < embedding.updatedAt
|
||||
) {
|
||||
latestVersionEntities.set(embedding.fileID, embedding);
|
||||
}
|
||||
});
|
||||
return Array.from(latestVersionEntities.values());
|
||||
};
|
||||
|
||||
export const getLatestVersionFileEmbeddings = (embeddings: FileML[]) => {
|
||||
const latestVersionEntities = new Map<number, FileML>();
|
||||
embeddings.forEach((embedding) => {
|
||||
if (!embedding?.fileID) {
|
||||
return;
|
||||
}
|
||||
const existingEmbeddings = latestVersionEntities.get(embedding.fileID);
|
||||
if (
|
||||
!existingEmbeddings ||
|
||||
existingEmbeddings.updatedAt < embedding.updatedAt
|
||||
) {
|
||||
latestVersionEntities.set(embedding.fileID, embedding);
|
||||
}
|
||||
});
|
||||
return Array.from(latestVersionEntities.values());
|
||||
};
|
|
@ -1,156 +0,0 @@
|
|||
import {
|
||||
ClipEmbedding,
|
||||
Face,
|
||||
FaceDetection,
|
||||
Landmark,
|
||||
MlFileData,
|
||||
} from "services/ml/types";
|
||||
|
||||
export interface FileML extends ServerFileMl {
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
class ServerFileMl {
|
||||
public fileID: number;
|
||||
public height?: number;
|
||||
public width?: number;
|
||||
public faceEmbedding: ServerFaceEmbeddings;
|
||||
public clipEmbedding?: ClipEmbedding;
|
||||
|
||||
public constructor(
|
||||
fileID: number,
|
||||
faceEmbedding: ServerFaceEmbeddings,
|
||||
clipEmbedding?: ClipEmbedding,
|
||||
height?: number,
|
||||
width?: number,
|
||||
) {
|
||||
this.fileID = fileID;
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.faceEmbedding = faceEmbedding;
|
||||
this.clipEmbedding = clipEmbedding;
|
||||
}
|
||||
}
|
||||
|
||||
class ServerFaceEmbeddings {
|
||||
public faces: ServerFace[];
|
||||
public version: number;
|
||||
public client?: string;
|
||||
public error?: boolean;
|
||||
|
||||
public constructor(
|
||||
faces: ServerFace[],
|
||||
version: number,
|
||||
client?: string,
|
||||
error?: boolean,
|
||||
) {
|
||||
this.faces = faces;
|
||||
this.version = version;
|
||||
this.client = client;
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
|
||||
class ServerFace {
|
||||
public faceID: string;
|
||||
public embeddings: number[];
|
||||
public detection: ServerDetection;
|
||||
public score: number;
|
||||
public blur: number;
|
||||
|
||||
public constructor(
|
||||
faceID: string,
|
||||
embeddings: number[],
|
||||
detection: ServerDetection,
|
||||
score: number,
|
||||
blur: number,
|
||||
) {
|
||||
this.faceID = faceID;
|
||||
this.embeddings = embeddings;
|
||||
this.detection = detection;
|
||||
this.score = score;
|
||||
this.blur = blur;
|
||||
}
|
||||
}
|
||||
|
||||
class ServerDetection {
|
||||
public box: ServerFaceBox;
|
||||
public landmarks: Landmark[];
|
||||
|
||||
public constructor(box: ServerFaceBox, landmarks: Landmark[]) {
|
||||
this.box = box;
|
||||
this.landmarks = landmarks;
|
||||
}
|
||||
}
|
||||
|
||||
class ServerFaceBox {
|
||||
public xMin: number;
|
||||
public yMin: number;
|
||||
public width: number;
|
||||
public height: number;
|
||||
|
||||
public constructor(
|
||||
xMin: number,
|
||||
yMin: number,
|
||||
width: number,
|
||||
height: number,
|
||||
) {
|
||||
this.xMin = xMin;
|
||||
this.yMin = yMin;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
export function LocalFileMlDataToServerFileMl(
|
||||
localFileMlData: MlFileData,
|
||||
): ServerFileMl {
|
||||
if (
|
||||
localFileMlData.errorCount > 0 &&
|
||||
localFileMlData.lastErrorMessage !== undefined
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const imageDimensions = localFileMlData.imageDimensions;
|
||||
|
||||
const faces: ServerFace[] = [];
|
||||
for (let i = 0; i < localFileMlData.faces.length; i++) {
|
||||
const face: Face = localFileMlData.faces[i];
|
||||
const faceID = face.id;
|
||||
const embedding = face.embedding;
|
||||
const score = face.detection.probability;
|
||||
const blur = face.blurValue;
|
||||
const detection: FaceDetection = face.detection;
|
||||
const box = detection.box;
|
||||
const landmarks = detection.landmarks;
|
||||
const newBox = new ServerFaceBox(box.x, box.y, box.width, box.height);
|
||||
const newLandmarks: Landmark[] = [];
|
||||
for (let j = 0; j < landmarks.length; j++) {
|
||||
newLandmarks.push({
|
||||
x: landmarks[j].x,
|
||||
y: landmarks[j].y,
|
||||
} as Landmark);
|
||||
}
|
||||
|
||||
const newFaceObject = new ServerFace(
|
||||
faceID,
|
||||
Array.from(embedding),
|
||||
new ServerDetection(newBox, newLandmarks),
|
||||
score,
|
||||
blur,
|
||||
);
|
||||
faces.push(newFaceObject);
|
||||
}
|
||||
const faceEmbeddings = new ServerFaceEmbeddings(
|
||||
faces,
|
||||
1,
|
||||
localFileMlData.lastErrorMessage,
|
||||
);
|
||||
return new ServerFileMl(
|
||||
localFileMlData.fileId,
|
||||
faceEmbeddings,
|
||||
undefined,
|
||||
imageDimensions.height,
|
||||
imageDimensions.width,
|
||||
);
|
||||
}
|
Loading…
Add table
Reference in a new issue