Skip to content

Commit

Permalink
adding example to readme, cleaning up code a bit
Browse files Browse the repository at this point in the history
Signed-off-by: vsoch <vsoch@users.noreply.github.com>
  • Loading branch information
vsoch committed Feb 28, 2022
1 parent 1430d24 commit d930399
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ and **Merged pull requests**. Critical items to know are:
The versions coincide with releases on pip. Only major versions will be released as tags on Github.

## [0.0.x](https://github.com/vsoch/riverapi/tree/main) (0.0.x)
- addition of link to examples (0.0.11)
- skeleton release (0.0.1)
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@ RUN pip install ipython
WORKDIR /code
COPY . /code
RUN pip install -e .[all]
ENTRYPOINT ["/opt/conda/bin/riverapi"]
50 changes: 48 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,61 @@
# River API Client

[![PyPI version](https://badge.fury.io/py/riverapi.svg)](https://badge.fury.io/py/riverapi)

This is an API client created for [django-river-ml](https://pypi.org/project/django-river-ml/)
that is intended to make it easy to interact with an online ML server providing river models (learning, predicting, etc.).
It currently does not provide a terminal or command line client and is intended to be used
from Python, but if there is a good use case for a command line set of interactions
this can be added.

**under development**
## Quick Start

Given that you have a server running that implements the same space as django-river-ml:

```python
from river import datasets
from river import linear_model
from river import preprocessing

from riverapi.main import Client


def main():

# This is the default, just to show how to customize
cli = Client("http://localhost:8000")

# Upload a model
model = preprocessing.StandardScaler() | linear_model.LinearRegression()

# Save the model name for other endpoint interaction
model_name = cli.upload_model(model, "regression")
print("Created model %s" % model_name)

# Train on some data
for x, y in datasets.TrumpApproval().take(100):
cli.learn(model_name, x=x, y=y)

# Get the model (this is a json representation)
model_json = cli.get_model_json(model_name)
model_json

# Saves to model-name>.pkl in pwd unless you provide a second arg, dest
cli.download_model(model_name)

# Make predictions
for x, y in datasets.TrumpApproval().take(10):
print(cli.predict(model_name, x=x))

# Get all models
print(cli.models())


not ready for use!
if __name__ == "__main__":
main()
```

**under development** more coming soon!

## Contributors

Expand Down
6 changes: 0 additions & 6 deletions riverapi/defaults.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
__author__ = "Vanessa Sochat"
__copyright__ = "Copyright 2022, Vanessa Sochat"
__license__ = "MPL 2.0"

import os

# Assumes local host for development
baseurl = "http://127.0.0.1:8000"
20 changes: 16 additions & 4 deletions riverapi/client.py → riverapi/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ def print_response(self, r):
def do_request(
self, typ, url, data=None, json=None, headers=None, return_json=True
):
"""
Do a request (get, post, etc)
"""
if not self.quiet:
logger.info("%s %s" % (typ.uppercase(), url))
logger.info("%s %s" % (typ.upper(), url))

# The first post when you upload the model defines the flavor (regression)
if json:
Expand All @@ -71,11 +74,17 @@ def do_request(
return r

def post(self, url, data=None, json=None, headers=None, return_json=True):
"""
Perform a POST request
"""
return self.do_request(
"post", url, data=data, json=json, headers=headers, return_json=return_json
)

def get(self, url, data=None, json=None, headers=None, return_json=True):
"""
Perform a GET request
"""
return self.do_request(
"get", url, data=data, json=json, headers=headers, return_json=return_json
)
Expand All @@ -92,7 +101,7 @@ def upload_model(self, model, flavor):
logger.info("Created model %s" % model_name)
return model_name

def train(self, model_name, x, y=None):
def learn(self, model_name, x, y=None):
"""
Train on some data. You are required to provide at least the model
name known to the server and x (data).
Expand Down Expand Up @@ -121,21 +130,24 @@ def download_model(self, model_name, dest=None):
r = self.get("/api/model/download/%s/" % model_name, return_json=False)

# Default to pickle in PWD
dest = dest or "%s.pkg" % model_name
dest = dest or "%s.pkl" % model_name

# Save to dest file
with open(dest, "wb") as f:
for chunk in r:
f.write(chunk)
return dest

def predict(self, model_name, x, y):
def predict(self, model_name, x):
"""
Make a prediction
"""
return self.post("/api/predict/", json={"model": model_name, "features": x})

def models(self):
"""
Get a listing of known models
"""
return self.get("/api/models/")

# TODO need to add streaming events/other endpoints and authentication
2 changes: 1 addition & 1 deletion riverapi/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
__copyright__ = "Copyright 2022, Vanessa Sochat"
__license__ = "MPL 2.0"

__version__ = "0.0.1"
__version__ = "0.0.11"
AUTHOR = "Vanessa Sochat"
EMAIL = "vsoch@users.noreply.github.com"
NAME = "riverapi"
Expand Down

0 comments on commit d930399

Please sign in to comment.