Add a prompt_template parameter to Task$new() that allows users to customize prompts on a per-sample basis using metadata columns from their dataset.
Motivation
Currently, if you want to vary the prompt context per sample (e.g., different instructions for each row), you need to build the prompts manually before creating the Task. This is a common need when:
- Running evaluations where each sample needs different instructions
- Testing how models respond to varied prompting strategies
- Parameterizing evaluations across different conditions
Solution (submitting as a PR)
Add a prompt_template argument to Task$new() that:
- Uses
{{ column_name }} syntax (via ellmer::interpolate()) to reference metadata columns
- Automatically prepends the interpolated template to each sample's
input
- Works with both
generate() and generate_structured() solvers
Examples
With generate()
library(vitals)
library(ellmer)
library(tibble)
shapes_data <- tibble(
input = c(
"The shapes are square, circle and rhombus",
"The shapes are square, circle and rhombus",
"The shapes are square, circle and rhombus"
),
target = c("square", "circle", "rhombus"),
shape_to_pick = c("square", "circle", "rhombus")
)
tsk <- Task$new(
dataset = shapes_data,
solver = generate(chat_anthropic(model = "claude-sonnet-4-5")),
scorer = detect_match("any"),
prompt_template = "Always pick {{ shape_to_pick }}. Just return the single chosen shape as 1 word.",
dir = tempdir()
)
tsk$eval()
Desired result:
tsk$get_samples()$result
[1] "square" "circle" "rhombus"
With generate_structured()
type_shape <- type_object(
shape = type_string("The name of the shape that was picked")
)
shapes_data <- tibble(
input = c(
"The shapes are square, circle and rhombus",
"The shapes are square, circle and rhombus",
"The shapes are square, circle and rhombus"
),
target = c("square", "circle", "rhombus"),
shape_to_pick = c("square", "circle", "rhombus")
)
tsk_str <- Task$new(
dataset = shapes_data,
solver = generate_structured(
solver_chat = chat_anthropic(model = "claude-sonnet-4-5"),
type = type_shape
),
scorer = detect_match("any"),
prompt_template = "Always pick {{ shape_to_pick }}. Just return the single chosen shape as 1 word.",
dir = tempdir()
)
tsk_str$eval()
Desired result:
tsk_str$get_samples()$result
[1] "[{\"shape\":\"square\"}]" "[{\"shape\":\"circle\"}]" "[{\"shape\":\"rhombus\"}]"
Implementation Notes
- The template is interpolated at the
Task level in $solve(), keeping solvers simple and unchanged
- Uses
ellmer::interpolate() which uses {{ }} syntax (avoids conflicts with JSON/R code)
- The interpolated template is prepended to the input with
\n\n separator
- When
prompt_template = NULL (default), behavior is unchanged
Add a
prompt_templateparameter toTask$new()that allows users to customize prompts on a per-sample basis using metadata columns from their dataset.Motivation
Currently, if you want to vary the prompt context per sample (e.g., different instructions for each row), you need to build the prompts manually before creating the Task. This is a common need when:
Solution (submitting as a PR)
Add a
prompt_templateargument toTask$new()that:{{ column_name }}syntax (viaellmer::interpolate()) to reference metadata columnsinputgenerate()andgenerate_structured()solversExamples
With
generate()Desired result:
With
generate_structured()Desired result:
Implementation Notes
Tasklevel in$solve(), keeping solvers simple and unchangedellmer::interpolate()which uses{{ }}syntax (avoids conflicts with JSON/R code)\n\nseparatorprompt_template = NULL(default), behavior is unchanged