---
title: "Data Schemas and Prompt Management"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Data Schemas and Prompt Management}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
```

This article follows data from source samples to modeling inputs and shows how prompt templates are
managed. All examples are deterministic and run without provider credentials.

## Samples and pairs

`read_samples_df()` normalizes a data frame and `read_samples_dir()` reads one text file per item.
Both return an `ID`/`text` table suitable for the fixed-pair workflow. Existing data frames can be
used directly when they already have those columns.

```{r samples-and-pairs}
library(pairwiseLLM)

data("example_writing_samples", package = "pairwiseLLM")
samples <- read_samples_df(example_writing_samples[, c("ID", "text")])

pairs <- samples |>
  make_pairs() |>
  sample_pairs(n_pairs = 4L, seed = 10L) |>
  randomize_pair_order(seed = 11L)

pairs[, c("ID1", "text1", "ID2", "text2")]
```

The fixed-pair schema uses `ID1`, `text1`, `ID2`, and `text2`. Reversal helpers preserve the
unordered pair while changing presentation order. Keep the identifiers: they are needed to map a
provider's `SAMPLE_1` or `SAMPLE_2` decision back to `better_id`.

## Traits and prompt templates

Templates require all four placeholders: `{TRAIT_NAME}`, `{TRAIT_DESCRIPTION}`, `{SAMPLE_1}`, and
`{SAMPLE_2}`. `build_prompt()` substitutes them but does not submit anything to a provider.

```{r build-prompt}
trait <- trait_description("overall_quality")
template <- set_prompt_template()

prompt <- build_prompt(
  template = template,
  trait_name = trait$name,
  trait_desc = trait$description,
  text1 = pairs$text1[[1]],
  text2 = pairs$text2[[1]]
)

substr(prompt, 1L, 180L)
```

The named registry lasts only for the current R session. Registration validates placeholders;
`overwrite = FALSE` protects an existing name. Persist a custom template by storing its text in
your project and registering it from a startup script, not by modifying package files.

```{r template-registry}
example_name <- "task07_example"
register_prompt_template(example_name, template = template)
example_name %in% list_prompt_templates()
identical(get_prompt_template(example_name), template)

register_prompt_template(example_name, template = template, overwrite = TRUE)
remove_prompt_template(example_name)
```

`set_prompt_template()` returns the built-in default or validates an inline/file template.
`get_prompt_template()` resolves a user registration before a built-in template of the same name.
`remove_prompt_template()` removes only session registrations; it cannot delete built-in files.

## Provider and result schemas

The live wrappers accept the fixed-pair rows directly. Batch request builders convert the same rows
to provider request records, and their matching parsers convert downloaded output back to package
results. Do not send a request table built for one provider to another provider's submission
function.

The normalized result bundle retains pair identifiers and adds provider metadata, visible content,
optional `thoughts`, `better_sample`, `better_id`, and token counts. Row-wise live calls return a
list whose valid `results`, unresolved `failed_pairs`, and attempt-level `failed_attempts` components
must be inspected separately. Batch parsers may omit unsuccessful rows from their successful result
table, so preserve the provider output/error file and job registry for audit and recovery.

```text
samples (ID, text)
  -> pairs (ID1, text1, ID2, text2)
     -> live call ---------------------> normalized results
     -> provider request + batch output -> provider parser -> normalized results
```

## Modeling and adaptive branches

For frequentist Bradley--Terry or Elo models, start from rows with `ID1`, `ID2`, and a valid
`better_id` and call `build_bt_data()` or `build_elo_data()`. Invalid or missing winners are not
valid outcomes; inspect failures before modeling rather than silently treating them as ties.

```{r modeling-schemas}
data("example_writing_pairs", package = "pairwiseLLM")

bt_data <- build_bt_data(example_writing_pairs)
elo_data <- build_elo_data(example_writing_pairs)
bayes_data <- build_btl_results_data(example_writing_pairs)

names(bt_data)
names(elo_data)
names(bayes_data)
```

Standalone Bayesian BTL uses the stricter canonical schema returned by
`build_btl_results_data()`; see
[Standalone Bayesian BTL with CmdStan](https://shmercer.github.io/pairwiseLLM/articles/bayesian-btl.html).

Adaptive ranking is a separate branch. `adaptive_rank()` starts from raw items and records each
attempt in an adaptive state with canonical step, round, link-stage, and item logs. A normalized
fixed-pair result table is not a drop-in replacement for an adaptive session. Use
`adaptive_results_history()` only when you need the committed adaptive outcomes in
`build_bt_data()` format.

## Failure checks at schema boundaries

- Reject missing, blank, or duplicate sample IDs before pairing.
- Preserve the original pair IDs and provider `custom_id` through batch submission and parsing.
- Model only outcomes whose `better_id` matches one member of the pair.
- Treat `thoughts` and raw responses as sensitive submitted/returned text when deciding retention.
- Validate persisted adaptive sessions with `validate_session_dir()` rather than editing `.rds`
  artifacts or coercing their schemas by hand.

## Related documentation

See [Getting Started with pairwiseLLM](https://shmercer.github.io/pairwiseLLM/articles/getting-started.html)
for the basic fixed-pair workflow,
[Provider Controls and Recovery](https://shmercer.github.io/pairwiseLLM/articles/provider-controls-and-recovery.html)
for live and batch failures, and
[Guide: Adaptive Pairing](https://shmercer.github.io/pairwiseLLM/articles/adaptive-pairing.html)
for adaptive state and logs.

## Citation

> Mercer, S. H. (2026). *Data schemas and prompt management* [R package vignette]. Comprehensive R
> Archive Network. https://doi.org/10.32614/CRAN.package.pairwiseLLM
