We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Reject predict(POST) API call if JSON payload is not properly wrapped by WHEN 
**Is your feature request related to a problem? Please describe.**
The MindsDB Predict API returns predictions even when the JSON payload is not properly following the specification.
(https://apidocs.mindsdb.com/#acaf5684-c1bb-4df7-bae0-3a673ac1dd11) . 
For instance, the payload should follow this rule but the API also accepts payload without 'when' 
```
--data-raw '{
	"when": {
		"number_of_rooms": 2,
		"sqft": 1700
	}
}'
```
```
--data-raw '{
		"number_of_rooms": 2,
		"sqft": 1700
}'
```
In this case, the API cannot recognize input variables in the JSON request, thus return them as 'missing' in the response text. I am not sure if the prediction itself is not reliable in this case, but we might as well block such wrong API requests. 

**Describe the solution you'd like**
Return 'error' message if 'predict when' specification is not met 



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mindsdb/api/http/namespaces/predictor.py`
Content:
```
1 import os
2 import time
3 
4 from dateutil.parser import parse as parse_datetime
5 from flask import request
6 from flask_restx import Resource, abort
7 from flask import current_app as ca
8 
9 from mindsdb.utilities.log import log
10 from mindsdb.api.http.utils import http_error
11 from mindsdb.api.http.namespaces.configs.predictors import ns_conf
12 from mindsdb.api.http.namespaces.entitites.predictor_metadata import (
13     predictor_metadata,
14     predictor_query_params,
15     upload_predictor_params,
16     put_predictor_params
17 )
18 from mindsdb.api.http.namespaces.entitites.predictor_status import predictor_status
19 
20 
21 @ns_conf.route('/')
22 class PredictorList(Resource):
23     @ns_conf.doc('list_predictors')
24     @ns_conf.marshal_list_with(predictor_status, skip_none=True)
25     def get(self):
26         '''List all predictors'''
27         return request.native_interface.get_models()
28 
29 
30 @ns_conf.route('/custom/<name>')
31 @ns_conf.param('name', 'The predictor identifier')
32 @ns_conf.response(404, 'predictor not found')
33 class CustomPredictor(Resource):
34     @ns_conf.doc('put_custom_predictor')
35     def put(self, name):
36         try:
37             trained_status = request.json['trained_status']
38         except Exception:
39             trained_status = 'untrained'
40 
41         predictor_file = request.files['file']
42         fpath = os.path.join(ca.config_obj.paths['tmp'],  name + '.zip')
43         with open(fpath, 'wb') as f:
44             f.write(predictor_file.read())
45 
46         request.custom_models.load_model(fpath, name, trained_status)
47 
48         return f'Uploaded custom model {name}'
49 
50 
51 @ns_conf.route('/<name>')
52 @ns_conf.param('name', 'The predictor identifier')
53 @ns_conf.response(404, 'predictor not found')
54 class Predictor(Resource):
55     @ns_conf.doc('get_predictor')
56     @ns_conf.marshal_with(predictor_metadata, skip_none=True)
57     def get(self, name):
58         try:
59             model = request.native_interface.get_model_data(name, db_fix=False)
60         except Exception as e:
61             abort(404, "")
62 
63         for k in ['train_end_at', 'updated_at', 'created_at']:
64             if k in model and model[k] is not None:
65                 model[k] = parse_datetime(model[k])
66 
67         return model
68 
69     @ns_conf.doc('delete_predictor')
70     def delete(self, name):
71         '''Remove predictor'''
72         request.native_interface.delete_model(name)
73 
74         return '', 200
75 
76     @ns_conf.doc('put_predictor', params=put_predictor_params)
77     def put(self, name):
78         '''Learning new predictor'''
79         data = request.json
80         to_predict = data.get('to_predict')
81 
82         try:
83             kwargs = data.get('kwargs')
84         except Exception:
85             kwargs = None
86 
87         if type(kwargs) != type({}):
88             kwargs = {}
89 
90         if 'equal_accuracy_for_all_output_categories' not in kwargs:
91             kwargs['equal_accuracy_for_all_output_categories'] = True
92 
93         if 'advanced_args' not in kwargs:
94             kwargs['advanced_args'] = {}
95 
96         if 'use_selfaware_model' not in kwargs['advanced_args']:
97             kwargs['advanced_args']['use_selfaware_model'] = False
98 
99         try:
100             retrain = data.get('retrain')
101             if retrain in ('true', 'True'):
102                 retrain = True
103             else:
104                 retrain = False
105         except Exception:
106             retrain = None
107 
108         ds_name = data.get('data_source_name') if data.get('data_source_name') is not None else data.get('from_data')
109         from_data = request.default_store.get_datasource_obj(ds_name, raw=True)
110 
111         if from_data is None:
112             return {'message': f'Can not find datasource: {ds_name}'}, 400
113 
114         if retrain is True:
115             original_name = name
116             name = name + '_retrained'
117 
118         model_names = [x['name'] for x in request.native_interface.get_models()]
119         if name in model_names:
120             return http_error(
121                 409,
122                 f"Predictor '{name}' already exists",
123                 f"Predictor with name '{name}' already exists. Each predictor must have unique name."
124             )
125 
126         request.native_interface.learn(name, from_data, to_predict, request.default_store.get_datasource(ds_name)['id'], kwargs=kwargs)
127         for i in range(20):
128             try:
129                 # Dirty hack, we should use a messaging queue between the predictor process and this bit of the code
130                 request.native_interface.get_model_data(name)
131                 break
132             except Exception:
133                 time.sleep(1)
134 
135         if retrain is True:
136             try:
137                 request.native_interface.delete_model(original_name)
138                 request.native_interface.rename_model(name, original_name)
139             except Exception:
140                 pass
141 
142         return '', 200
143 
144 
145 @ns_conf.route('/<name>/learn')
146 @ns_conf.param('name', 'The predictor identifier')
147 class PredictorLearn(Resource):
148     def post(self, name):
149         data = request.json
150         to_predict = data.get('to_predict')
151         kwargs = data.get('kwargs', None)
152 
153         if not isinstance(kwargs, dict):
154             kwargs = {}
155 
156         if 'advanced_args' not in kwargs:
157             kwargs['advanced_args'] = {}
158 
159         ds_name = data.get('data_source_name') if data.get('data_source_name') is not None else data.get('from_data')
160         from_data = request.default_store.get_datasource_obj(ds_name, raw=True)
161 
162         request.custom_models.learn(name, from_data, to_predict, request.default_store.get_datasource(ds_name)['id'], kwargs)
163 
164         return '', 200
165 
166 
167 @ns_conf.route('/<name>/update')
168 @ns_conf.param('name', 'Update predictor')
169 class PredictorPredict(Resource):
170     @ns_conf.doc('Update predictor')
171     def get(self, name):
172         msg = request.native_interface.update_model(name)
173         return {
174             'message': msg
175         }
176 
177 
178 @ns_conf.route('/<name>/predict')
179 @ns_conf.param('name', 'The predictor identifier')
180 class PredictorPredict2(Resource):
181     @ns_conf.doc('post_predictor_predict', params=predictor_query_params)
182     def post(self, name):
183         '''Queries predictor'''
184         data = request.json
185         when = data.get('when', {})
186         format_flag = data.get('format_flag', 'explain')
187         kwargs = data.get('kwargs', {})
188 
189         if when is None:
190             return 'No data provided for the predictions', 500
191 
192         results = request.native_interface.predict(name, format_flag, when_data=when, **kwargs)
193 
194         return results
195 
196 
197 @ns_conf.route('/<name>/predict_datasource')
198 @ns_conf.param('name', 'The predictor identifier')
199 class PredictorPredictFromDataSource(Resource):
200     @ns_conf.doc('post_predictor_predict', params=predictor_query_params)
201     def post(self, name):
202         data = request.json
203         format_flag = data.get('format_flag', 'explain')
204         kwargs = data.get('kwargs', {})
205 
206         use_raw = False
207 
208         from_data = request.default_store.get_datasource_obj(data.get('data_source_name'), raw=use_raw)
209         if from_data is None:
210             abort(400, 'No valid datasource given')
211 
212         results = request.native_interface.predict(name, format_flag, when_data=from_data, **kwargs)
213         return results
214 
215 
216 @ns_conf.route('/<name>/rename')
217 @ns_conf.param('name', 'The predictor identifier')
218 class PredictorDownload(Resource):
219     @ns_conf.doc('get_predictor_download')
220     def get(self, name):
221         '''Export predictor to file'''
222         try:
223             new_name = request.args.get('new_name')
224             request.native_interface.rename_model(name, new_name)
225         except Exception as e:
226             return str(e), 400
227 
228         return f'Renamed model to {new_name}', 200
229
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mindsdb/api/http/namespaces/predictor.py b/mindsdb/api/http/namespaces/predictor.py
--- a/mindsdb/api/http/namespaces/predictor.py
+++ b/mindsdb/api/http/namespaces/predictor.py
@@ -182,12 +182,12 @@
     def post(self, name):
         '''Queries predictor'''
         data = request.json
-        when = data.get('when', {})
+        when = data.get('when')
         format_flag = data.get('format_flag', 'explain')
         kwargs = data.get('kwargs', {})
 
-        if when is None:
-            return 'No data provided for the predictions', 500
+        if isinstance(when, dict) is False or len(when) == 0:
+            return 'No data provided for the predictions', 400
 
         results = request.native_interface.predict(name, format_flag, when_data=when, **kwargs)

{"golden_diff": "diff --git a/mindsdb/api/http/namespaces/predictor.py b/mindsdb/api/http/namespaces/predictor.py\n--- a/mindsdb/api/http/namespaces/predictor.py\n+++ b/mindsdb/api/http/namespaces/predictor.py\n@@ -182,12 +182,12 @@\n     def post(self, name):\n         '''Queries predictor'''\n         data = request.json\n-        when = data.get('when', {})\n+        when = data.get('when')\n         format_flag = data.get('format_flag', 'explain')\n         kwargs = data.get('kwargs', {})\n \n-        if when is None:\n-            return 'No data provided for the predictions', 500\n+        if isinstance(when, dict) is False or len(when) == 0:\n+            return 'No data provided for the predictions', 400\n \n         results = request.native_interface.predict(name, format_flag, when_data=when, **kwargs)\n", "issue": "Reject predict(POST) API call if JSON payload is not properly wrapped by WHEN \n**Is your feature request related to a problem? Please describe.**\r\nThe MindsDB Predict API returns predictions even when the JSON payload is not properly following the specification.\r\n(https://apidocs.mindsdb.com/#acaf5684-c1bb-4df7-bae0-3a673ac1dd11) . \r\nFor instance, the payload should follow this rule but the API also accepts payload without 'when' \r\n```\r\n--data-raw '{\r\n\t\"when\": {\r\n\t\t\"number_of_rooms\": 2,\r\n\t\t\"sqft\": 1700\r\n\t}\r\n}'\r\n```\r\n```\r\n--data-raw '{\r\n\t\t\"number_of_rooms\": 2,\r\n\t\t\"sqft\": 1700\r\n}'\r\n```\r\nIn this case, the API cannot recognize input variables in the JSON request, thus return them as 'missing' in the response text. I am not sure if the prediction itself is not reliable in this case, but we might as well block such wrong API requests. \r\n\r\n**Describe the solution you'd like**\r\nReturn 'error' message if 'predict when' specification is not met \r\n\r\n\n", "before_files": [{"content": "import os\nimport time\n\nfrom dateutil.parser import parse as parse_datetime\nfrom flask import request\nfrom flask_restx import Resource, abort\nfrom flask import current_app as ca\n\nfrom mindsdb.utilities.log import log\nfrom mindsdb.api.http.utils import http_error\nfrom mindsdb.api.http.namespaces.configs.predictors import ns_conf\nfrom mindsdb.api.http.namespaces.entitites.predictor_metadata import (\n    predictor_metadata,\n    predictor_query_params,\n    upload_predictor_params,\n    put_predictor_params\n)\nfrom mindsdb.api.http.namespaces.entitites.predictor_status import predictor_status\n\n\n@ns_conf.route('/')\nclass PredictorList(Resource):\n    @ns_conf.doc('list_predictors')\n    @ns_conf.marshal_list_with(predictor_status, skip_none=True)\n    def get(self):\n        '''List all predictors'''\n        return request.native_interface.get_models()\n\n\n@ns_conf.route('/custom/<name>')\n@ns_conf.param('name', 'The predictor identifier')\n@ns_conf.response(404, 'predictor not found')\nclass CustomPredictor(Resource):\n    @ns_conf.doc('put_custom_predictor')\n    def put(self, name):\n        try:\n            trained_status = request.json['trained_status']\n        except Exception:\n            trained_status = 'untrained'\n\n        predictor_file = request.files['file']\n        fpath = os.path.join(ca.config_obj.paths['tmp'],  name + '.zip')\n        with open(fpath, 'wb') as f:\n            f.write(predictor_file.read())\n\n        request.custom_models.load_model(fpath, name, trained_status)\n\n        return f'Uploaded custom model {name}'\n\n\n@ns_conf.route('/<name>')\n@ns_conf.param('name', 'The predictor identifier')\n@ns_conf.response(404, 'predictor not found')\nclass Predictor(Resource):\n    @ns_conf.doc('get_predictor')\n    @ns_conf.marshal_with(predictor_metadata, skip_none=True)\n    def get(self, name):\n        try:\n            model = request.native_interface.get_model_data(name, db_fix=False)\n        except Exception as e:\n            abort(404, \"\")\n\n        for k in ['train_end_at', 'updated_at', 'created_at']:\n            if k in model and model[k] is not None:\n                model[k] = parse_datetime(model[k])\n\n        return model\n\n    @ns_conf.doc('delete_predictor')\n    def delete(self, name):\n        '''Remove predictor'''\n        request.native_interface.delete_model(name)\n\n        return '', 200\n\n    @ns_conf.doc('put_predictor', params=put_predictor_params)\n    def put(self, name):\n        '''Learning new predictor'''\n        data = request.json\n        to_predict = data.get('to_predict')\n\n        try:\n            kwargs = data.get('kwargs')\n        except Exception:\n            kwargs = None\n\n        if type(kwargs) != type({}):\n            kwargs = {}\n\n        if 'equal_accuracy_for_all_output_categories' not in kwargs:\n            kwargs['equal_accuracy_for_all_output_categories'] = True\n\n        if 'advanced_args' not in kwargs:\n            kwargs['advanced_args'] = {}\n\n        if 'use_selfaware_model' not in kwargs['advanced_args']:\n            kwargs['advanced_args']['use_selfaware_model'] = False\n\n        try:\n            retrain = data.get('retrain')\n            if retrain in ('true', 'True'):\n                retrain = True\n            else:\n                retrain = False\n        except Exception:\n            retrain = None\n\n        ds_name = data.get('data_source_name') if data.get('data_source_name') is not None else data.get('from_data')\n        from_data = request.default_store.get_datasource_obj(ds_name, raw=True)\n\n        if from_data is None:\n            return {'message': f'Can not find datasource: {ds_name}'}, 400\n\n        if retrain is True:\n            original_name = name\n            name = name + '_retrained'\n\n        model_names = [x['name'] for x in request.native_interface.get_models()]\n        if name in model_names:\n            return http_error(\n                409,\n                f\"Predictor '{name}' already exists\",\n                f\"Predictor with name '{name}' already exists. Each predictor must have unique name.\"\n            )\n\n        request.native_interface.learn(name, from_data, to_predict, request.default_store.get_datasource(ds_name)['id'], kwargs=kwargs)\n        for i in range(20):\n            try:\n                # Dirty hack, we should use a messaging queue between the predictor process and this bit of the code\n                request.native_interface.get_model_data(name)\n                break\n            except Exception:\n                time.sleep(1)\n\n        if retrain is True:\n            try:\n                request.native_interface.delete_model(original_name)\n                request.native_interface.rename_model(name, original_name)\n            except Exception:\n                pass\n\n        return '', 200\n\n\n@ns_conf.route('/<name>/learn')\n@ns_conf.param('name', 'The predictor identifier')\nclass PredictorLearn(Resource):\n    def post(self, name):\n        data = request.json\n        to_predict = data.get('to_predict')\n        kwargs = data.get('kwargs', None)\n\n        if not isinstance(kwargs, dict):\n            kwargs = {}\n\n        if 'advanced_args' not in kwargs:\n            kwargs['advanced_args'] = {}\n\n        ds_name = data.get('data_source_name') if data.get('data_source_name') is not None else data.get('from_data')\n        from_data = request.default_store.get_datasource_obj(ds_name, raw=True)\n\n        request.custom_models.learn(name, from_data, to_predict, request.default_store.get_datasource(ds_name)['id'], kwargs)\n\n        return '', 200\n\n\n@ns_conf.route('/<name>/update')\n@ns_conf.param('name', 'Update predictor')\nclass PredictorPredict(Resource):\n    @ns_conf.doc('Update predictor')\n    def get(self, name):\n        msg = request.native_interface.update_model(name)\n        return {\n            'message': msg\n        }\n\n\n@ns_conf.route('/<name>/predict')\n@ns_conf.param('name', 'The predictor identifier')\nclass PredictorPredict2(Resource):\n    @ns_conf.doc('post_predictor_predict', params=predictor_query_params)\n    def post(self, name):\n        '''Queries predictor'''\n        data = request.json\n        when = data.get('when', {})\n        format_flag = data.get('format_flag', 'explain')\n        kwargs = data.get('kwargs', {})\n\n        if when is None:\n            return 'No data provided for the predictions', 500\n\n        results = request.native_interface.predict(name, format_flag, when_data=when, **kwargs)\n\n        return results\n\n\n@ns_conf.route('/<name>/predict_datasource')\n@ns_conf.param('name', 'The predictor identifier')\nclass PredictorPredictFromDataSource(Resource):\n    @ns_conf.doc('post_predictor_predict', params=predictor_query_params)\n    def post(self, name):\n        data = request.json\n        format_flag = data.get('format_flag', 'explain')\n        kwargs = data.get('kwargs', {})\n\n        use_raw = False\n\n        from_data = request.default_store.get_datasource_obj(data.get('data_source_name'), raw=use_raw)\n        if from_data is None:\n            abort(400, 'No valid datasource given')\n\n        results = request.native_interface.predict(name, format_flag, when_data=from_data, **kwargs)\n        return results\n\n\n@ns_conf.route('/<name>/rename')\n@ns_conf.param('name', 'The predictor identifier')\nclass PredictorDownload(Resource):\n    @ns_conf.doc('get_predictor_download')\n    def get(self, name):\n        '''Export predictor to file'''\n        try:\n            new_name = request.args.get('new_name')\n            request.native_interface.rename_model(name, new_name)\n        except Exception as e:\n            return str(e), 400\n\n        return f'Renamed model to {new_name}', 200\n", "path": "mindsdb/api/http/namespaces/predictor.py"}], "after_files": [{"content": "import os\nimport time\n\nfrom dateutil.parser import parse as parse_datetime\nfrom flask import request\nfrom flask_restx import Resource, abort\nfrom flask import current_app as ca\n\nfrom mindsdb.utilities.log import log\nfrom mindsdb.api.http.utils import http_error\nfrom mindsdb.api.http.namespaces.configs.predictors import ns_conf\nfrom mindsdb.api.http.namespaces.entitites.predictor_metadata import (\n    predictor_metadata,\n    predictor_query_params,\n    upload_predictor_params,\n    put_predictor_params\n)\nfrom mindsdb.api.http.namespaces.entitites.predictor_status import predictor_status\n\n\n@ns_conf.route('/')\nclass PredictorList(Resource):\n    @ns_conf.doc('list_predictors')\n    @ns_conf.marshal_list_with(predictor_status, skip_none=True)\n    def get(self):\n        '''List all predictors'''\n        return request.native_interface.get_models()\n\n\n@ns_conf.route('/custom/<name>')\n@ns_conf.param('name', 'The predictor identifier')\n@ns_conf.response(404, 'predictor not found')\nclass CustomPredictor(Resource):\n    @ns_conf.doc('put_custom_predictor')\n    def put(self, name):\n        try:\n            trained_status = request.json['trained_status']\n        except Exception:\n            trained_status = 'untrained'\n\n        predictor_file = request.files['file']\n        fpath = os.path.join(ca.config_obj.paths['tmp'],  name + '.zip')\n        with open(fpath, 'wb') as f:\n            f.write(predictor_file.read())\n\n        request.custom_models.load_model(fpath, name, trained_status)\n\n        return f'Uploaded custom model {name}'\n\n\n@ns_conf.route('/<name>')\n@ns_conf.param('name', 'The predictor identifier')\n@ns_conf.response(404, 'predictor not found')\nclass Predictor(Resource):\n    @ns_conf.doc('get_predictor')\n    @ns_conf.marshal_with(predictor_metadata, skip_none=True)\n    def get(self, name):\n        try:\n            model = request.native_interface.get_model_data(name, db_fix=False)\n        except Exception as e:\n            abort(404, \"\")\n\n        for k in ['train_end_at', 'updated_at', 'created_at']:\n            if k in model and model[k] is not None:\n                model[k] = parse_datetime(model[k])\n\n        return model\n\n    @ns_conf.doc('delete_predictor')\n    def delete(self, name):\n        '''Remove predictor'''\n        request.native_interface.delete_model(name)\n\n        return '', 200\n\n    @ns_conf.doc('put_predictor', params=put_predictor_params)\n    def put(self, name):\n        '''Learning new predictor'''\n        data = request.json\n        to_predict = data.get('to_predict')\n\n        try:\n            kwargs = data.get('kwargs')\n        except Exception:\n            kwargs = None\n\n        if type(kwargs) != type({}):\n            kwargs = {}\n\n        if 'equal_accuracy_for_all_output_categories' not in kwargs:\n            kwargs['equal_accuracy_for_all_output_categories'] = True\n\n        if 'advanced_args' not in kwargs:\n            kwargs['advanced_args'] = {}\n\n        if 'use_selfaware_model' not in kwargs['advanced_args']:\n            kwargs['advanced_args']['use_selfaware_model'] = False\n\n        try:\n            retrain = data.get('retrain')\n            if retrain in ('true', 'True'):\n                retrain = True\n            else:\n                retrain = False\n        except Exception:\n            retrain = None\n\n        ds_name = data.get('data_source_name') if data.get('data_source_name') is not None else data.get('from_data')\n        from_data = request.default_store.get_datasource_obj(ds_name, raw=True)\n\n        if from_data is None:\n            return {'message': f'Can not find datasource: {ds_name}'}, 400\n\n        if retrain is True:\n            original_name = name\n            name = name + '_retrained'\n\n        model_names = [x['name'] for x in request.native_interface.get_models()]\n        if name in model_names:\n            return http_error(\n                409,\n                f\"Predictor '{name}' already exists\",\n                f\"Predictor with name '{name}' already exists. Each predictor must have unique name.\"\n            )\n\n        request.native_interface.learn(name, from_data, to_predict, request.default_store.get_datasource(ds_name)['id'], kwargs=kwargs)\n        for i in range(20):\n            try:\n                # Dirty hack, we should use a messaging queue between the predictor process and this bit of the code\n                request.native_interface.get_model_data(name)\n                break\n            except Exception:\n                time.sleep(1)\n\n        if retrain is True:\n            try:\n                request.native_interface.delete_model(original_name)\n                request.native_interface.rename_model(name, original_name)\n            except Exception:\n                pass\n\n        return '', 200\n\n\n@ns_conf.route('/<name>/learn')\n@ns_conf.param('name', 'The predictor identifier')\nclass PredictorLearn(Resource):\n    def post(self, name):\n        data = request.json\n        to_predict = data.get('to_predict')\n        kwargs = data.get('kwargs', None)\n\n        if not isinstance(kwargs, dict):\n            kwargs = {}\n\n        if 'advanced_args' not in kwargs:\n            kwargs['advanced_args'] = {}\n\n        ds_name = data.get('data_source_name') if data.get('data_source_name') is not None else data.get('from_data')\n        from_data = request.default_store.get_datasource_obj(ds_name, raw=True)\n\n        request.custom_models.learn(name, from_data, to_predict, request.default_store.get_datasource(ds_name)['id'], kwargs)\n\n        return '', 200\n\n\n@ns_conf.route('/<name>/update')\n@ns_conf.param('name', 'Update predictor')\nclass PredictorPredict(Resource):\n    @ns_conf.doc('Update predictor')\n    def get(self, name):\n        msg = request.native_interface.update_model(name)\n        return {\n            'message': msg\n        }\n\n\n@ns_conf.route('/<name>/predict')\n@ns_conf.param('name', 'The predictor identifier')\nclass PredictorPredict2(Resource):\n    @ns_conf.doc('post_predictor_predict', params=predictor_query_params)\n    def post(self, name):\n        '''Queries predictor'''\n        data = request.json\n        when = data.get('when')\n        format_flag = data.get('format_flag', 'explain')\n        kwargs = data.get('kwargs', {})\n\n        if isinstance(when, dict) is False or len(when) == 0:\n            return 'No data provided for the predictions', 400\n\n        results = request.native_interface.predict(name, format_flag, when_data=when, **kwargs)\n\n        return results\n\n\n@ns_conf.route('/<name>/predict_datasource')\n@ns_conf.param('name', 'The predictor identifier')\nclass PredictorPredictFromDataSource(Resource):\n    @ns_conf.doc('post_predictor_predict', params=predictor_query_params)\n    def post(self, name):\n        data = request.json\n        format_flag = data.get('format_flag', 'explain')\n        kwargs = data.get('kwargs', {})\n\n        use_raw = False\n\n        from_data = request.default_store.get_datasource_obj(data.get('data_source_name'), raw=use_raw)\n        if from_data is None:\n            abort(400, 'No valid datasource given')\n\n        results = request.native_interface.predict(name, format_flag, when_data=from_data, **kwargs)\n        return results\n\n\n@ns_conf.route('/<name>/rename')\n@ns_conf.param('name', 'The predictor identifier')\nclass PredictorDownload(Resource):\n    @ns_conf.doc('get_predictor_download')\n    def get(self, name):\n        '''Export predictor to file'''\n        try:\n            new_name = request.args.get('new_name')\n            request.native_interface.rename_model(name, new_name)\n        except Exception as e:\n            return str(e), 400\n\n        return f'Renamed model to {new_name}', 200\n", "path": "mindsdb/api/http/namespaces/predictor.py"}]}