model-service/model_service/views/svm_view.py

164 lines
5.5 KiB
Python
Raw Normal View History

2020-04-13 21:14:06 +02:00
#!/usr/bin/env python3
2020-04-14 13:48:11 +02:00
import tempfile
2020-04-14 17:03:15 +02:00
import os
2020-04-14 13:48:11 +02:00
from flask import request, jsonify, current_app, abort, Response
2020-04-13 21:14:06 +02:00
from flask_classful import FlaskView, route
2020-07-28 20:19:52 +02:00
from model import db, Default, AIModel, AIModelType, SVMDetails
from minio.error import NoSuchKey
2020-04-14 17:03:15 +02:00
from schemas import AIModelSchema, DefaultSchema, InfoSchema
2020-04-14 14:02:35 +02:00
from marshmallow.exceptions import ValidationError
2020-07-28 20:19:52 +02:00
from utils import json_required, storage, ensure_buckets
2020-04-14 17:03:15 +02:00
from pyAudioAnalysis.audioTrainTest import load_model, load_model_knn
2020-04-13 21:14:06 +02:00
2020-07-28 20:19:52 +02:00
class SVMView(FlaskView):
2020-04-14 13:48:11 +02:00
aimodel_schema = AIModelSchema(many=False)
2020-07-28 20:19:52 +02:00
aimodels_schema = AIModelSchema(many=True, exclude=['timestamp', 'details'])
2020-04-14 02:01:44 +02:00
default_schema = DefaultSchema(many=False)
2020-04-14 17:03:15 +02:00
info_schema = InfoSchema(many=False)
2020-04-14 19:42:43 +02:00
def index(self):
2020-07-28 20:19:52 +02:00
models = AIModel.query.filter_by(type=AIModelType.SVM).all()
2020-04-14 19:42:43 +02:00
return jsonify(self.aimodels_schema.dump(models)), 200
2020-04-13 21:14:06 +02:00
def post(self):
2020-04-14 17:03:15 +02:00
# get important data from the request
try:
info = self.info_schema.loads(request.form.get('info'))
except ValidationError as e:
abort(400, str(e))
# check for conflict
m = AIModel.query.filter_by(id=info['id']).first()
if m:
abort(409)
# get and validate file
model_file = request.files['modelFile']
if model_file.content_length <= 0:
abort(411, f"Content length for modelFile is not a positive integer or missing.")
means_file = request.files['meansFile']
if means_file.content_length <= 0:
abort(411, f"Content length for meansFile is not a positive integer or missing.")
# create bucket if necessary
2020-07-28 20:19:52 +02:00
ensure_buckets()
2020-04-14 17:03:15 +02:00
# Temporarily save the file, because pyAudioAnalysis can only read files
_, temp_model_filename = tempfile.mkstemp()
temp_means_filename = temp_model_filename + "MEANS"
model_file.save(temp_model_filename)
means_file.save(temp_means_filename)
try:
2020-07-28 20:19:52 +02:00
_, _, _, _, mid_window, mid_step, short_window, short_step, compute_beat \
= load_model(temp_model_filename)
2020-04-14 17:03:15 +02:00
# Because of pyAudiomeme the files already saved, so we just use the file uploader functions
storage.connection.fput_object(
2020-07-28 20:19:52 +02:00
current_app.config['MINIO_SVM_BUCKET_NAME'],
"model/" + str(info['id']),
2020-04-14 17:03:15 +02:00
temp_model_filename
)
storage.connection.fput_object(
2020-07-28 20:19:52 +02:00
current_app.config['MINIO_SVM_BUCKET_NAME'],
"means/" + str(info['id']),
2020-04-14 17:03:15 +02:00
temp_means_filename
)
finally:
os.remove(temp_model_filename)
os.remove(temp_means_filename)
2020-07-28 20:19:52 +02:00
m = AIModel(id=info['id'], type=AIModelType.SVM)
d = SVMDetails(
aimodel=m,
mid_window=mid_window,
mid_step=mid_step,
short_window=short_window,
short_step=short_step,
compute_beat=compute_beat
)
2020-04-14 17:03:15 +02:00
db.session.add(m)
2020-07-28 20:19:52 +02:00
db.session.add(d)
2020-04-14 17:03:15 +02:00
db.session.commit()
return jsonify(self.aimodel_schema.dump(m)), 200
2020-04-13 21:14:06 +02:00
def get(self, _id: str):
2020-04-14 13:48:11 +02:00
if _id == "$default":
2020-07-28 20:19:52 +02:00
# TODO: Kitalálni, hogy inkább a latestestest-el térjen-e vissza
default = Default.query.filter_by(type=AIModelType.SVM).first_or_404()
2020-04-14 19:42:43 +02:00
m = default.aimodel
else:
2020-07-28 20:19:52 +02:00
m = AIModel.query.filter_by(type=AIModelType.SVM, id=_id).first_or_404()
2020-04-14 19:42:43 +02:00
if "means" in request.args:
2020-07-28 20:19:52 +02:00
path = "means/" + str(m.id)
2020-04-14 13:48:11 +02:00
else:
2020-07-28 20:19:52 +02:00
path = "model/" + str(m.id)
2020-04-14 19:42:43 +02:00
try:
2020-07-28 20:19:52 +02:00
data = storage.connection.get_object(current_app.config['MINIO_SVM_BUCKET_NAME'], path)
2020-04-14 19:42:43 +02:00
except NoSuchKey:
abort(500, "The ID is stored in the database but not int the Object Store")
2020-04-14 13:48:11 +02:00
2020-04-14 19:42:43 +02:00
return Response(data.stream(), mimetype=data.headers['Content-type'])
2020-04-13 21:14:06 +02:00
@route('<_id>/details')
def get_details(self, _id: str):
2020-04-14 13:48:11 +02:00
if _id == "$default":
2020-07-28 20:19:52 +02:00
# TODO: Kitalálni, hogy inkább a latestestest-el térjen-e vissza
default = Default.query.filter_by(type=AIModelType.SVM).first_or_404()
2020-04-14 17:26:33 +02:00
m = default.aimodel
2020-04-14 13:48:11 +02:00
else:
2020-07-28 20:19:52 +02:00
m = AIModel.query.filter_by(type=AIModelType.SVM, id=_id).first_or_404()
2020-04-13 21:14:06 +02:00
2020-04-14 13:48:11 +02:00
return jsonify(self.aimodel_schema.dump(m))
2020-04-14 02:01:44 +02:00
2020-04-14 13:48:11 +02:00
def delete(self, _id: str):
2020-07-28 20:19:52 +02:00
if _id == "$default":
# TODO: Kitalálni, hogy inkább a latestestest-el térjen-e vissza
default = Default.query.filter_by(type=AIModelType.SVM).first_or_404()
2020-04-14 17:26:33 +02:00
m = default.aimodel
else:
2020-07-28 20:19:52 +02:00
m = AIModel.query.filter_by(type=AIModelType.SVM, id=_id).first_or_404()
2020-04-14 02:01:44 +02:00
2020-07-28 20:19:52 +02:00
storage.connection.remove_object(current_app.config['MINIO_SVM_BUCKET_NAME'], "means/" + str(m.id))
storage.connection.remove_object(current_app.config['MINIO_SVM_BUCKET_NAME'], "model/" + str(m.id))
2020-04-14 02:01:44 +02:00
2020-04-14 13:48:11 +02:00
db.session.delete(m)
2020-04-14 02:01:44 +02:00
db.session.commit()
2020-04-14 13:48:11 +02:00
return '', 204
@json_required
@route('$default', methods=['PUT'])
def put_default(self):
2020-04-14 14:02:35 +02:00
try:
2020-04-14 17:26:33 +02:00
req = self.default_schema.load(request.json)
2020-04-14 14:02:35 +02:00
except ValidationError as e:
2020-07-28 20:19:52 +02:00
abort(400, str(e))
2020-04-14 14:02:35 +02:00
2020-07-28 20:19:52 +02:00
m = AIModel.query.filter_by(type=AIModelType.SVM, id=req['id']).first_or_404()
2020-04-14 14:02:35 +02:00
2020-07-28 20:19:52 +02:00
Default.query.filter_by(type=AIModelType.SVM).delete()
new_default = Default(type=AIModelType.SVM, aimodel=m)
2020-04-14 14:02:35 +02:00
db.session.add(new_default)
db.session.commit()
2020-04-14 17:03:15 +02:00
return '', 204