diff --git a/myproject/docker-compose.yml b/myproject/docker-compose.yml
index 646ed6edf7373383aaeadede99e06f9863a8b147..976121da56f2d023d43a325fd7948e21340ea351 100644
--- a/myproject/docker-compose.yml
+++ b/myproject/docker-compose.yml
@@ -19,6 +19,7 @@ services:
     volumes:
       - .:/usr/src/app
       - static_volume:/usr/src/app/static
+      - ./models:/usr/src/app/models
     depends_on:
       - db
       - tensorflow_serving
diff --git a/myproject/models/instrument_model/1/fingerprint.pb b/myproject/models/instrument_model/1/fingerprint.pb
deleted file mode 100644
index 141b4c1792009ca22145b9f5ba9c01ed66ce207c..0000000000000000000000000000000000000000
--- a/myproject/models/instrument_model/1/fingerprint.pb
+++ /dev/null
@@ -1 +0,0 @@
-؋���������ס�ȭ��ʏ����� �Ԛ���ʘ�(����Ǜ	2
\ No newline at end of file
diff --git a/myproject/models/instrument_model/1/keras_metadata.pb b/myproject/models/instrument_model/1/keras_metadata.pb
index 4d889d7af020adb530b97500ddd438adb64c68a7..17c52e5f3ac95836f44215e4d16ccc8403689e22 100644
--- a/myproject/models/instrument_model/1/keras_metadata.pb
+++ b/myproject/models/instrument_model/1/keras_metadata.pb
@@ -1,7 +1,7 @@
 
-�\root"_tf_keras_sequential*�\{"name": "sequential", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": false, "class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "conv2d_input"}}, {"class_name": "Conv2D", "config": {"name": "conv2d", "trainable": true, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "filters": 32, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}}, {"class_name": "Dropout", "config": {"name": "dropout", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}}, {"class_name": "Conv2D", "config": {"name": "conv2d_1", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_1", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}}, {"class_name": "Dropout", "config": {"name": "dropout_1", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}}, {"class_name": "Conv2D", "config": {"name": "conv2d_2", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Flatten", "config": {"name": "flatten", "trainable": true, "dtype": "float32", "data_format": "channels_last"}}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 64, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dropout", "config": {"name": "dropout_2", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 32, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_2", "trainable": true, "dtype": "float32", "units": 4, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "shared_object_id": 25, "input_spec": [{"class_name": "InputSpec", "config": {"dtype": null, "shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}}], "build_input_shape": {"class_name": "TensorShape", "items": [null, 128, 44, 1]}, "is_graph_network": true, "full_save_spec": {"class_name": "__tuple__", "items": [[{"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 128, 44, 1]}, "float32", "conv2d_input"]}], {}]}, "save_spec": {"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 128, 44, 1]}, "float32", "conv2d_input"]}, "keras_version": "2.15.0", "backend": "tensorflow", "model_config": {"class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "conv2d_input"}, "shared_object_id": 0}, {"class_name": "Conv2D", "config": {"name": "conv2d", "trainable": true, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "filters": 32, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 1}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 2}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 3}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "shared_object_id": 4}, {"class_name": "Dropout", "config": {"name": "dropout", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 5}, {"class_name": "Conv2D", "config": {"name": "conv2d_1", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 6}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 7}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 8}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_1", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "shared_object_id": 9}, {"class_name": "Dropout", "config": {"name": "dropout_1", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 10}, {"class_name": "Conv2D", "config": {"name": "conv2d_2", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 11}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 12}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 13}, {"class_name": "Flatten", "config": {"name": "flatten", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "shared_object_id": 14}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 64, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 15}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 16}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 17}, {"class_name": "Dropout", "config": {"name": "dropout_2", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 18}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 32, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 19}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 20}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 21}, {"class_name": "Dense", "config": {"name": "dense_2", "trainable": true, "dtype": "float32", "units": 4, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 22}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 23}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 24}]}}, "training_config": {"loss": {"class_name": "SparseCategoricalCrossentropy", "config": {"reduction": "auto", "name": "sparse_categorical_crossentropy", "from_logits": true, "ignore_class": null, "fn": "sparse_categorical_crossentropy"}, "shared_object_id": 27}, "metrics": [[{"class_name": "MeanMetricWrapper", "config": {"name": "accuracy", "dtype": "float32", "fn": "sparse_categorical_accuracy"}, "shared_object_id": 28}]], "weighted_metrics": null, "loss_weights": null, "optimizer_config": {"class_name": "Adam", "config": {"name": "Adam", "learning_rate": 0.0010000000474974513, "decay": 0.0, "beta_1": 0.8999999761581421, "beta_2": 0.9990000128746033, "epsilon": 1e-07, "amsgrad": false}}}}2
+�\root"_tf_keras_sequential*�\{"name": "sequential", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": false, "class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "conv2d_input"}}, {"class_name": "Conv2D", "config": {"name": "conv2d", "trainable": true, "batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "dtype": "float32", "filters": 32, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}}, {"class_name": "Dropout", "config": {"name": "dropout", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}}, {"class_name": "Conv2D", "config": {"name": "conv2d_1", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_1", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}}, {"class_name": "Dropout", "config": {"name": "dropout_1", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}}, {"class_name": "Conv2D", "config": {"name": "conv2d_2", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Flatten", "config": {"name": "flatten", "trainable": true, "dtype": "float32", "data_format": "channels_last"}}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 64, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dropout", "config": {"name": "dropout_2", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 32, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_2", "trainable": true, "dtype": "float32", "units": 4, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "shared_object_id": 25, "input_spec": [{"class_name": "InputSpec", "config": {"dtype": null, "shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}}], "build_input_shape": {"class_name": "TensorShape", "items": [null, 128, 44, 1]}, "is_graph_network": true, "full_save_spec": {"class_name": "__tuple__", "items": [[{"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 128, 44, 1]}, "float32", "conv2d_input"]}], {}]}, "save_spec": {"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 128, 44, 1]}, "float32", "conv2d_input"]}, "keras_version": "2.10.0", "backend": "tensorflow", "model_config": {"class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "conv2d_input"}, "shared_object_id": 0}, {"class_name": "Conv2D", "config": {"name": "conv2d", "trainable": true, "batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "dtype": "float32", "filters": 32, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 1}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 2}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 3}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "shared_object_id": 4}, {"class_name": "Dropout", "config": {"name": "dropout", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 5}, {"class_name": "Conv2D", "config": {"name": "conv2d_1", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 6}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 7}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 8}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_1", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "shared_object_id": 9}, {"class_name": "Dropout", "config": {"name": "dropout_1", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 10}, {"class_name": "Conv2D", "config": {"name": "conv2d_2", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 11}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 12}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 13}, {"class_name": "Flatten", "config": {"name": "flatten", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "shared_object_id": 14}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 64, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 15}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 16}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 17}, {"class_name": "Dropout", "config": {"name": "dropout_2", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 18}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 32, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 19}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 20}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 21}, {"class_name": "Dense", "config": {"name": "dense_2", "trainable": true, "dtype": "float32", "units": 4, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 22}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 23}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 24}]}}, "training_config": {"loss": {"class_name": "SparseCategoricalCrossentropy", "config": {"reduction": "auto", "name": "sparse_categorical_crossentropy", "from_logits": true, "ignore_class": null}, "shared_object_id": 27}, "metrics": [[{"class_name": "MeanMetricWrapper", "config": {"name": "accuracy", "dtype": "float32", "fn": "sparse_categorical_accuracy"}, "shared_object_id": 28}]], "weighted_metrics": null, "loss_weights": null, "optimizer_config": {"class_name": "Adam", "config": {"name": "Adam", "learning_rate": 0.0010000000474974513, "decay": 0.0, "beta_1": 0.8999999761581421, "beta_2": 0.9990000128746033, "epsilon": 1e-07, "amsgrad": false}}}}2
 �root.layer_with_weights-0"_tf_keras_layer*�
