knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
This vignette walks through the six-call workflow screenllm
implements. Everything below runs on a laptop against a locally-served
Ollama backend. If you don't yet have Ollama installed and the four
default models pulled, check_setup() will tell you what's missing.
library(screenllm) check_setup()
Any tibble with title and abstract columns works; read_records()
also accepts CSV, XLSX, or RIS paths and normalises common column-name
variations (Scopus, Web of Science, EndNote). The package ships with a
40-record toy dataset drawn from the Community-Based Fisheries
Management (CBFM) review used in the manuscript, which we use here
for demonstration.
library(screenllm) toy_path <- system.file("extdata", "toy_cbfm.csv", package = "screenllm") records <- read_records(toy_path) head(records[, c("id", "title")])
criteria <- define_criteria( scope = "Articles potentially relevant to community-based fisheries management (CBFM) in Pacific Island contexts.", inclusions = c( "It is possible that the study includes a case study from a Pacific Island country (e.g. Fiji, Solomon Islands, Vanuatu, Papua New Guinea, Samoa, Tonga, or similar).", "It is possible that the study discusses fisheries and/or marine resource management.", "It is possible that the study discusses a community-based approach." ) ) print(criteria)
Real screening uses default_ensemble(), which talks to Ollama. For this
vignette we use backend_mock() so the code runs without Ollama.
mock_ensemble <- custom_ensemble( models = c("gemma3:27b", "gpt-oss:20b"), replicates = 2, backend = backend_mock() ) ranked <- rank_records(records, criteria, ensemble = mock_ensemble, verbose = FALSE) head(ranked[, c("id", "title", "universal_best_score", "rank")])
For a real run, swap the mock for the default:
ranked <- rank_records(records, criteria, ensemble = default_ensemble())
plan <- plan_screening(ranked) plan
The to_screen element is the tibble of records the reviewer should
inspect. Everything below the stopping point is treated as excluded.
Interactive screening via the Shiny app:
launch_screening_app(plan, ranked, out_file = "screening_decisions.csv")
Offline screening (spreadsheet round-trip):
export_worksheet(plan, path = "to_screen.xlsx") # Reviewer fills in the human_decision column and saves as # 'to_screen_completed.xlsx'. decisions <- read_decisions("to_screen_completed.xlsx")
Summarise the run and surface any strong LLM-human disagreements as a manual audit queue:
report <- summarise_screening(ranked, decisions, plan = plan) print(report) disagreements <- audit_disagreements(ranked, decisions) disagreements
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.