@@ -6,67 +6,69 @@ Upgrade notes
66Upgrading to version 1.0.0
77--------------------------
88
9- The release ``1.0.0 `` of the DEEPaaS API implementes several backwards
9+ The release ``1.0.0 `` of the DEEPaaS API implements several backwards
1010incompatible changes when compared with the previous releases in the ``0.X.X ``
1111series. Before upgrading your code and deploying into production, read the
1212following, as changes are needed in your model. Please go through the following
1313checklist in order.
1414
15- * Migrate new namespace entry point .
15+ * ** Migrate new namespace entry point. **
1616
1717 Previous code relied on a top-level entry point named ``deepaas.model ``,
1818 where we searched for the required functions or methods to be invoked for
1919 each API action.
2020
2121 Now the namespace has changed to ``deepaas.v2.model ``.
2222
23- Therefore, assumming that your code for V1 of the API was under the
23+ Therefore, assuming that your code for V1 of the API was under the
2424 ``my_model.api `` and you defined your the entry point as follows:
2525
26- .. code-block :: ini
26+ .. code-block :: ini
2727
28- [entry_points]
28+ [entry_points]
2929
30- deepaas.model =
31- my_model = my_model.api
30+ deepaas.model =
31+ my_model = my_model.api
3232
33- You should migrate to the following:
33+ You should migrate to the following:
3434
35- .. code-block :: ini
35+ .. code-block :: ini
3636
3737 [entry_points]
3838
3939 deepaas.v2.model =
4040 my_model = my_model.api
4141
42- .. note ::
43- If you do not change the namespace, we will try to load the old
44- entrypoint. However, this is deprecated and you should upgrade as soon as
45- possible.
42+ .. note ::
43+ If you do not change the namespace, we will try to load the old
44+ entrypoint. However, this is deprecated and you should upgrade as soon as
45+ possible.
4646
47- * Migrate from returning dictionaries to use an argument parser to define
48- train and predict arguments.
47+ * ** Migrate from returning dictionaries to use an argument parser to define
48+ train and predict arguments. **
4949
50- Previous code relied on returing arbitrary dictionaries that were used to
50+ Previous code relied on returning arbitrary dictionaries that were used to
5151 generate the arguments for each of the API endpoints. This is not anymore
52- supported and you should return a ``webargs `` field dictioary. This is still
53- done by defining the ``get_predict_args `` and ``fet_train_args `` functions.
52+ supported and you should return a ``webargs `` field dictionary (check
53+ `here <https://marshmallow.readthedocs.io/en/latest/api_reference.html#module-marshmallow.fields >`_
54+ for a full reference of the available options). This is still
55+ done by defining the ``get_predict_args `` and ``get_train_args `` functions.
5456 These functions must receive no arguments and they should return a dictionary
5557 as follows::
5658
57- from webargs import fields
58-
59- (...)
59+ from webargs import fields
6060
61- def get_predict_args():
62- return {
63- "arg1": fields.Str(
64- required=False,
65- default="foo",
66- description="Argument one"
67- ),
68- }
61+ (...)
6962
63+ def get_predict_args():
64+ return {
65+ "arg1": fields.Str(
66+ required=False, # force the user to define the value
67+ missing="foo", # default value to use
68+ enum=["choice1", "choice2"], # list of choices
69+ description="Argument one" # help string
70+ ),
71+ }
7072
7173 .. note ::
7274 If you do still follow the old way of returning the arguments we will try
@@ -75,34 +77,83 @@ checklist in order.
7577 soon as possible. All the arguments will be converted to Strings,
7678 therefore you will loose any type checking, etc.
7779
78- * Explictly define your input arguments. The previous version of the API
80+ * **Explicitly define your input arguments. **
81+
82+ The previous version of the API
7983 defined two arguments for inference: ``data `` and ``urls ``. This is not
80- anymore true, and you must define your own input arguments as follows::
84+ anymore true, and you must define your own input arguments.
85+ To replicate the response of v1 you have to define::
8186
8287 from webargs import fields
8388
8489 (...)
8590
8691 def get_predict_args():
8792 return {
88- "data": fields.Field(
89- required=True,
90- type="file",
91- location="form",
92- ),
93- }
94-
95- Then, you will get your input data in the ``data `` keyword argument in your
93+ 'files': fields.Field(
94+ required=False,
95+ missing=None,
96+ type="file",
97+ data_key="data",
98+ location="form",
99+ description="Select the image you want to classify."),
100+
101+ 'urls': fields.Url(
102+ required=False,
103+ missing=None,
104+ description="Select an URL of the image you want to classify.")
105+ }
106+
107+ Then, you will get your input data in the ``data `` and ``urls `` keyword arguments in your
96108 application.
97109
98- * Define your responses for the prediction. Now, unless you explicitly define
99- your application response schema, whatever you return will be converted into
100- a string and wrapped in the following response::
110+ .. note ::
111+ For the moment, in contrast with v1, only one url field at the same time is enabled,
112+ although multi-url (along with multi-files) support is coming soon.
113+
114+ * **Define your responses for the prediction. **
115+
116+ Now, unless you explicitly define your application response schema,
117+ whatever you return will be converted into a string and wrapped in the following response::
101118
102119 {
103120 "status": "OK",
104121 "predictions": "<model response as string>"
105122 }
106123
107- * Arguments and now passed as unpacked keyword arguments, not anymore as a
108- dictionary.
124+ * **Change in the ``predict`` function name. **
125+
126+ The ``predict_url `` and ``predict_data `` functions have been merged into a single ``predict ``
127+ function. In addition, arguments are now passed as unpacked keyword arguments, not anymore as a
128+ dictionary. So if you want to upgrade to v2 with minimal code changes, you just have to add
129+ the following function to your .py file::
130+
131+ def predict(**args):
132+
133+ if (not any([args['urls'], args['files']]) or
134+ all([args['urls'], args['files']])):
135+ raise Exception("You must provide either 'url' or 'data' in the payload")
136+
137+ if args['files']:
138+ args['files'] = [args['files']] # patch until list is available
139+ return predict_data(args)
140+ elif args['urls']:
141+ args['urls'] = [args['urls']] # patch until list is available
142+ return predict_url(args)
143+
144+ * **Changes in the data response **
145+
146+ The return object in ``args['files'] `` is no longer a ``werkzeug.FileStorage `` but an
147+ ``aiohttp.web_request.FileField ``.
148+
149+ The main difference is that now you should read the bytes using ``f.file.read() ``
150+ instead of ``f.read() ``. Additional changes might be needed if you were also
151+ using file information like content-type.
152+
153+ * **Catch error function **
154+
155+ The ``catch_error `` decorator around function is no longer needed.
156+
157+ * **API url **
158+
159+ Now the API functions are accessed under http://api_url/docs (eg. http://0.0.0.0:5000/docs)
0 commit comments