-{"name": "conv2d", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Conv2D", "config": {"name": "conv2d", "trainable": true, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "filters": 32, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 1}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 2}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 3, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 4, "axes": {"-1": 1}}, "shared_object_id": 29}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128, 44, 1]}}2
+{"name": "conv2d", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Conv2D", "config": {"name": "conv2d", "trainable": true, "batch_input_shape": {"class_name": "__tuple__", "items": [null, 128, 44, 1]}, "dtype": "float32", "filters": 32, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "valid", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 1}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 2}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 3, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 4, "axes": {"-1": 1}}, "shared_object_id": 29}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128, 44, 1]}}2
 �root.layer-1"_tf_keras_layer*�{"name": "max_pooling2d", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "MaxPooling2D", "config": {"name": "max_pooling2d", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "shared_object_id": 4, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}, "shared_object_id": 30}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 126, 42, 32]}}2
 �root.layer-2"_tf_keras_layer*�{"name": "dropout", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Dropout", "config": {"name": "dropout", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 5, "build_input_shape": {"class_name": "TensorShape", "items": [null, 63, 21, 32]}}2
 �
@@ -16,5 +16,5 @@
 root.layer-9"_tf_keras_layer*�{"name": "dropout_2", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Dropout", "config": {"name": "dropout_2", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "shared_object_id": 18, "build_input_shape": {"class_name": "TensorShape", "items": [null, 64]}}2
 �root.layer_with_weights-4"_tf_keras_layer*�{"name": "dense_1", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 32, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 19}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 20}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 21, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 64}}, "shared_object_id": 36}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 64]}}2
 �root.layer_with_weights-5"_tf_keras_layer*�{"name": "dense_2", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Dense", "config": {"name": "dense_2", "trainable": true, "dtype": "float32", "units": 4, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 22}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 23}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 24, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 32}}, "shared_object_id": 37}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 32]}}2
