## ----setup, include = FALSE---------------------------------------------------
fixture_dir <- "files-batches"
recording <- nzchar(Sys.getenv("FOUNDRY_RECORD_DOCS"))
have_fixtures <- dir.exists(fixture_dir) && length(list.files(fixture_dir)) > 0
run_api <- requireNamespace("httptest2", quietly = TRUE) &&
  (recording || have_fixtures)
library(foundryR)
if (run_api) {
  httptest2::start_vignette(fixture_dir)
}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = run_api,
  fig.width = 7, fig.height = 4.5, out.width = "100%")

## ----libraries, message = FALSE, eval = TRUE----------------------------------
library(foundryR)
library(dplyr)

## ----data-and-schema, eval = TRUE---------------------------------------------
comments <- tibble::tibble(
  comment_id = sprintf("c%02d", 1:6),
  comment = c(
    "The lectures were clear and the examples made regression feel concrete.",
    "The weekly quizzes felt rushed and did not match the homework.",
    "Office hours helped me catch up after I missed the first lab.",
    "The slides were hard to follow because notation changed between weeks.",
    "The final project connected the material to real policy questions.",
    "I needed more feedback before the midterm."
  )
)

course_schema <- foundry_schema(
  theme = schema_enum(
    c("instruction", "assessment", "support", "materials"),
    description = "Primary course evaluation theme."
  ),
  sentiment = schema_enum(
    c("positive", "negative", "mixed"),
    description = "Overall sentiment toward the course element."
  )
)

course_instructions <- paste(
  "Code one course evaluation comment.",
  "Choose exactly one primary theme and one sentiment.",
  "Return only fields that conform to the schema."
)

## ----request-file, eval = TRUE------------------------------------------------
jsonl <- tempfile(fileext = ".jsonl")

request_info <- foundry_batch_requests(
  comments,
  input = "comment",
  path = jsonl,
  model = "gpt-4.1-nano-batch",
  custom_id = "comment_id",
  schema = course_schema,
  schema_name = "CourseEvaluationCodes",
  instructions = course_instructions,
  overwrite = TRUE
)

request_info |>
  select(requests, endpoint)

## ----pretty-request, eval = TRUE----------------------------------------------
jsonlite::prettify(readLines(jsonl, n = 1))

## ----low-level-submit---------------------------------------------------------
uploaded_file <- foundry_file_upload(jsonl, purpose = "batch")

batch <- foundry_batch_create(
  input_file_id = uploaded_file$file_id,
  endpoint = request_info$endpoint
)

batch |>
  select(status, completion_window, batch_id)

## ----low-level-wait-----------------------------------------------------------
completed_batch <- foundry_batch_wait(
  batch$batch_id,
  interval = 60
)

completed_batch |>
  select(
    status,
    request_counts_total,
    request_counts_completed,
    request_counts_failed
  )

## ----low-level-results--------------------------------------------------------
batch_results <- foundry_batch_results(completed_batch$batch_id)

batch_results |>
  select(custom_id, output_text, .error, input_tokens, output_tokens)

## ----result-order, echo = FALSE, results = "asis"-----------------------------
if (!identical(batch_results$custom_id, comments$comment_id)) {
  cat(sprintf(
    "The results came back in the order %s, not in the order the requests were written. Join on `custom_id`, never on row position.\n",
    paste(batch_results$custom_id, collapse = ", ")
  ))
} else {
  cat("The results came back in request order this time, but the service does not promise an order. Join on `custom_id`, never on row position.\n")
}

## ----usage--------------------------------------------------------------------
foundry_usage(
  batch_results,
  rates = c(
    input = 0.00000010,
    cached_input = 0.000000025,
    output = 0.00000040
  )
)

## ----extract-batch-submit-----------------------------------------------------
extract_batch <- foundry_extract_batch(
  comments,
  text_col = "comment",
  schema = course_schema,
  model = "gpt-4.1-nano-batch",
  wait = FALSE,
  instructions = course_instructions
)

extract_batch |>
  select(status, completion_window, batch_id)

## ----extract-batch-results----------------------------------------------------
foundry_batch_wait(extract_batch$batch_id, interval = 60) |>
  select(status, request_counts_completed, request_counts_failed)

extract_results <- foundry_extract_batch_results(
  extract_batch$batch_id,
  data = comments,
  schema = course_schema,
  text_col = "comment"
)

extract_results |>
  select(comment_id, theme, sentiment, .error)

## ----cleanup-files------------------------------------------------------------
file_deletes <- bind_rows(
  foundry_file_delete(uploaded_file$file_id),
  foundry_file_delete(extract_batch$input_file_id)
)

file_deletes

## ----cleanup, include = FALSE, eval = TRUE------------------------------------
if (exists("jsonl")) {
  unlink(jsonl)
}
if (run_api) {
  httptest2::end_vignette()
}

