% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/LLMR_tidy.R
\name{llm_mutate}
\alias{llm_mutate}
\title{Mutate a data frame with LLM output}
\usage{
llm_mutate(
  .data,
  output,
  prompt = NULL,
  .messages = NULL,
  .config,
  .system_prompt = NULL,
  .before = NULL,
  .after = NULL,
  .return = c("columns", "text", "object"),
  .structured = FALSE,
  .schema = NULL,
  .fields = NULL,
  .tags = NULL,
  ...
)
}
\arguments{
\item{.data}{A data.frame / tibble.}

\item{output}{Unquoted name that becomes \strong{the new column} (generative) \emph{or}
\strong{the prefix} for embedding columns. In shorthand form, omit this argument
and pass \code{newcol = "<glue prompt>"} or
\code{newcol = c(system = "...", user = "...")} through \code{...}.}

\item{prompt}{Optional glue template string for a single user turn; reference
any columns in \code{.data} (e.g. \code{"{id}. {question}\\nContext: {context}"}).
Ignored if \code{.messages} is supplied.}

\item{.messages}{Optional \strong{named} character vector of glue templates to build
a multi-turn message, using roles in \code{c("system","user","assistant","file")}.
Values are glue templates evaluated per-row; all can reference multiple columns.
For multimodal, use role \code{"file"} with a column containing a path template.}

\item{.config}{An \link{llm_config} object (generative or embedding).}

\item{.system_prompt}{Optional system message sent with every request when
\code{.messages} does not include a \code{system} entry.}

\item{.before, .after}{Standard \link[dplyr:relocate]{dplyr::relocate} helpers controlling where the
generated column(s) are placed.}

\item{.return}{One of \code{c("columns","text","object")}. For generative mode,
controls how results are added. \code{"columns"} (default) adds text plus
diagnostic columns; \code{"text"} adds a single text column; \code{"object"} adds a
list-column of \code{llmr_response} objects.}

\item{.structured}{Logical. If \code{TRUE}, enables structured JSON output with automatic
parsing. When enabled, this is equivalent to calling \code{\link[=llm_mutate_structured]{llm_mutate_structured()}}.
Default is \code{FALSE}.}

\item{.schema}{Optional JSON Schema (R list). When \code{.structured = TRUE}, this schema
is sent to the provider for validation and used for local parsing. When \code{NULL},
only JSON mode is enabled (no strict schema validation).}

\item{.fields}{Optional character vector of fields to extract from parsed JSON
or tag output. In JSON mode, supports nested paths (e.g., \code{"user.name"} or
\code{"/data/items/0"}). When \code{NULL} and \code{.schema} is provided, auto-extracts all
top-level schema properties. In tag mode, \code{NULL} extracts all \code{.tags}. Set
to \code{FALSE} to skip field extraction entirely.}

\item{.tags}{Optional character vector of XML-like tag names to request and parse,
such as \code{c("age", "job")}. When supplied, \code{\link[=llm_mutate]{llm_mutate()}} delegates to
\code{\link[=llm_mutate_tags]{llm_mutate_tags()}} and adds \code{tags_ok}, \code{tags_data}, and one column per tag
unless \code{.fields = FALSE}.}

\item{...}{Passed to the underlying calls: \code{\link[=call_llm_broadcast]{call_llm_broadcast()}} in
generative mode, \code{\link[=get_batched_embeddings]{get_batched_embeddings()}} in embedding mode.}
}
\value{
\code{.data} with the new column(s) appended.
}
\description{
Adds one or more columns to \code{.data} that are produced by a Large-Language-Model.
}
\details{
\itemize{
\item \strong{Multi-column injection:} templating is NA-safe (\code{NA} -> empty string).
\item \strong{Multi-turn templating:} supply \code{.messages = c(system=..., user=..., file=...)}.
Duplicate role names are allowed (e.g., two \code{user} turns).
\item \strong{Generative mode:} one request per row via \code{\link[=call_llm_broadcast]{call_llm_broadcast()}}.
\item \strong{Parallelism:} calls \code{\link[=call_llm_broadcast]{call_llm_broadcast()}}, which uses
\code{\link[=call_llm_robust]{call_llm_robust()}} under the hood. If no future plan is active,
workers are auto-configured; call \code{\link[=setup_llm_parallel]{setup_llm_parallel()}} to set worker
count explicitly.
\item \strong{Embedding mode:} the per-row text is embedded via \code{\link[=get_batched_embeddings]{get_batched_embeddings()}}.
Result expands to numeric columns named \verb{paste0(<output>, 1:N)}. If all rows
fail to embed, a single \verb{<output>1} column of \code{NA} is returned.
\item Diagnostic columns use suffixes: \verb{_finish}, \verb{_sent}, \verb{_rec}, \verb{_tot}, \verb{_reason}, \verb{_ok}, \verb{_err}, \verb{_id}, \verb{_status}, \verb{_ecode}, \verb{_param}, \verb{_t}.
}
}
\section{Shorthand}{

You can supply the output column and prompt in one argument:

\preformatted{
df |> llm_mutate(answer = "{question} (hint: {hint})", .config = cfg)
df |> llm_mutate(answer = c(system = "One word.", user = "{question}"), .config = cfg)
df |> llm_mutate(country = "Where is {city}? Answer with only the country.", .config = cfg)
}

This is equivalent to:
\preformatted{
df |> llm_mutate(answer, prompt = "{question} (hint: {hint})", .config = cfg)
df |> llm_mutate(answer, .messages = c(system = "One word.", user = "{question}"), .config = cfg)
}
}