-��root.keras_api.metrics.0"_tf_keras_metric*�{"class_name": "Mean", "name": "loss", "dtype": "float32", "config": {"name": "loss", "dtype": "float32"}, "shared_object_id": 38}2
-��root.keras_api.metrics.1"_tf_keras_metric*�{"class_name": "MeanMetricWrapper", "name": "accuracy", "dtype": "float32", "config": {"name": "accuracy", "dtype": "float32", "fn": "sparse_categorical_accuracy"}, "shared_object_id": 28}2
\ No newline at end of file
+��root.keras_api.metrics.0"_tf_keras_metric*�{"class_name": "Mean", "name": "loss", "dtype": "float32", "config": {"name": "loss", "dtype": "float32"}, "shared_object_id": 38}2
+��root.keras_api.metrics.1"_tf_keras_metric*�{"class_name": "MeanMetricWrapper", "name": "accuracy", "dtype": "float32", "config": {"name": "accuracy", "dtype": "float32", "fn": "sparse_categorical_accuracy"}, "shared_object_id": 28}2
\ No newline at end of file
diff --git a/myproject/models/instrument_model/1/saved_model.pb b/myproject/models/instrument_model/1/saved_model.pb
index 17ff0d94c083b07b5eb7f1a9348cfb36fa15d532..334a4f1e41dcb57d38aabfc36e2e0af32608617f 100644
Binary files a/myproject/models/instrument_model/1/saved_model.pb and b/myproject/models/instrument_model/1/saved_model.pb differ
diff --git a/myproject/models/instrument_model/1/variables/variables.data-00000-of-00001 b/myproject/models/instrument_model/1/variables/variables.data-00000-of-00001
index ad1698fc39af144e83ea1bf207d1908eb51d22c4..6535da5d890975b1eaa6fc5060823c7a6d1018ed 100644
Binary files a/myproject/models/instrument_model/1/variables/variables.data-00000-of-00001 and b/myproject/models/instrument_model/1/variables/variables.data-00000-of-00001 differ
diff --git a/myproject/models/instrument_model/1/variables/variables.index b/myproject/models/instrument_model/1/variables/variables.index
index 6a8d3e1a107e9ba3b6a210b1af5d176f97f9ef14..28f23f1867b3715a930109b4857a14a0756441ef 100644
Binary files a/myproject/models/instrument_model/1/variables/variables.index and b/myproject/models/instrument_model/1/variables/variables.index differ
diff --git a/myproject/myapp/migrations/0002_modelconfig.py b/myproject/myapp/migrations/0002_modelconfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc16f7a5eda2b34e9d8219d77e9c5c2820e59a04
--- /dev/null
+++ b/myproject/myapp/migrations/0002_modelconfig.py
@@ -0,0 +1,20 @@
+# Generated by Django 5.0.1 on 2024-04-30 23:25
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('myapp', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='ModelConfig',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('selected_model_version', models.CharField(default='2', max_length=255)),
+            ],
+        ),
+    ]
diff --git a/myproject/myapp/migrations/0003_modelperformancemetrics.py b/myproject/myapp/migrations/0003_modelperformancemetrics.py
new file mode 100644
index 0000000000000000000000000000000000000000..bbaaf929c12d6ca636204521578361f546fef8ba
--- /dev/null
+++ b/myproject/myapp/migrations/0003_modelperformancemetrics.py
@@ -0,0 +1,25 @@
+# Generated by Django 5.0.1 on 2024-05-01 00:07
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('myapp', '0002_modelconfig'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='ModelPerformanceMetrics',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('request_count', models.IntegerField(default=0)),
+                ('request_latency_sum', models.FloatField(default=0)),
+                ('request_latency_count', models.IntegerField(default=0)),
+                ('runtime_latency_sum', models.FloatField(default=0)),
+                ('runtime_latency_count', models.IntegerField(default=0)),
+                ('model_load_latency', models.FloatField(default=0)),
+            ],
+        ),
+    ]
diff --git a/myproject/myapp/migrations/0004_payment.py b/myproject/myapp/migrations/0004_payment.py
new file mode 100644
index 0000000000000000000000000000000000000000..1e06945e7015f4dbcd1d774d1e6e1b6a4c2a2b61
--- /dev/null
+++ b/myproject/myapp/migrations/0004_payment.py
@@ -0,0 +1,27 @@
+# Generated by Django 5.0.1 on 2024-05-01 00:39
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('myapp', '0003_modelperformancemetrics'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Payment',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('amount', models.DecimalField(decimal_places=2, max_digits=10)),
+                ('payment_id', models.CharField(max_length=255)),
+                ('payer_id', models.CharField(max_length=255)),
+                ('date', models.DateTimeField(auto_now_add=True)),
+                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/myproject/myapp/models.py b/myproject/myapp/models.py
index 326123a737d7ef7aca00446c56a78ff39684017b..a67236e7fa208922c551b56bb7d1b251c14fd2ff 100644
--- a/myproject/myapp/models.py
+++ b/myproject/myapp/models.py
@@ -57,3 +57,43 @@ class Log(models.Model):
     log = models.JSONField()
     feedback = models.BooleanField(null=True)
 
+class ModelConfig(models.Model):
+    selected_model_version = models.CharField(max_length=255, default='2')
+
+    def save(self, *args, **kwargs):
+        # Ensure there's only one instance of ModelConfig
+        self.pk = 1
+        super().save(*args, **kwargs)
+
+    @classmethod
+    def load(cls):
+        obj, _ = cls.objects.get_or_create(pk=1)
+        return obj
+
+class ModelPerformanceMetrics(models.Model):
+    request_count = models.IntegerField(default=0)
+    request_latency_sum = models.FloatField(default=0)
+    request_latency_count = models.IntegerField(default=0)
+    runtime_latency_sum = models.FloatField(default=0)
+    runtime_latency_count = models.IntegerField(default=0)
+    model_load_latency = models.FloatField(default=0)
+
+    def reset_metrics(self):
+        self.request_count = 0
+        self.request_latency_sum = 0
+        self.request_latency_count = 0
+        self.runtime_latency_sum = 0
+        self.runtime_latency_count = 0
+        self.model_load_latency = 0
+        self.save(force_update=True)
+
+class Payment(models.Model):
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    amount = models.DecimalField(max_digits=10, decimal_places=2)
+    payment_id = models.CharField(max_length=255)
+    payer_id = models.CharField(max_length=255)
+    date = models.DateTimeField(auto_now_add=True)
+    
+    def __str__(self):
+        return f'Payment by {self.user.username} - Amount: {self.amount}'
+
diff --git a/myproject/myapp/payments.py b/myproject/myapp/payments.py
index dd8e0026c63867cf88788ec2b0979647e3b6c11b..b1108fd9e985622974b0b69dfa042f426da12ac8 100644
--- a/myproject/myapp/payments.py
+++ b/myproject/myapp/payments.py
@@ -5,6 +5,7 @@ from django.shortcuts import redirect, render
 from django.urls import reverse
 from django.shortcuts import redirect, render
 from django.urls import reverse
+from .models import Action, UserTokenCount, Payment
 from .views import get_log_data, create_log
 from .models import UserTokenCount, Action
 from rest_framework.response import Response
@@ -82,12 +83,56 @@ def create_payment(request, purchase_type):
 
 
 # Execute a successful payment
+# def execute_payment(request):
+#     # Get payment id and payer id
+#     payment_id = request.GET.get('paymentId')
+#     payer_id = request.GET.get('PayerID')
+
+#     #If neither ID, error, restart
+#     if not payment_id or not payer_id:
+#         print("no payment")
+#         #TODO: Change this to a more appropriate path, maybe a generic error page that takes a string:Error to display in a template
+#         return redirect('handler404')
+
+#     # configure API
+#     paypalrestsdk.configure({
+#         "mode": settings.PAYPAL_MODE,
+#         "client_id": settings.PAYPAL_CLIENT_ID,
+#         "client_secret": settings.PAYPAL_CLIENT_SECRET
+#     })
+
+#     # Check we've got a successful payment
+#     payment = paypalrestsdk.Payment.find(payment_id)
+
+#     # If it we do an the payer IDs match
+#     if payment.execute({"payer_id": payer_id}):
+#         print("Payment executed successfully!")
+
+#         # Allocate some tokens
+#         user = request.user
+#         tokens_purchased = 1
+
+#         # increment user_tokens
+#         # commit changes
+#         # TODO: Change something here such that the token amount added depends on a detail of the transaction,
+#         #       i.e. £9.99 payment for one token or £24.99 for
+#         #
+#         if request.user.is_authenticated:
+#             add_tokens(user, tokens_purchased)
+#             return redirect('success')
+#         else:
+#             return redirect('handler404')
+#     else:
+#         #TODO: Change this to a more appropriate error message
+#         print("exiting at the end of execute_payment()")
+#         return redirect('handler404')
+
 def execute_payment(request):
     # Get payment id and payer id
     payment_id = request.GET.get('paymentId')
     payer_id = request.GET.get('PayerID')
 
-    #If neither ID, error, restart
+    # If neither ID, error, restart
     if not payment_id or not payer_id:
         print("no payment id or payer_id")
         return Response({"error": "Error: No payment id or payer id was found."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@@ -102,7 +147,7 @@ def execute_payment(request):
     # Check we've got a successful payment
     payment = paypalrestsdk.Payment.find(payment_id)
 
-    # If it we do an the payer IDs match
+    # If it we do and the payer IDs match
     if payment.execute({"payer_id": payer_id}):
         print("Payment executed successfully!")
         print(f"Payment: {payment}")
@@ -124,7 +169,6 @@ def execute_payment(request):
         print("exiting at the end of execute_payment(), incorrect payer id")
         return Response({"error": "Error: Payment failed to execute, incorrect payer id"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
 
-
 def add_tokens(user, tokens):
     token_count_instance, created = UserTokenCount.objects.get_or_create(user=user)
     token_count_instance.token_count += int(tokens)
diff --git a/myproject/myapp/templates/model_performance.html b/myproject/myapp/templates/model_performance.html
index 493a96fefbcdd6400b46e9557fba667aa6001aae..30d0227a9162012986db987ee01335e57d991cd3 100644
--- a/myproject/myapp/templates/model_performance.html
+++ b/myproject/myapp/templates/model_performance.html
@@ -1,18 +1,26 @@
+<!-- model_performance.html -->
 {% extends "_base.html" %}
 
 {% block content %}
 <div class="container mx-auto px-4">
-  <h1 class="text-2xl font-bold mb-4">Model Performance</h1>
-  
-  {% if metrics %}
+    <h1 class="text-2xl font-bold mb-4">Model Performance</h1>
+
+    {% if metrics %}
     <div class="bg-white shadow-md rounded p-6">
-      <p><strong>Request Count:</strong> {{ metrics.request_count }}</p>
-      <p><strong>Average Request Latency:</strong> {{ metrics.avg_request_latency|floatformat:6 }} seconds</p>
-      <p><strong>Average Runtime Latency:</strong> {{ metrics.avg_runtime_latency|floatformat:6 }} seconds</p>
-      <p><strong>Model Load Latency:</strong> {{ metrics.model_load_latency|floatformat:6 }} seconds</p>
+        <p><strong>Request Count:</strong> {{ metrics.request_count }}</p>
+        <p><strong>Average Request Latency:</strong> {{ metrics.avg_request_latency|floatformat:6 }} seconds</p>
+        <p><strong>Average Runtime Latency:</strong> {{ metrics.avg_runtime_latency|floatformat:6 }} seconds</p>
+        <p><strong>Model Load Latency:</strong> {{ metrics.model_load_latency|floatformat:6 }} seconds</p>
     </div>
-  {% else %}
+    {% else %}
     <p>Failed to retrieve model performance metrics.</p>
-  {% endif %}
+    {% endif %}
+
+    <form method="post" action="{% url 'model_performance' %}" class="mt-4">
+        {% csrf_token %}
+        <button type="submit" name="reset_metrics" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+            Reset Metrics
+        </button>
+    </form>
 </div>
 {% endblock content %}
\ No newline at end of file
diff --git a/myproject/myapp/templates/model_selection.html b/myproject/myapp/templates/model_selection.html
new file mode 100644
index 0000000000000000000000000000000000000000..d14c882f552a27e1260ecb0641f247918004229b
--- /dev/null
+++ b/myproject/myapp/templates/model_selection.html
@@ -0,0 +1,15 @@
+{% extends '_base.html' %}
+
+{% block content %}
+  <h1>Model Version Selection</h1>
+  <form method="post">
+    {% csrf_token %}
+    <label for="model_version">Select Model Version:</label>
+    <select name="model_version" id="model_version">
+      {% for version in model_versions %}
+        <option value="{{ version }}" {% if selected_model_version == version %}selected{% endif %}>{{ version }}</option>
+      {% endfor %}
+    </select>
+    <button type="submit">Save</button>
+  </form>
+{% endblock %}
\ No newline at end of file
diff --git a/myproject/myapp/templates/user_page.html b/myproject/myapp/templates/user_page.html
index 94fff4c7e67ee2c07c291645b76abd1283521393..987c029969c603ccae4006aaed7ba29cd5c26af4 100644
--- a/myproject/myapp/templates/user_page.html
+++ b/myproject/myapp/templates/user_page.html
@@ -1,4 +1,6 @@
-{% extends "_base.html" %} {% block content %}
+<!-- user_page.html -->
+{% extends "_base.html" %} 
+{% block content %}
 <div
   class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-grey-300"
 >
@@ -33,7 +35,13 @@
       <h3 class="mb-4 text-xl font-semibold dark:text-white">Change your password</h3>
       <a href="{% url 'password_change' %}" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Change Password</a>
     </div>
-
+    
+    {% if user_profile.user_type == 2 or user.is_superuser %}
+    <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
+      <h3 class="mb-4 text-xl font-semibold dark:text-white">Model Selection</h3>
+      <a href="{% url 'model_selection' %}" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Select Model</a>
+    </div>
+    {% endif %}
 
     {% if user_profile.user_type == 3 or user.is_superuser or user_profile.user_type == 1%}
     <div
diff --git a/myproject/myapp/urls.py b/myproject/myapp/urls.py
index 6a58000925a139ce144b37b3bffe66981948f90a..a7c38d019e636e988f655430977fb3a3eca36243 100644
--- a/myproject/myapp/urls.py
+++ b/myproject/myapp/urls.py
@@ -1,5 +1,5 @@
 from django.urls import path
-from .views import InstrumentDetectionView, ModelPerformanceView, index, log_fileupload, users, maintenance, \
+from .views import InstrumentDetectionView, ModelPerformanceView, ModelSelectionView, index, log_fileupload, users, maintenance, \
 handler404, handler500, terms_conditions, privacy_policy, pricing, generate_pdf, admin_table,\
       change_user_type, submit_feedback
 from .payments import create_payment, execute_payment, payment_cancelled, payment_success
@@ -26,6 +26,7 @@ urlpatterns = [
     path('generate_pdf/', generate_pdf, name='generate_pdf'),
     path('instrument_detection/', InstrumentDetectionView.as_view(), name='instrument_detection'),
     path('model_performance/', ModelPerformanceView.as_view(), name='model_performance'),
+    path('model_selection/', ModelSelectionView.as_view(), name='model_selection'),
     path('password_change/', auth_views.PasswordChangeView.as_view(template_name='password_change_form.html'), name='password_change'),
     path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'), name='password_change_done'),
 
diff --git a/myproject/myapp/views.py b/myproject/myapp/views.py
index f89359211c1c844ac595562a1a452dee9ecffbd0..e65ac6c9f5be9c7e24b166b5748322c5aaa0721a 100644
--- a/myproject/myapp/views.py
+++ b/myproject/myapp/views.py
@@ -1,3 +1,5 @@
+# views.py
+import os
 from django.contrib.auth import authenticate, login, logout
 from django.contrib.auth.forms import UserCreationForm
 from django.contrib.auth.models import User
@@ -12,7 +14,7 @@ import json
 from datetime import datetime
 
 from .forms import InstrumentDetectionForm
-from .models import Log, Action, User, UserTokenCount, Profile
+from .models import Log, Action, User, UserTokenCount, Profile, ModelConfig, ModelPerformanceMetrics
 from django.http import JsonResponse
 from django.db import connection
 
@@ -26,8 +28,8 @@ import requests
 
 # Authentication Imports
 from django.urls import reverse_lazy
-from django.views import generic
-from .models import Profile
+from django.views import View, generic
+from .models import Profile, ModelConfig
 from .forms import UserRegisterForm, LoginAuthenticationForm
 from django.contrib.auth.views import LoginView
 from django.views.decorators.csrf import csrf_exempt
@@ -370,42 +372,50 @@ class InstrumentDetectionView(APIView):
         else: return super().dispatch(request, *args, **kwargs)
     
     def post(self, request):
-        # Get the user's token count
-        user_token_count = UserTokenCount.objects.get(user=request.user)
-
-        # Decrease the user's token count by one
-        user_token_count.token_count -= 1
-        user_token_count.save()
-
-        serializer = InstrumentDetectionSerializer(data=request.data)
-        if serializer.is_valid():
-            audio_file = serializer.validated_data['audio_file']
-
-            # Save the uploaded file temporarily
-            # with open('temp_audio.wav', 'wb') as f:
-            #     f.write(audio_file.read())
-
-            # Preprocess the audio file
-            preprocessed_data = preprocess_audio_for_inference(audio_file)
-
-            # Prepare data for TensorFlow Serving
-            data = json.dumps({"signature_name": "serving_default", "instances": [window.tolist() for window in preprocessed_data]})
-
-            # Send request to TensorFlow Serving
-            url = 'http://tensorflow_serving:8501/v1/models/instrument_model/versions/2:predict'
-            headers = {"Content-Type": "application/json"}
-            response = requests.post(url, data=data, headers=headers)
-
-            # Process the response
-            if response.status_code == 200:
-                raw_predictions = response.json()['predictions']
-                # Convert raw prediction numbers into percentages
-                formatted_predictions = self.format_predictions(raw_predictions)
-                return Response({"predictions": formatted_predictions}, status=status.HTTP_200_OK)
-            else:
-                return Response({"error": "Failed to get predictions"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
-
-        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+        try:
+            model_config = ModelConfig.load()
+            selected_model_version = model_config.selected_model_version
+            # Get the user's token count
+            user_token_count = UserTokenCount.objects.get(user=request.user)
+
+            # Decrease the user's token count by one
+            user_token_count.token_count -= 1
+            user_token_count.save()
+
+            serializer = InstrumentDetectionSerializer(data=request.data)
+            if serializer.is_valid():
+                audio_file = serializer.validated_data['audio_file']
+
+                # Save the uploaded file temporarily
+                # with open('temp_audio.wav', 'wb') as f:
+                #     f.write(audio_file.read())
+
+                # Preprocess the audio file
+                preprocessed_data = preprocess_audio_for_inference(audio_file)
+
+                # Prepare data for TensorFlow Serving
+                data = json.dumps({"signature_name": "serving_default", "instances": [window.tolist() for window in preprocessed_data]})
+
+                # Send request to TensorFlow Serving
+                # url = 'http://tensorflow_serving:8501/v1/models/instrument_model/versions/2:predict'
+                url = f'http://tensorflow_serving:8501/v1/models/instrument_model/versions/{selected_model_version}:predict'
+                headers = {"Content-Type": "application/json"}
+                response = requests.post(url, data=data, headers=headers)
+
+                # Process the response
+                if response.status_code == 200:
+                    print('Predictions received')
+                    raw_predictions = response.json()['predictions']
+                    # Convert raw prediction numbers into percentages
+                    formatted_predictions = self.format_predictions(raw_predictions)
+                    return Response({"predictions": formatted_predictions}, status=status.HTTP_200_OK)
+                else:
+                    return Response({"error": "Failed to get predictions"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+        except Exception as e:
+            logger.error(f"An error occurred: {e}")
+            messages.error(request, 'An error occurred: {e}')
+            return redirect('index')
 
 
     def format_predictions(self, predictions):
@@ -433,10 +443,10 @@ class ModelPerformanceView(UserPassesTestMixin, TemplateView):
 
     def dispatch(self, request, *args, **kwargs):
         if request.user.is_anonymous:
-            messages.info(request, 'Must be logged in as an ML Engineer or Admin to access this page.')
+            messages.info(request, 'Must be logged in as an ML Engineer or Superuser to access this page.')
             return redirect('login')
         elif request.user.profile.user_type != 2 and not request.user.is_superuser:
-            messages.info(request, 'Must be logged in as an ML Engineer or Admin to access this page.')
+            messages.info(request, 'Must be logged in as an ML Engineer or Superuser to access this page.')
             return redirect('users')
         else:
             return super().dispatch(request, *args, **kwargs)
@@ -461,21 +471,73 @@ class ModelPerformanceView(UserPassesTestMixin, TemplateView):
             runtime_latency_count = re.search(r':tensorflow:serving:runtime_latency_count{model_name="instrument_model",API="Predict",runtime="TF1"} (\d+)', metrics_data)
             model_load_latency = re.search(r':tensorflow:cc:saved_model:load_latency{model_path="/models/instrument_model/2"} (\d+)', metrics_data)
 
+            # Get or create the ModelPerformanceMetrics instance
+            metrics, _ = ModelPerformanceMetrics.objects.get_or_create(pk=1)
+
+            # Update the metrics in the database
+            metrics.request_count = int(request_count.group(1)) if request_count else 0
+            metrics.request_latency_sum = float(request_latency_sum.group(1)) if request_latency_sum else 0
+            metrics.request_latency_count = int(request_latency_count.group(1)) if request_latency_count else 0
+            metrics.runtime_latency_sum = float(runtime_latency_sum.group(1)) if runtime_latency_sum else 0
+            metrics.runtime_latency_count = int(runtime_latency_count.group(1)) if runtime_latency_count else 0
+            metrics.model_load_latency = float(model_load_latency.group(1)) if model_load_latency else 0
+            metrics.save()
+
             # Calculate average latencies in seconds
-            avg_request_latency = float(request_latency_sum.group(1)) / float(request_latency_count.group(1)) / 1e6 if request_latency_sum and request_latency_count else None
-            avg_runtime_latency = float(runtime_latency_sum.group(1)) / float(runtime_latency_count.group(1)) / 1e6 if runtime_latency_sum and runtime_latency_count else None
-            model_load_latency_seconds = float(model_load_latency.group(1)) / 1e6 if model_load_latency else None
+            avg_request_latency = metrics.request_latency_sum / metrics.request_latency_count / 1e6 if metrics.request_latency_count else None
+            avg_runtime_latency = metrics.runtime_latency_sum / metrics.runtime_latency_count / 1e6 if metrics.runtime_latency_count else None
 
             context['metrics'] = {
-                'request_count': request_count.group(1) if request_count else None,
+                'request_count': metrics.request_count,
                 'avg_request_latency': avg_request_latency,
                 'avg_runtime_latency': avg_runtime_latency,
-                'model_load_latency': model_load_latency_seconds
+                'model_load_latency': metrics.model_load_latency / 1e6
             }
         else:
             context['metrics'] = None
 
         return context
+    def post(self, request, *args, **kwargs):
+        if 'reset_metrics' in request.POST:
+            metrics = ModelPerformanceMetrics.objects.get(pk=1)
+            metrics.reset_metrics()
+            metrics.save()
+            return redirect('users')
+        else:
+            messages.error(request, 'Invalid request')
+            return redirect('users')
+
+class ModelSelectionView(UserPassesTestMixin, View):
+    def dispatch(self, request, *args, **kwargs):
+        if request.user.is_anonymous:
+            messages.info(request, 'Must be logged in as an ML Engineer or Superuser to access this page.')
+            return redirect('login')
+        elif request.user.profile.user_type != 2 and not request.user.is_superuser:
+            messages.info(request, 'Must be logged in as an ML Engineer or Superuser to access this page.')
+            return redirect('users')
+        else:
+            return super().dispatch(request, *args, **kwargs)
+
+    def test_func(self):
+        return self.request.user.is_authenticated and self.request.user.profile.user_type == 2
+
+    def get(self, request):
+        model_versions = os.listdir('models/instrument_model')
+        model_config = ModelConfig.load()
+        context = {
+            'model_versions': model_versions,
+            'selected_model_version': model_config.selected_model_version,
+        }
+        return render(request, 'model_selection.html', context)
+
+    def post(self, request):
+        selected_model_version = request.POST.get('model_version')
+        model_config = ModelConfig.load()
+        model_config.selected_model_version = selected_model_version
+        model_config.save()
+        return redirect('model_selection')
+    
+
 
 def change_user_type(request, user_id):
     if request.method == 'POST':
@@ -487,7 +549,4 @@ def change_user_type(request, user_id):
 
 def user_has_credits():
     has_credits = False
-
-
-
     return has_credits