Skip to content

Commit

Permalink
Integration with an internal training server (cvat-ai#2785)
Browse files Browse the repository at this point in the history
Co-authored-by: Boris Sekachev <boris.sekachev@intel.com>
Co-authored-by: Nikita Manovich <nikita.manovich@intel.com>
  • Loading branch information
3 people committed Apr 6, 2021
1 parent babf1a3 commit d2a1d12
Show file tree
Hide file tree
Showing 54 changed files with 1,743 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"python.pythonPath": ".env/bin/python",
"eslint.enable": true,
"eslint.probe": [
"javascript",
"typescript",
Expand Down
2 changes: 1 addition & 1 deletion cvat-core/src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ function build() {
* @param {module:API.cvat.classes.Task} task task to be annotated
* @param {module:API.cvat.classes.MLModel} model model used to get annotation
* @param {object} [args] extra arguments
* @returns {string} requestID
* @returns {object[]} annotations
* @throws {module:API.cvat.exceptions.ServerError}
* @throws {module:API.cvat.exceptions.PluginError}
* @throws {module:API.cvat.exceptions.ArgumentError}
Expand Down
23 changes: 23 additions & 0 deletions cvat-core/src/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
created_date: undefined,
updated_date: undefined,
task_subsets: undefined,
training_project: undefined,
};

for (const property in data) {
Expand Down Expand Up @@ -64,6 +65,9 @@
}
data.task_subsets = Array.from(subsetsSet);
}
if (initialData.training_project) {
data.training_project = JSON.parse(JSON.stringify(initialData.training_project));
}

Object.defineProperties(
this,
Expand Down Expand Up @@ -94,6 +98,7 @@
data.name = value;
},
},

/**
* @name status
* @type {module:API.cvat.enums.TaskStatus}
Expand Down Expand Up @@ -217,9 +222,21 @@
subsets: {
get: () => [...data.task_subsets],
},

_internalData: {
get: () => data,
},

training_project: {
get: () => data.training_project,
set: (training) => {
if (training) {
data.training_project = JSON.parse(JSON.stringify(training));
} else {
data.training_project = training;
}
},
},
}),
);
}
Expand Down Expand Up @@ -261,12 +278,17 @@
};

Project.prototype.save.implementation = async function () {
let trainingProject;
if (this.training_project) {
trainingProject = JSON.parse(JSON.stringify(this.training_project));
}
if (typeof this.id !== 'undefined') {
const projectData = {
name: this.name,
assignee_id: this.assignee ? this.assignee.id : null,
bug_tracker: this.bugTracker,
labels: [...this._internalData.labels.map((el) => el.toJSON())],
training_project: trainingProject,
};

await serverProxy.projects.save(this.id, projectData);
Expand All @@ -276,6 +298,7 @@
const projectSpec = {
name: this.name,
labels: [...this.labels.map((el) => el.toJSON())],
training_project: trainingProject,
};

if (this.bugTracker) {
Expand Down
123 changes: 123 additions & 0 deletions cvat-core/src/server-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,31 @@
const config = require('./config');
const DownloadWorker = require('./download.worker');

function waitFor(frequencyHz, predicate) {
return new Promise((resolve, reject) => {
if (typeof predicate !== 'function') {
reject(new Error(`Predicate must be a function, got ${typeof predicate}`));
}

const internalWait = () => {
let result = false;
try {
result = predicate();
} catch (error) {
reject(error);
}

if (result) {
resolve();
} else {
setTimeout(internalWait, 1000 / frequencyHz);
}
};

setTimeout(internalWait);
});
}

function generateError(errorData) {
if (errorData.response) {
const message = `${errorData.message}. ${JSON.stringify(errorData.response.data) || ''}.`;
Expand Down Expand Up @@ -993,6 +1018,96 @@
}
}

function predictorStatus(projectId) {
const { backendAPI } = config;

return new Promise((resolve, reject) => {
async function request() {
try {
const response = await Axios.get(`${backendAPI}/predict/status?project=${projectId}`);
return response.data;
} catch (errorData) {
throw generateError(errorData);
}
}

const timeoutCallback = async () => {
let data = null;
try {
data = await request();
if (data.status === 'queued') {
setTimeout(timeoutCallback, 1000);
} else if (data.status === 'done') {
resolve(data);
} else {
throw new Error(`Unknown status was received "${data.status}"`);
}
} catch (error) {
reject(error);
}
};

setTimeout(timeoutCallback);
});
}

function predictAnnotations(taskId, frame) {
return new Promise((resolve, reject) => {
const { backendAPI } = config;

async function request() {
try {
const response = await Axios.get(
`${backendAPI}/predict/frame?task=${taskId}&frame=${frame}`,
);
return response.data;
} catch (errorData) {
throw generateError(errorData);
}
}

const timeoutCallback = async () => {
let data = null;
try {
data = await request();
if (data.status === 'queued') {
setTimeout(timeoutCallback, 1000);
} else if (data.status === 'done') {
predictAnnotations.latestRequest.fetching = false;
resolve(data.annotation);
} else {
throw new Error(`Unknown status was received "${data.status}"`);
}
} catch (error) {
predictAnnotations.latestRequest.fetching = false;
reject(error);
}
};

const closureId = Date.now();
predictAnnotations.latestRequest.id = closureId;
const predicate = () => !predictAnnotations.latestRequest.fetching || predictAnnotations.latestRequest.id !== closureId;
if (predictAnnotations.latestRequest.fetching) {
waitFor(5, predicate).then(() => {
if (predictAnnotations.latestRequest.id !== closureId) {
resolve(null);
} else {
predictAnnotations.latestRequest.fetching = true;
setTimeout(timeoutCallback);
}
});
} else {
predictAnnotations.latestRequest.fetching = true;
setTimeout(timeoutCallback);
}
});
}

predictAnnotations.latestRequest = {
fetching: false,
id: null,
};

async function installedApps() {
const { backendAPI } = config;
try {
Expand Down Expand Up @@ -1123,6 +1238,14 @@
}),
writable: false,
},

predictor: {
value: Object.freeze({
status: predictorStatus,
predict: predictAnnotations,
}),
writable: false,
},
}),
);
}
Expand Down
Loading

0 comments on commit d2a1d12

Please sign in to comment.