This commit is contained in:
		@@ -1,9 +1,10 @@
 | 
				
			|||||||
FROM python:3
 | 
					FROM python:3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADD classification_service requirements.txt /classification_service/
 | 
					ADD classification_service requirements.txt uwsgi.ini /classification_service/
 | 
				
			||||||
WORKDIR /classification_service/
 | 
					WORKDIR /classification_service/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUN pip3 install -r requirements.txt && pip3 install gunicorn
 | 
					RUN pip3 install -r requirements.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USER 33
 | 
				
			||||||
EXPOSE 8000
 | 
					EXPOSE 8000
 | 
				
			||||||
CMD ["gunicorn", "-b", "0.0.0.0:8000", "app:app"]
 | 
					CMD ["uwsgi", "--ini", "uwsgi.ini"]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,6 @@ from utils import register_all_error_handlers
 | 
				
			|||||||
# import views
 | 
					# import views
 | 
				
			||||||
from views import ClassifyView
 | 
					from views import ClassifyView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Setup sentry
 | 
					# Setup sentry
 | 
				
			||||||
SENTRY_DSN = os.environ.get("SENTRY_DSN")
 | 
					SENTRY_DSN = os.environ.get("SENTRY_DSN")
 | 
				
			||||||
if SENTRY_DSN:
 | 
					if SENTRY_DSN:
 | 
				
			||||||
@@ -36,7 +35,6 @@ register_all_error_handlers(app)
 | 
				
			|||||||