\section{Structured modes}{

\itemize{
\item \code{.structured = TRUE} delegates to \code{\link[=llm_mutate_structured]{llm_mutate_structured()}} for JSON.
\item \code{.tags} delegates to \code{\link[=llm_mutate_tags]{llm_mutate_tags()}} for XML-like tags.
If both are supplied, \code{.structured} takes precedence.
}
}

\examples{
\dontrun{
library(dplyr)

df <- tibble::tibble(
  id       = 1:2,
  question = c("Capital of France?", "Author of 1984?"),
  hint     = c("European city", "English novelist")
)

cfg <- llm_config("openai", "gpt-4.1-nano",
                  temperature = 0)

# Generative: single-turn with multi-column injection
df |>
  llm_mutate(
    answer,
    prompt = "{question} (hint: {hint})",
    .config = cfg,
    .system_prompt = "Respond in one word."
  )

# Generative: multi-turn via .messages (system + user)
df |>
  llm_mutate(
    advice,
    .messages = c(
      system = "You are a helpful zoologist. Keep answers short.",
      user   = "What is a key fact about this? {question} (hint: {hint})"
    ),
    .config = cfg
  )

# Multimodal: include an image path with role 'file'
pics <- tibble::tibble(
  img    = c("inst/extdata/cat.png", "inst/extdata/dog.jpg"),
  prompt = c("Describe the image.", "Describe the image.")
)
pics |>
  llm_mutate(
    vision_desc,
    .messages = c(user = "{prompt}", file = "{img}"),
    .config = llm_config("openai","gpt-4.1-mini")
  )

# Embeddings: output name becomes the prefix of embedding columns
emb_cfg <- llm_config("voyage", "voyage-3.5-lite",
                      embedding = TRUE)
df |>
  llm_mutate(
    vec,
    prompt  = "{question}",
    .config = emb_cfg,
    .after  = id
  )

# Structured output: using .structured = TRUE (equivalent to llm_mutate_structured)
schema <- list(
  type = "object",
  properties = list(
    answer = list(type = "string"),
    confidence = list(type = "number")
  ),
  required = list("answer", "confidence")
)

df |>
  llm_mutate(
    result,
    prompt = "{question}",
    .config = cfg,
    .structured = TRUE,
    .schema = schema
  )

# Structured with shorthand
df |>
  llm_mutate(
    result = "{question}",
    .config = cfg,
    .structured = TRUE,
    .schema = schema
  )

# Soft structured output with XML-like tags
df |>
  llm_mutate(
    result = "Extract the person's age and job from: {question}",
    .config = cfg,
    .tags = c("age", "job")
  )

cities <- tibble::tibble(city = c("Cairo", "Lima"))
cities |>
  llm_mutate(
    geo = "Where is {city}? Give country and continent in their own tags.",
    .config = cfg,
    .system_prompt = paste(
      "Use XML tags for different parts of the answer, but do not nest tags.",
      "Return <country>...</country> and <continent>...</continent>."
    ),
    .tags = c("country", "continent")
  )
}
}
\seealso{
\code{\link[=llm_fn]{llm_fn()}}, \code{\link[=llm_mutate_structured]{llm_mutate_structured()}}, \code{\link[=llm_mutate_tags]{llm_mutate_tags()}},
\code{\link[=llm_parse_structured_col]{llm_parse_structured_col()}}, \code{\link[=llm_parse_tags_col]{llm_parse_tags_col()}},
\code{\link[=call_llm_broadcast]{call_llm_broadcast()}}, \code{\link[=setup_llm_parallel]{setup_llm_parallel()}}
}
