Skip to content

Commit

Permalink
Add docs around converting to / from JSON (#1165)
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrian Gonzalez-Martin committed May 26, 2023
1 parent 85b223d commit 80a0ee0
Showing 1 changed file with 53 additions and 9 deletions.
62 changes: 53 additions & 9 deletions docs/user-guide/content-type.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,58 @@ from mlserver.codecs import PandasCodec

dataframe = pd.DataFrame({'First Name': ["Joanne", "Michael"], 'Age': [34, 22]})

v2_request = PandasCodec.encode_request(dataframe)
print(v2_request)
inference_request = PandasCodec.encode_request(dataframe)
print(inference_request)
```

For a full end-to-end example on how content types and codecs work under the
hood, feel free to check out this [Content Type Decoding
example](../examples/content-type/README.md).

#### Converting to / from JSON

When using MLServer's request codecs, the output of encoding payloads will
always be one of the classes within the `mlserver.types` package (i.e.
{class}`InferenceRequest <mlserver.types.InferenceRequest>` or
{class}`InferenceResponse <mlserver.types.InferenceResponse>`).
Therefore, if you want to use them with `requests` (or other package outside of
MLServer) you will need to **convert them to a Python dict or a JSON string**.

Luckily, these classes leverage [Pydantic](https://docs.pydantic.dev/latest/)
under the hood.
Therefore you can just call the `.dict()` or `.json()` method to convert them.
Likewise, to read them back from JSON, we can always pass the JSON fields as
kwargs to the class' constructor (or use any of the [other
methods](https://docs.pydantic.dev/latest/usage/models/#model-properties)
available within Pydantic).

For example, if we want to send an inference request to model `foo`, we could
do something along the following lines:

```{code-block} python
---
emphasize-lines: 10-11, 15-18
---
import pandas as pd
import requests
from mlserver.codecs import PandasCodec
dataframe = pd.DataFrame({'First Name': ["Joanne", "Michael"], 'Age': [34, 22]})
inference_request = PandasCodec.encode_request(dataframe)
# raw_request will be a Python dictionary compatible with `requests`'s `json` kwarg
raw_request = inference_request.dict()
response = requests.post("localhost:8080/v2/models/foo/infer", json=raw_request)
# raw_response will be a dictionary (loaded from the response's JSON),
# therefore we can pass it as the InferenceResponse constructors' kwargs
raw_response = response.json()
inference_response = InferenceResponse(**raw_response)
```

### Model Metadata

Content types can also be defined as part of the [model's
Expand Down Expand Up @@ -292,7 +336,7 @@ emphasize-lines: 1,4
from mlserver.codecs import NumpyRequestCodec
# Encode an entire V2 request
v2_request = NumpyRequestCodec.encode_request(foo)
inference_request = NumpyRequestCodec.encode_request(foo)
```
````
Expand All @@ -306,7 +350,7 @@ from mlserver.codecs import NumpyCodec
# We can use the `NumpyCodec` to encode a single input head with name `foo`
# within a larger request
v2_request = InferenceRequest(
inference_request = InferenceRequest(
inputs=[
NumpyCodec.encode_input("foo", foo)
]
Expand Down Expand Up @@ -400,7 +444,7 @@ foo = pd.DataFrame({
"C": ["c1", "c2", "c3", "c4"]
})
v2_request = PandasCodec.encode_request(foo)
inference_request = PandasCodec.encode_request(foo)
```
````
`````
Expand Down Expand Up @@ -453,7 +497,7 @@ emphasize-lines: 1,4
from mlserver.codecs.string import StringRequestCodec
# Encode an entire V2 request
v2_request = StringRequestCodec.encode_request(foo, use_bytes=False)
inference_request = StringRequestCodec.encode_request(foo, use_bytes=False)
```
````
Expand All @@ -467,7 +511,7 @@ from mlserver.codecs import StringCodec
# We can use the `StringCodec` to encode a single input head with name `foo`
# within a larger request
v2_request = InferenceRequest(
inference_request = InferenceRequest(
inputs=[
StringCodec.encode_input("foo", foo, use_bytes=False)
]
Expand Down Expand Up @@ -532,7 +576,7 @@ from mlserver.codecs import Base64Codec
# We can use the `Base64Codec` to encode a single input head with name `foo`
# within a larger request
v2_request = InferenceRequest(
inference_request = InferenceRequest(
inputs=[
Base64Codec.encode_input("foo", foo, use_bytes=False)
]
Expand Down Expand Up @@ -597,7 +641,7 @@ from mlserver.codecs import DatetimeCodec
# We can use the `DatetimeCodec` to encode a single input head with name `foo`
# within a larger request
v2_request = InferenceRequest(
inference_request = InferenceRequest(
inputs=[
DatetimeCodec.encode_input("foo", foo, use_bytes=False)
]
Expand Down

0 comments on commit 80a0ee0

Please sign in to comment.