Vetiver
Vetiver is a framework for MLOps tasks in Python and R. The goal of vetiver is to provide fluent tooling to version, share, deploy, and monitor a trained model. Functions handle both recording and checking the model’s input data prototype, and predicting from a remote API endpoint.
Vetiver integrates with pins in Python and pins in R to support model versioning. When you write a vetiver model to a board, the binary model object is stored together with necessary metadata, including its version, the packages needed to make a prediction, and the model’s input data prototype for checking new data at prediction time.
Deploy
To deploy a vetiver API to Connect, we recommend that users first pin their model to a board, possibly board_rsconnect()
in R or in Python. From the pin info, the vetiver package can deploy the API.
library(vetiver)
vetiver_deploy_rsconnect(
board = board,
name = "my.username/pin_name",
predict_args = list(debug = TRUE),
account = "my.username"
)
The username for the pin and the account deploying the model API do not have to be the same.
To deploy a vetiver API for a model trained in Python to Connect, users need a deployable app file as well as a file to capture dependencies. Vetiver offers functionality to build deployable files via vetiver.write_app()
. Dependencies can be captured with a requirements.txt
in Python.
from vetiver import vetiver_write_app
from rsconnect.actions import deploy_python_fastapi
= vetiver_write_app(
app_file = board,
board = "my.username/pin_name",
pin_name file = "app.py"
)
deploy_python_fastapi(=connect_server,
connect_server=".",
directory=None,
extra_files=None,
excludes= "app:api",
entry_point =True,
new=None,
app_id="vetiver api",
title=None,
python=False,
conda_mode=False,
force_generate=None,
log_callback )
When deploying a vetiver API in Python, ensure that you specify the correct entrypoint for the specific app you are deploying. The example above has its source code in a file named app.py
, and within that file, the Vetiver API application object is named api
, making the entrypoint app:api
. See the documentation on entrypoints for more information.
Predict from your model endpoint
A model deployed via vetiver can be treated as a special vetiver_endpoint()
object. If the API is only accessible to specified people, use an API Key for authorization. You can use predict()
to make predictions from your remote endpoint with your new data.
<- vetiver_endpoint(
endpoint "https://connect.example.com/content/$APP_ID/predict")
<- Sys.getenv("CONNECT_API_KEY")
apiKey
predict(
endpoint,
new_data,::add_headers(Authorization = paste("Key", apiKey))) httr
from vetiver.server import predict, vetiver_endpoint
= vetiver_endpoint(
endpoint f"https://connect.example.com/content/{APP_ID}/predict")
= { 'Authorization': f'Key {api_key}' }
h = predict(endpoint = endpoint, data = new_data, headers=h) response
Example
To run this example, you must have your Connect URL and API key loaded in your environment.
library(vetiver)
library(pins)
<- lm(mpg ~ ., data = mtcars)
cars_lm <- vetiver_model(cars_lm, "cars_mpg")
v <- board_rsconnect()
b vetiver_pin_write(b, v)
vetiver_deploy_rsconnect(
b, "my.username/cars_mpg",
predict_args = list(debug = TRUE),
account = "my.username"
)
import pins
import vetiver
from vetiver.data import mtcars
from rsconnect.api import RSConnectServer
from rsconnect.actions import deploy_python_fastapi
from sklearn import linear_model
= RSConnectServer(url = rsc_url, api_key = api_key)
connect_server = pins.board_rsconnect(server_url = rsc_url, api_key=api_key, allow_pickle_read=True)
board
= linear_model.LinearRegression().fit(mtcars, mtcars["mpg"])
cars_lm = vetiver.VetiverModel(cars_lm, model_name = "user.name/cars_mpg",
v = True, ptype_data = mtcars)
save_ptype
vetiver.vetiver_pin_write(board, v)"user.name/cars_mpg")
vetiver.vetiver_write_app(board,
deploy_python_fastapi(=connect_server,
connect_server=".",
directory=None,
extra_files=None,
excludes= "app:api",
entry_point =True,
new=None,
app_id="mtcars linear regression",
title=None,
python=False,
conda_mode=False,
force_generate=None,
log_callback )