for view in [ClassifyView]:
 | 
					for view in [ClassifyView]:
 | 
				
			||||||
    view.register(app, trailing_slash=False)
 | 
					    view.register(app, trailing_slash=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
# start debugging if needed
 | 
					# start debugging if needed
 | 
				
			||||||
if __name__ == "__main__":
 | 
					if __name__ == "__main__":
 | 
				
			||||||
    app.run(debug=True)
 | 
					    app.run(debug=True)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										91
									
								
								classification_service/mule.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								classification_service/mule.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					import sentry_sdk
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import requests
 | 
				
			||||||
 | 
					import tempfile
 | 
				
			||||||
 | 
					import numpy
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					import pika
 | 
				
			||||||
 | 
					import uwsgi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pyAudioAnalysis.audioTrainTest import load_model, load_model_knn, classifier_wrapper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SENTRY_DSN = os.environ.get("SENTRY_DSN")
 | 
				
			||||||
 | 
					if SENTRY_DSN:
 | 
				
			||||||
 | 
					    sentry_sdk.init(
 | 
				
			||||||
 | 
					        dsn=SENTRY_DSN,
 | 
				
			||||||
 | 
					        send_default_pii=True,
 | 
				
			||||||
 | 
					        release=os.environ.get('RELEASE_ID', 'test'),
 | 
				
			||||||
 | 
					        environment=os.environ.get('RELEASEMODE', 'dev')
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def run_classification(task):
 | 
				
			||||||
 | 
					    _, temp_model_name = tempfile.mkstemp()
 | 
				
			||||||
 | 
					    temp_means_name = temp_model_name + "MEANS"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    r = requests.get(f"http://model-service/model/{task['model']}/details")
 | 
				
			||||||
 | 
					    r.raise_for_status()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    model_details = r.json()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        r = requests.get(f"http://model-service/model/{task['model']}")
 | 
				
			||||||
 | 
					        r.raise_for_status()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with open(temp_model_name, 'wb') as f:
 | 
				
			||||||
 | 
					            f.write(r.content)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        r = requests.get(f"http://model-service/model/{task['model']}?means")
 | 
				
			||||||
 | 
					        r.raise_for_status()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with open(temp_means_name, 'wb') as f:
 | 
				
			||||||
 | 
					            f.write(r.content)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if model_details['type'] == 'knn':
 | 
				
			||||||
 | 
					            classifier, mean, std, classes, mid_window, mid_step, short_window, short_step, compute_beat \
 | 
				
			||||||
 | 
					                = load_model_knn(temp_model_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            classifier, mean, std, classes, mid_window, mid_step, short_window, short_step, compute_beat \
 | 
				
			||||||
 | 
					                = load_model(temp_model_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        feature_vector = (numpy.array(task['features']) - mean) / std
 | 
				
			||||||
 | 
					        class_id, probability = classifier_wrapper(classifier, model_details['type'], feature_vector)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    finally:  # bruuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuh
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            os.remove(temp_model_name)
 | 
				
			||||||
 | 
					        except FileNotFoundError:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            os.remove(temp_means_name)
 | 
				
			||||||
 | 
					        except FileNotFoundError:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    results = {
 | 
				
			||||||
 | 
					        "tag": task['tag'],
 | 
				
			||||||
 | 
					        "model": task['model'],
 | 
				
			||||||
 | 
					        "class_id": class_id,
 | 
				
			||||||
 | 
					        "probability": probability
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return results
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    connection = pika.BlockingConnection(pika.connection.URLParameters(os.environ['PIKA_URL']))
 | 
				
			||||||
 | 
					    channel = connection.channel()
 | 
				
			||||||
 | 
					    channel.exchange_declare(exchange=os.environ['PIKA_EXCHANGE'], exchange_type='fanout')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while True:
 | 
				
			||||||
 | 
					        message = uwsgi.mule_get_msg()
 | 
				
			||||||
 | 
					        task = json.loads(message)
 | 
				
			||||||
 | 
					        results = run_classification(task)
 | 
				
			||||||
 | 
					        channel.basic_publish(exchange=os.environ['PIKA_EXCHANGE'], routing_key='classification-result', body=results)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
#!/usr/bin/env python3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import pika
 | 
					 | 
				
			||||||
from config import *
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
Rabbitmq setup
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__author__ = '@tormakris'
 | 
					 | 
				
			||||||
__copyright__ = "Copyright 2020, Birbnetes Team"
 | 
					 | 
				
			||||||
__module_name__ = "rabbit"
 | 
					 | 
				
			||||||
__version__text__ = "1"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
credentials = pika.PlainCredentials(RABBITMQ_USERNAME, RABBITMQ_PASSWORD)
 | 
					 | 
				
			||||||
rabbitmq = pika.BlockingConnection(pika.ConnectionParameters(host=RABBITMQ_HOST, credentials=credentials))
 | 
					 | 
				
			||||||
rabbitmq_channel = rabbitmq.channel()
 | 
					 | 
				
			||||||
rabbitmq_channel.exchange_declare(exchange=RABBITMQ_EXCHANGE, exchange_type='fanout')
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
"""Usage:
 | 
					 | 
				
			||||||
          from rabbit import rabbitmq_channel
 | 
					 | 
				
			||||||
 	      rabbitmq_channel.basic_publish(
 | 
					 | 
				
			||||||
            exchange=RABBITMQ_EXCHANGE,
 | 
					 | 
				
			||||||
            routing_key='feature',
 | 
					 | 
				
			||||||
            body=generated_tag)
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
#!/usr/bin/env python3
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
from flask import request, current_app, abort
 | 
					from flask import request, abort
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from functools import wraps
 | 
					from functools import wraps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,70 +1,15 @@
 | 
				
			|||||||
#!/usr/bin/env python3
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
from flask import request, jsonify
 | 
					from flask import request, jsonify
 | 
				
			||||||
from flask_classful import FlaskView
 | 
					from flask_classful import FlaskView
 | 
				
			||||||
from utils import json_required
 | 
					from utils import json_required
 | 
				
			||||||
import requests
 | 
					import json
 | 
				
			||||||
import tempfile
 | 
					import uwsgi
 | 
				
			||||||
import numpy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from pyAudioAnalysis.audioTrainTest import load_model, load_model_knn, classifier_wrapper
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClassifyView(FlaskView):
 | 
					class ClassifyView(FlaskView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @json_required
 | 
					    @json_required
 | 
				
			||||||
    def post(self):
 | 
					    def post(self):
 | 
				
			||||||
 | 
					 | 
				
			||||||
        task = request.json  # tag, features, model
 | 
					        task = request.json  # tag, features, model
 | 
				
			||||||
 | 
					        uwsgi.mule_msg(json.dumps(task))
 | 
				
			||||||
        _, temp_model_name = tempfile.mkstemp()
 | 
					 | 
				
			||||||
        temp_means_name = temp_model_name + "MEANS"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        r = requests.get(f"http://model-service/model/{task['model']}/details")
 | 
					 | 
				
			||||||
        r.raise_for_status()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        model_details = r.json()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            r = requests.get(f"http://model-service/model/{task['model']}")
 | 
					 | 
				
			||||||
            r.raise_for_status()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            with open(temp_model_name, 'wb') as f:
 | 
					 | 
				
			||||||
                f.write(r.content)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            r = requests.get(f"http://model-service/model/{task['model']}?means")
 | 
					 | 
				
			||||||
            r.raise_for_status()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            with open(temp_means_name, 'wb') as f:
 | 
					 | 
				
			||||||
                f.write(r.content)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if model_details['type'] == 'knn':
 | 
					 | 
				
			||||||
                classifier, mean, std, classes, mid_window, mid_step, short_window, short_step, compute_beat \
 | 
					 | 
				
			||||||
                    = load_model_knn(temp_model_name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                classifier, mean, std, classes, mid_window, mid_step, short_window, short_step, compute_beat \
 | 
					 | 
				
			||||||
                    = load_model(temp_model_name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            feature_vector = (numpy.array(task['features']) - mean) / std
 | 
					 | 
				
			||||||
            class_id, probability = classifier_wrapper(classifier, model_details['type'], feature_vector)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        finally:  # bruuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuh
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                os.remove(temp_model_name)
 | 
					 | 
				
			||||||
            except FileNotFoundError:
 | 
					 | 
				
			||||||
                pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                os.remove(temp_means_name)
 | 
					 | 
				
			||||||
            except FileNotFoundError:
 | 
					 | 
				
			||||||
                pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # TODO: Publish to message queue
 | 
					 | 
				
			||||||
        results = {
 | 
					 | 
				
			||||||
            "class_id": class_id,
 | 
					 | 
				
			||||||
            "probability": probability
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return jsonify({"status": "OK", "msg": "enqueued"})
 | 
					        return jsonify({"status": "OK", "msg": "enqueued"})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ marshmallow
 | 
				
			|||||||
Flask-Classful
 | 
					Flask-Classful
 | 
				
			||||||
sentry-sdk
 | 
					sentry-sdk
 | 
				
			||||||
pika
 | 
					pika
 | 
				
			||||||
 | 
					uwsgi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pyAudioanalysis
 | 
					pyAudioanalysis
 | 
				
			||||||
numpy
 | 
					numpy
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user