## ----setup, include = FALSE--------------------------------------------------- # Evaluated wherever INLA and the serving stack are installed (CI and # development machines); rendered as static code elsewhere. knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = all(vapply( c("INLA", "vetiver", "pins", "plumber", "callr", "httr2", "yardstick"), requireNamespace, logical(1), quietly = TRUE )) ) ## ----message = FALSE---------------------------------------------------------- library(inlabru) library(vetiver) library(pins) library(plumber) library(inlaops) ## ----------------------------------------------------------------------------- set.seed(42) n <- 200 dat <- data.frame( x1 = rnorm(n), x2 = rnorm(n) ) dat$y <- 2 + 0.8 * dat$x1 - 0.4 * dat$x2 + rnorm(n, sd = 0.5) fit <- bru( y ~ Intercept(1) + x1 + x2, family = "gaussian", data = dat, options = bru_options( control.compute = list(config = TRUE, dic = TRUE, waic = TRUE) ) ) ## ----------------------------------------------------------------------------- v <- vetiver_model( fit, "gaussian_glm", metadata = list( pred_formula = "~ Intercept + x1 + x2", n_samples = 200L, # posterior samples per request; 200 is the default waic = fit$waic$waic, dic = fit$dic$dic ) ) v v$prototype ## ----eval = FALSE------------------------------------------------------------- # fit_p <- bru_reg(family = "gaussian") |> # parsnip::set_engine("inlabru") |> # parsnip::fit(y ~ Intercept(1) + x1 + x2, data = dat) # # v_parsnip <- vetiver_model( # fit_p$fit, "gaussian_glm", # note: fit_p$fit # metadata = list(pred_formula = "~ Intercept + x1 + x2") # ) ## ----------------------------------------------------------------------------- board <- board_temp() # swap for board_s3(), board_connect(), etc. vetiver_pin_write(board, v) pin_versions(board, "gaussian_glm") ## ----eval = FALSE------------------------------------------------------------- # pr() |> # vetiver_api(v) |> # pr_run(port = 8088) ## ----------------------------------------------------------------------------- port <- httpuv::randomPort() server <- callr::r_bg( function(board_path, port) { library(inlaops) v <- vetiver::vetiver_pin_read(pins::board_folder(board_path), "gaussian_glm") plumber::pr() |> vetiver::vetiver_api(v) |> plumber::pr_run(port = port) }, args = list(board_path = board$path, port = port) ) # Wait until the API answers its health check. for (i in 1:60) { up <- tryCatch( { httr2::request(sprintf("http://127.0.0.1:%d/ping", port)) |> httr2::req_perform() TRUE }, error = function(e) FALSE ) if (up || !server$is_alive()) break Sys.sleep(1) } stopifnot(up) ## ----------------------------------------------------------------------------- endpoint <- vetiver_endpoint(sprintf("http://127.0.0.1:%d/predict", port)) new_obs <- data.frame(x1 = c(0.5, -1.2), x2 = c(1.0, 0.3)) predict(endpoint, new_obs) ## ----------------------------------------------------------------------------- try(predict(endpoint, data.frame(x1 = 0.5))) ## ----------------------------------------------------------------------------- server$kill() ## ----------------------------------------------------------------------------- versions <- pin_versions(board, "gaussian_glm") do.call(rbind, lapply(versions$version, function(ver) { meta <- pin_meta(board, "gaussian_glm", version = ver) data.frame(version = ver, waic = meta$user$waic, dic = meta$user$dic) })) ## ----------------------------------------------------------------------------- monitoring_data <- dat # in production: observations collected since deployment monitoring_data$.pred <- inlabru::generate( fit, newdata = monitoring_data, formula = ~ Intercept + x1 + x2, n.samples = 500 ) |> rowMeans() # Synthetic timestamps for the example. Replace with real collection times. monitoring_data$obs_date <- seq.Date( from = as.Date("2026-01-01"), by = "day", length.out = nrow(monitoring_data) ) metrics_board <- board_temp() new_metrics <- vetiver_compute_metrics( monitoring_data, date_var = obs_date, period = "week", truth = y, estimate = .pred ) # vetiver_pin_metrics() appends to an existing metrics pin — the first time # you record metrics, write the pin directly with pins::pin_write(). On # subsequent runs (e.g. weekly cron jobs), use vetiver_pin_metrics() so each # new window's rows are appended without overwriting history. if ("gaussian_glm_metrics" %in% pins::pin_list(metrics_board)) { vetiver_pin_metrics(metrics_board, new_metrics, "gaussian_glm_metrics") } else { pins::pin_write(metrics_board, new_metrics, "gaussian_glm_metrics") } head(pins::pin_read(metrics_board, "gaussian_glm_metrics")) ## ----eval = FALSE------------------------------------------------------------- # v <- vetiver_model( # fit, # "multi_lhood_model", # save_prototype = tibble::tibble(x1 = 0, x2 = 0) # )