Repository: ray-project/ray

Issue:
[serve] Composed models with numpy arguments
### What is the problem?

I tried modifying the [composing multiple models](https://docs.ray.io/en/master/serve/advanced.html?highlight=pipeline#composing-multiple-models) examples to pass a numpy array to another endpoint. However, I get the following error:

```
2020-07-13 22:21:37,329 ERROR worker.py:987 -- Possible unhandled error from worker: ray::RayServeWorker_sum_model.handle_request() (pid=22037, ip=192.168.1.31)
  File "python/ray/_raylet.pyx", line 410, in ray._raylet.execute_task
  File "python/ray/_raylet.pyx", line 424, in ray._raylet.execute_task
  File "python/ray/_raylet.pyx", line 1212, in ray._raylet.CoreWorker.run_async_func_in_event_loop
  File "/home/users/daniel/.local/conda/lib/python3.7/concurrent/futures/_base.py", line 428, in result
    return self.__get_result()
  File "/home/users/daniel/.local/conda/lib/python3.7/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "python/ray/_raylet.pyx", line 422, in deserialize_args
  File "/home/users/daniel/.cache/pypoetry/virtualenvs/ray-test-mjIDN_hR-py3.7/lib/python3.7/site-packages/ray/serialization.py", line 312, in deserialize_objects
    self._deserialize_object(data, metadata, object_id))
  File "/home/users/daniel/.cache/pypoetry/virtualenvs/ray-test-mjIDN_hR-py3.7/lib/python3.7/site-packages/ray/serialization.py", line 252, in _deserialize_object
    return self._deserialize_msgpack_data(data, metadata)
  File "/home/users/daniel/.cache/pypoetry/virtualenvs/ray-test-mjIDN_hR-py3.7/lib/python3.7/site-packages/ray/serialization.py", line 233, in _deserialize_msgpack_data
    python_objects = self._deserialize_pickle5_data(pickle5_data)
  File "/home/users/daniel/.cache/pypoetry/virtualenvs/ray-test-mjIDN_hR-py3.7/lib/python3.7/site-packages/ray/serialization.py", line 221, in _deserialize_pickle5_data
    obj = pickle.loads(in_band)
  File "/home/users/daniel/.cache/pypoetry/virtualenvs/ray-test-mjIDN_hR-py3.7/lib/python3.7/site-packages/ray/serve/router.py", line 53, in ray_deserialize
    kwargs = pickle.loads(value)
  File "/home/users/daniel/.cache/pypoetry/virtualenvs/ray-test-mjIDN_hR-py3.7/lib/python3.7/site-packages/ray/cloudpickle/cloudpickle_fast.py", line 448, in _numpy_frombuffer
    array.setflags(write=isinstance(buffer, bytearray) or not buffer.readonly)
AttributeError: 'bytes' object has no attribute 'readonly'
```

Ray version: 0.8.6
Python version: 3.7.7
Numpy version: 1.19.0

### Reproduction (REQUIRED)

```
import time
from ray import serve
import requests
import numpy as np

serve.init()


def sum_model(_request, data=None):
    return np.sum(data)


class ComposedModel:
    def __init__(self):
        self.model = serve.get_handle("sum_model")

    async def __call__(self, _request):
        data = np.ones((10, 10))
        result = await self.model.remote(data=data)
        return result



serve.create_backend("sum_model", sum_model)
serve.create_endpoint("sum_model", backend="sum_model")
serve.create_backend("model", ComposedModel)
serve.create_endpoint("model", backend="model", route="/model", methods=['GET'])

while True:
    result = requests.get('http://127.0.0.1:8000/model')
    print(result)
    time.sleep(1)
```


- [x] I have verified my script runs in a clean environment and reproduces the issue.
- [x] I have verified the issue also occurs with the [latest wheels](https://docs.ray.io/en/latest/installation.html).



Discussion:

Resolving patch:
diff --git a/python/ray/serve/request_params.py b/python/ray/serve/request_params.py
--- a/python/ray/serve/request_params.py
+++ b/python/ray/serve/request_params.py
@@ -42,7 +42,7 @@ def adjust_relative_slo_ms(self) -> float:
         return current_time_ms + slo_ms
 
     def ray_serialize(self):
-        return pickle.dumps(self.__dict__, protocol=5)
+        return pickle.dumps(self.__dict__)
 
     @staticmethod
     def ray_deserialize(value):
diff --git a/python/ray/serve/router.py b/python/ray/serve/router.py
--- a/python/ray/serve/router.py
+++ b/python/ray/serve/router.py
@@ -3,10 +3,10 @@
 from collections import defaultdict, deque
 import time
 from typing import DefaultDict, List
+import pickle
 
 import blist
 
-import ray.cloudpickle as pickle
 from ray.exceptions import RayTaskError
 
 import ray
@@ -50,7 +50,7 @@ def ray_serialize(self):
         # worker without removing async_future.
         clone = copy.copy(self).__dict__
         clone.pop("async_future")
-        return pickle.dumps(clone, protocol=5)
+        return pickle.dumps(clone)
 
     @staticmethod
     def ray_deserialize(value):


Test patch:
diff --git a/python/ray/serve/tests/test_regression.py b/python/ray/serve/tests/test_regression.py
new file mode 100644
--- /dev/null
+++ b/python/ray/serve/tests/test_regression.py
@@ -0,0 +1,38 @@
+import numpy as np
+import requests
+
+from ray import serve
+
+
+def test_np_in_composed_model(serve_instance):
+    # https://github.com/ray-project/ray/issues/9441
+    # AttributeError: 'bytes' object has no attribute 'readonly'
+    # in cloudpickle _from_numpy_buffer
+
+    def sum_model(_request, data=None):
+        return np.sum(data)
+
+    class ComposedModel:
+        def __init__(self):
+            self.model = serve.get_handle("sum_model")
+
+        async def __call__(self, _request):
+            data = np.ones((10, 10))
+            result = await self.model.remote(data=data)
+            return result
+
+    serve.create_backend("sum_model", sum_model)
+    serve.create_endpoint("sum_model", backend="sum_model")
+    serve.create_backend("model", ComposedModel)
+    serve.create_endpoint(
+        "model", backend="model", route="/model", methods=['GET'])
+
+    result = requests.get("http://127.0.0.1:8000/model")
+    assert result.status_code == 200
+    assert result.json() == 100.0
+
+
+if __name__ == "__main__":
+    import sys
+    import pytest
+    sys.exit(pytest.main(["-v", "-s", __file__]))