rstudio / vetiver-r

Version, share, deploy, and monitor models

Home Page:https://rstudio.github.io/vetiver-r/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Function not found at inference time

rvalieris opened this issue · comments

Hello,

In my recipe I'm using a function from the stringi package, during training it works fine, but after converting the workflow to vetiver, it can't find the function even if the package is loaded, is there a way to tell vetiver which packages are required at inference time ?

example:

library(tidyverse)
library(tidymodels)
library(vetiver)
library(stringi)

rec <- recipe(Petal.Width ~ ., data=iris) |>
    # removes accents
    step_mutate(Species = stri_trans_general(Species, 'Latin-ASCII'))

wf <- 
    workflow() |>
    add_model(linear_reg()) |>
    add_recipe(rec)

res <- fit(wf, data=iris)

v <- vetiver_model(res, 'test')

predict(v, new_data=tibble(
    Sepal.Length=NA,
    Sepal.Width=NA,
    Petal.Length=NA,
    Species=NA
))
! could not find function "stri_trans_general" Error in `dplyr::mutate()`: ℹ In argument: `Species = stri_trans_general(Species, "Latin-ASCII")`. Caused by error in `stri_trans_general()`: ! could not find function "stri_trans_general" Traceback:
  1. predict(v, new_data = tibble(Sepal.Length = NA, Sepal.Width = NA,
    . Petal.Length = NA, Species = NA))
  2. predict.vetiver_model(v, new_data = tibble(Sepal.Length = NA,
    . Sepal.Width = NA, Petal.Length = NA, Species = NA))
  3. predict(model, ...)
  4. predict.workflow(model, ...)
  5. forge_predictors(new_data, workflow)
  6. hardhat::forge(new_data, blueprint = mold$blueprint)
  7. forge.data.frame(new_data, blueprint = mold$blueprint)
  8. run_forge(blueprint, new_data = new_data, outcomes = outcomes)
  9. run_forge.default_recipe_blueprint(blueprint, new_data = new_data,
    . outcomes = outcomes)
  10. forge_recipe_default_process(blueprint = blueprint, predictors = predictors,
    . outcomes = outcomes, extras = extras)
  11. recipes::bake(object = rec, new_data = new_data)
  12. bake.recipe(object = rec, new_data = new_data)
  13. bake(step, new_data = new_data)
  14. bake.step_mutate(step, new_data = new_data)
  15. dplyr::mutate(new_data, !!!object$inputs)
  16. mutate.data.frame(new_data, !!!object$inputs)
  17. mutate_cols(.data, dplyr_quosures(...), by)
  18. withCallingHandlers(for (i in seq_along(dots)) {
    . poke_error_context(dots, i, mask = mask)
    . context_poke("column", old_current_column)
    . new_columns <- mutate_col(dots[[i]], data, mask, new_columns)
    . }, error = dplyr_error_handler(dots = dots, mask = mask, bullets = mutate_bullets,
    . error_call = error_call, error_class = "dplyr:::mutate_error"),
    . warning = dplyr_warning_handler(state = warnings_state, mask = mask,
    . error_call = error_call))
  19. mutate_col(dots[[i]], data, mask, new_columns)
  20. mask$eval_all_mutate(quo)
  21. eval()
  22. .handleSimpleError(function (cnd)
    . {
    . local_error_context(dots, i = frame[[i_sym]], mask = mask)
    . if (inherits(cnd, "dplyr:::internal_error")) {
    . parent <- error_cnd(message = bullets(cnd))
    . }
    . else {
    . parent <- cnd
    . }
    . message <- c(cnd_bullet_header(action), i = if (has_active_group_context(mask)) cnd_bullet_cur_group_label())
    . abort(message, class = error_class, parent = parent, call = error_call)
    . }, "could not find function "stri_trans_general"", base::quote(stri_trans_general(Species,
    . "Latin-ASCII")))
  23. h(simpleError(msg, call))
  24. abort(message, class = error_class, parent = parent, call = error_call)
  25. signal_abort(cnd, .file)

This happens because vetiver uses the required_pkgs() generic to find out what needs to be installed/loaded:

library(tidymodels)
library(stringi)

rec <- recipe(Petal.Width ~ ., data=iris) |>
  # removes accents
  step_mutate(Species = stri_trans_general(Species, 'Latin-ASCII'))

# there is no stringi here:
required_pkgs(rec)
#> [1] "recipes"

Created on 2024-02-01 with reprex v2.1.0

We would need this to look like c("recipes", "stringi") instead.

  • Can you ask on the recipes repo how they recommend getting an additional package in there?
  • As a workaround for now, you can do v$metadata$required_pkgs <- c(v$metadata$required_pkgs, "stringi") to force the package into the vetiver model's required packages.

ah, I see, I didn't knew about required_pkgs, I will ask over there thanks.

sorry but the workaround does not seems to work for me, I'm getting the same error even after modifying v$metadata$required_pkgs.

We added an issue in recipes here: tidymodels/recipes#1282

@rvalieris What happens if you namespace the function, like this?

library(tidymodels)
library(vetiver)
#> 
#> Attaching package: 'vetiver'
#> The following object is masked from 'package:tune':
#> 
#>     load_pkgs

rec <- recipe(Petal.Width ~ ., data=iris) |>
    step_mutate(Species = stringi::stri_trans_general(Species, 'Latin-ASCII'))

fitted <- 
    workflow() |>
    add_model(linear_reg()) |>
    add_recipe(rec) |> 
    fit(data = iris)

v <- vetiver_model(fitted, 'test')

predict(v, new_data = slice_sample(iris, n = 1))
#> # A tibble: 1 × 1
#>   .pred
#>   <dbl>
#> 1  2.24

Created on 2024-02-01 with reprex v2.1.0

You will need to do this and still do v$metadata$required_pkgs <- c(v$metadata$required_pkgs, "stringi") for it to work in a deployed context.

@juliasilge , that works for me !! thanks for the help.

So glad to hear that! 🙌

For now, you can use this workaround and then we'll look to tidymodels/recipes#1282 for a more permanent solution.