#' Create a vetiver object for deployment of a trained model
#'
#' A `vetiver_model()` object collects the information needed to store, version,
#' and deploy a trained model. Once your `vetiver_model()` object has been
#' created, you can:
#' - store and version it as a pin with [vetiver_pin_write()]
#' - create an API endpoint for it with [vetiver_api()]
#'
#'
#' @param model A trained model, such as an `lm()` model or a tidymodels
#' [workflows::workflow()].
#' @param model_name Model name or ID.
#' @param description A detailed description of the model. If omitted, a brief
#' description of the model will be generated.
#' @param save_prototype Should an input data prototype be stored with the model?
#' The options are `TRUE` (the default, which stores a zero-row slice of the
#' training data), `FALSE` (no input data prototype for visual documentation or
#' checking), or a dataframe to be used for both checking at prediction time
#' *and* examples in API visual documentation.
#' @param save_ptype `r lifecycle::badge("deprecated")`
#' @param prototype An input data prototype. If `NULL`, there is no checking of
#' new data at prediction time.
#' @param versioned Should the model object be versioned when stored with
#' [vetiver_pin_write()]? The default, `NULL`, will use the default for the
#' `board` where you store the model.
#' @param ... Other method-specific arguments passed to [vetiver_ptype()]
#' to compute an input data prototype, such as `prototype_data` (a sample of
#' training features).
#' @inheritParams pins::pin_write
#'
#' @details
#' You can provide your own data to `save_prototype` to use as examples in the
#' visual documentation created by [vetiver_api()]. If you do this,
#' consider checking that your input data prototype has the same structure
#' as your training data (perhaps with [hardhat::scream()]) and/or simulating
#' data to avoid leaking PII via your deployed model.
#'
#' Some models, like [ranger::ranger()], [keras](https://tensorflow.rstudio.com/),
#' and [luz (torch)](https://torch.mlverse.org/),
#' *require* that you pass in example training data as `prototype_data`
#' or else explicitly set `save_prototype = FALSE`. For non-rectangular data
#' input to models, such as image input for a keras or torch model, we currently
#' recommend that you turn off prototype checking via `save_prototype = FALSE`.
#'
#' @return A new `vetiver_model` object.
#'
#' @examples
#'
#' cars_lm <- lm(mpg ~ ., data = mtcars)
#' vetiver_model(cars_lm, "cars-linear")
#'
#' @export
vetiver_model <- function(model,
model_name,
...,
description = NULL,
metadata = list(),
save_prototype = TRUE,
save_ptype = deprecated(),
versioned = NULL) {
check_dots_used()
if (lifecycle::is_present(save_ptype)) {
lifecycle::deprecate_soft(
"0.2.0",
"vetiver_model(save_ptype)",
"vetiver_model(save_prototype)"
)
save_prototype <- save_ptype
}
if (is_null(description)) {
description <- vetiver_create_description(model)
}
prototype <- vetiver_create_ptype(model, save_prototype, ...)
metadata <- vetiver_create_meta(model, metadata)
model <- vetiver_prepare_model(model)
new_vetiver_model(
model = model,
model_name = model_name,
description = as.character(description),
metadata = metadata,
prototype = prototype,
versioned = versioned
)
}
#' @rdname vetiver_model
#' @export
new_vetiver_model <- function(model,
model_name,
description,
metadata,
prototype,
versioned) {
data <- list(
model = model,
model_name = model_name,
description = description,
metadata = metadata,
prototype = prototype,
versioned = versioned
)
structure(data, class = "vetiver_model")
}
is_vetiver_model <- function(x) {
inherits(x, "vetiver_model")
}
#' @export
format.vetiver_model <- function(x, ...) {
first_class <- class(x$model)[[1]]
cli::cli_format_method({
cli::cli_h3("{.emph {x$model_name}} {cli::symbol$line} {.cls {first_class}} model for deployment")
if (is.null(x$prototype)) {
cli::cli_text("{x$description}")
} else {
cli::cli_text("{x$description} using {ncol(x$prototype)} feature{?s}")
}
})
}
#' @export
print.vetiver_model <- function(x, ...) {
cat(format(x), sep = "\n")
invisible(x)
}
#' @export
predict.vetiver_model <- function(object, ...) {
check_dots_used()
model <- bundle::unbundle(object$model)
predict(model, ...)
}
#' @export
augment.vetiver_model <- function(x, ...) {
check_dots_used()
model <- bundle::unbundle(x$model)
augment(model, ...)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.