% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/QueryChat.R
\name{QueryChat}
\alias{QueryChat}
\title{QueryChat: Interactive Data Querying with Natural Language}
\description{
\code{QueryChat} is an R6 class built on Shiny, shinychat, and ellmer to enable
interactive querying of data using natural language. It leverages large
language models (LLMs) to translate user questions into SQL queries, execute
them against a data source (data frame or database), and various ways of
accessing/displaying the results.

The \code{QueryChat} class takes your data (a data frame or database connection)
as input and provides methods to:
\itemize{
\item Generate a chat UI for natural language queries (e.g., \verb{$app()},
\verb{$sidebar()})
\item Initialize server logic that returns session-specific reactive values (via
\verb{$server()})
\item Access reactive data, SQL queries, and titles through the returned server
values
}
}
\section{Usage in Shiny Apps}{


\if{html}{\out{<div class="sourceCode r">}}\preformatted{library(querychat)

# Create a QueryChat object
qc <- QueryChat$new(mtcars)

# Quick start: run a complete app
qc$app()

# Or build a custom Shiny app
ui <- page_sidebar(
  qc$sidebar(),
  verbatimTextOutput("sql"),
  dataTableOutput("data")
)

server <- function(input, output, session) \{
  qc_vals <- qc$server()

  output$sql <- renderText(qc_vals$sql())
  output$data <- renderDataTable(qc_vals$df())
\}

shinyApp(ui, server)
}\if{html}{\out{</div>}}
}

\examples{
\dontshow{if (rlang::is_installed("duckdb") || rlang::is_installed("RSQLite")) withAutoprint(\{ # examplesIf}
# Basic usage with a data frame
qc <- QueryChat$new(mtcars)
\dontrun{
app <- qc$app()
}

# With a custom greeting
greeting <- "Welcome! Ask me about the mtcars dataset."
qc <- QueryChat$new(mtcars, greeting = greeting)

# With a specific LLM provider
qc <- QueryChat$new(mtcars, client = "anthropic/claude-sonnet-4-5")

# Generate a greeting for reuse (requires internet/API access)
\dontrun{
qc <- QueryChat$new(mtcars)
greeting <- qc$generate_greeting(echo = "text")
# Save greeting for next time
writeLines(greeting, "mtcars_greeting.md")
}

# Or specify greeting and additional options at initialization
qc <- QueryChat$new(
  mtcars,
  greeting = "Welcome to the mtcars explorer!",
  client = "openai/gpt-4o",
  data_description = "Motor Trend car road tests dataset"
)
\dontshow{\}) # examplesIf}
\dontshow{if (rlang::is_installed("RSQLite")) withAutoprint(\{ # examplesIf}
# Create a QueryChat object from a database connection
# 1. Set up the database connection
con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")

# 2. (For this demo) Create a table in the database
DBI::dbWriteTable(con, "mtcars", mtcars)

# 3. Pass the connection and table name to `QueryChat`
qc <- QueryChat$new(con, "mtcars")
\dontshow{\}) # examplesIf}
}
\section{Public fields}{
  \if{html}{\out{<div class="r6-fields">}}
  \describe{
    \item{\code{greeting}}{The greeting message displayed to users.}

    \item{\code{id}}{ID for the QueryChat instance.}

    \item{\code{tools}}{The allowed tools for the chat client.}
  }
  \if{html}{\out{</div>}}
}
\section{Active bindings}{
  \if{html}{\out{<div class="r6-active-bindings">}}
  \describe{
    \item{\code{system_prompt}}{Get the system prompt.}

    \item{\code{data_source}}{Get or set the current data source. When setting,
the value is normalized and the system prompt is rebuilt.}
  }
  \if{html}{\out{</div>}}
}
\section{Methods}{
\subsection{Public methods}{
  \itemize{
    \item \href{#method-QueryChat-initialize}{\code{QueryChat$new()}}
    \item \href{#method-QueryChat-client}{\code{QueryChat$client()}}
    \item \href{#method-QueryChat-console}{\code{QueryChat$console()}}
    \item \href{#method-QueryChat-app}{\code{QueryChat$app()}}
    \item \href{#method-QueryChat-app_obj}{\code{QueryChat$app_obj()}}
    \item \href{#method-QueryChat-sidebar}{\code{QueryChat$sidebar()}}
    \item \href{#method-QueryChat-ui}{\code{QueryChat$ui()}}
    \item \href{#method-QueryChat-server}{\code{QueryChat$server()}}
    \item \href{#method-QueryChat-generate_greeting}{\code{QueryChat$generate_greeting()}}
    \item \href{#method-QueryChat-cleanup}{\code{QueryChat$cleanup()}}
    \item \href{#method-QueryChat-clone}{\code{QueryChat$clone()}}
  }
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-initialize"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-initialize}{}}}
\subsection{\code{QueryChat$new()}}{
  Create a new QueryChat object.
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$new(
  data_source,
  table_name = missing_arg(),
  ...,
  id = NULL,
  greeting = NULL,
  client = NULL,
  tools = c("filter", "query"),
  data_description = NULL,
  categorical_threshold = 20,
  extra_instructions = NULL,
  prompt_template = NULL,
  cleanup = NA
)}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{data_source}}{Either a data.frame, a database connection (e.g., DBI
connection), or \code{NULL} to defer setting the data source until later.
When \code{NULL}, the data source must be set via the \verb{$data_source} property
or passed to \verb{$server()} before calling methods that require data access.}
      \item{\code{table_name}}{A string specifying the table name to use in SQL
queries. If \code{data_source} is a data.frame, this is the name to refer to
it by in queries (typically the variable name). If not provided, will
be inferred from the variable name for data.frame inputs. For database
connections or \code{NULL} data sources, this parameter is required.}
      \item{\code{...}}{Additional arguments (currently unused).}
      \item{\code{id}}{Optional module ID for the QueryChat instance. If not provided,
will be auto-generated from \code{table_name}. The ID is used to namespace
the Shiny module.}
      \item{\code{greeting}}{Optional initial message to display to users. Can be a
character string (in Markdown format) or a file path. If not provided,
a greeting will be generated at the start of each conversation using
the LLM, which adds latency and cost. Use \verb{$generate_greeting()} to
create a greeting to save and reuse.}
      \item{\code{client}}{Optional chat client. Can be:
\itemize{
\item An \link[ellmer:Chat]{ellmer::Chat} object
\item A string to pass to \code{\link[ellmer:chat]{ellmer::chat()}} (e.g., \code{"openai/gpt-4o"})
\item \code{NULL} (default): Uses the \code{querychat.client} option, the
\code{QUERYCHAT_CLIENT} environment variable, or defaults to
\code{\link[ellmer:chat_openai]{ellmer::chat_openai()}}
}}
      \item{\code{tools}}{Which querychat tools to include in the chat client, by
default. \code{"filter"} includes the tools for filtering and resetting the
dashboard and \code{"query"} includes the tool for executing SQL queries.
Use \code{tools = "filter"} when you only want the dashboard filtering tools,
or when you want to disable the querying tool entirely to prevent the
LLM from seeing any of the data in your dataset. The legacy name
\code{"update"} is still accepted as an alias for \code{"filter"}.}
      \item{\code{data_description}}{Optional description of the data in plain text or
Markdown. Can be a string or a file path. This provides context to the
LLM about what the data represents.}
      \item{\code{categorical_threshold}}{For text columns, the maximum number of
unique values to consider as a categorical variable. Default is 20.}
      \item{\code{extra_instructions}}{Optional additional instructions for the chat
model in plain text or Markdown. Can be a string or a file path.}
      \item{\code{prompt_template}}{Optional path to or string of a custom prompt
template file. If not provided, the default querychat template will be
used. See the package prompts directory for the default template
format.}
      \item{\code{cleanup}}{Whether or not to automatically run \verb{$cleanup()} when the
Shiny session/app stops. By default, cleanup only occurs if \code{QueryChat}
gets created within a Shiny session. Set to \code{TRUE} to always clean up,
or \code{FALSE} to never clean up automatically.}
    }
    \if{html}{\out{</div>}}
  }
  \subsection{Returns}{
    A new \code{QueryChat} object.
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-client"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-client}{}}}
\subsection{\code{QueryChat$client()}}{
  Create a chat client, complete with registered tools, for the current
data source.
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$client(
  tools = NA,
  update_dashboard = function(query, title) {
 },
  reset_dashboard = function() {
 },
  visualize = function(data) {
 },
  session = NULL
)}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{tools}}{Which querychat tools to include in the chat client.
\code{"filter"} includes the tools for filtering and resetting the dashboard
and \code{"query"} includes the tool for executing SQL queries. By default,
when \code{tools = NA}, the values provided at initialization are used.
The legacy name \code{"update"} is still accepted as an alias for \code{"filter"}.}
      \item{\code{update_dashboard}}{Optional function to call with the \code{query} and
\code{title} generated by the LLM for the \code{update_dashboard} tool.}
      \item{\code{reset_dashboard}}{Optional function to call when the
\code{reset_dashboard} tool is called.}
      \item{\code{visualize}}{Optional function to call with a list containing
\code{ggsql}, \code{title}, and \code{widget_id} when a visualization succeeds.}
      \item{\code{session}}{A Shiny session object. Required when \code{"visualize"} is
in \code{tools} and you want interactive chart rendering. When \code{NULL}
(the default), visualizations still execute but are not rendered
as Shiny outputs.}
    }
    \if{html}{\out{</div>}}
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-console"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-console}{}}}
\subsection{\code{QueryChat$console()}}{
  Launch a console-based chat interface with the data source.
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$console(new = FALSE, ..., tools = "query")}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{new}}{Whether to create a new chat client instance or continue the
conversation from the last console chat session (the default).}
      \item{\code{...}}{Additional arguments passed to the \verb{$client()} method.}
      \item{\code{tools}}{Which querychat tools to include in the chat client. See
\verb{$client()} for details. Ignored when not creating a new chat client.
By default, only the \code{"query"} tool is included, regardless of the
\code{tools} set at initialization.}
    }
    \if{html}{\out{</div>}}
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-app"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-app}{}}}
\subsection{\code{QueryChat$app()}}{
  Create and run a Shiny gadget for chatting with data

Runs a Shiny gadget (designed for interactive use) that provides a
complete interface for chatting with your data using natural language. If
you're looking to deploy this app or run it through some other means, see
\verb{$app_obj()}.

\if{html}{\out{<div class="sourceCode r">}}\preformatted{library(querychat)

qc <- QueryChat$new(mtcars)
qc$app()
}\if{html}{\out{</div>}}
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$app(..., bookmark_store = "url")}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{...}}{Arguments passed to \verb{$app_obj()}.}
      \item{\code{bookmark_store}}{The bookmarking storage method. Passed to
\code{\link[shiny:enableBookmarking]{shiny::enableBookmarking()}}. If \code{"url"} or \code{"server"}, the chat state
(including current query) will be bookmarked. Default is \code{"url"}.}
    }
    \if{html}{\out{</div>}}
  }
  \subsection{Returns}{
    Invisibly returns a list of session-specific values:
\itemize{
\item \code{df}: The final filtered data frame
\item \code{sql}: The final SQL query string
\item \code{title}: The final title
\item \code{client}: The session-specific chat client instance
}
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-app_obj"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-app_obj}{}}}
\subsection{\code{QueryChat$app_obj()}}{
  A streamlined Shiny app for chatting with data

Creates a Shiny app designed for chatting with data, with:
\itemize{
\item A sidebar containing the chat interface
\item A card displaying the current SQL query
\item A card displaying the filtered data table
\item A reset button to clear the query
}

\if{html}{\out{<div class="sourceCode r">}}\preformatted{library(querychat)

qc <- QueryChat$new(mtcars)
app <- qc$app_obj()
shiny::runApp(app)
}\if{html}{\out{</div>}}
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$app_obj(..., bookmark_store = "url")}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{...}}{Additional arguments (currently unused).}
      \item{\code{bookmark_store}}{The bookmarking storage method. Passed to
\code{\link[shiny:enableBookmarking]{shiny::enableBookmarking()}}. If \code{"url"} or \code{"server"}, the chat state
(including current query) will be bookmarked. Default is \code{"url"}.}
    }
    \if{html}{\out{</div>}}
  }
  \subsection{Returns}{
    A Shiny app object that can be run with \code{shiny::runApp()}.
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-sidebar"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-sidebar}{}}}
\subsection{\code{QueryChat$sidebar()}}{
  Create a sidebar containing the querychat UI.

This method generates a \code{\link[bslib:sidebar]{bslib::sidebar()}} component containing the chat
interface, suitable for use with \code{\link[bslib:page_sidebar]{bslib::page_sidebar()}} or similar
layouts.

\if{html}{\out{<div class="sourceCode r">}}\preformatted{qc <- QueryChat$new(mtcars)

ui <- page_sidebar(
  qc$sidebar(),
  # Main content here
)
}\if{html}{\out{</div>}}
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$sidebar(
  ...,
  width = 400,
  height = "100\%",
  fillable = TRUE,
  id = NULL
)}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{...}}{Additional arguments passed to \code{\link[bslib:sidebar]{bslib::sidebar()}}.}
      \item{\code{width}}{Width of the sidebar in pixels. Default is 400.}
      \item{\code{height}}{Height of the sidebar. Default is "100\%".}
      \item{\code{fillable}}{Whether the sidebar should be fillable. Default is
\code{TRUE}.}
      \item{\code{id}}{Optional ID for the QueryChat instance. If not provided, will
use the ID provided at initialization. If using \verb{$sidebar()} in a Shiny
module, you'll need to provide \code{id = ns("your_id")} where \code{ns} is the
namespacing function from \code{\link[shiny:NS]{shiny::NS()}}.}
    }
    \if{html}{\out{</div>}}
  }
  \subsection{Returns}{
    A \code{\link[bslib:sidebar]{bslib::sidebar()}} UI component.
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-ui"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-ui}{}}}
\subsection{\code{QueryChat$ui()}}{
  Create the UI for the querychat chat interface.

This method generates the chat UI component. Typically you'll use
\verb{$sidebar()} instead, which wraps this in a sidebar layout.

\if{html}{\out{<div class="sourceCode r">}}\preformatted{qc <- QueryChat$new(mtcars)

ui <- fluidPage(
  qc$ui()
)
}\if{html}{\out{</div>}}
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$ui(..., id = NULL)}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{...}}{Additional arguments passed to \code{\link[shinychat:chat_ui]{shinychat::chat_ui()}}.}
      \item{\code{id}}{Optional ID for the QueryChat instance. If not provided,
will use the ID provided at initialization. If using \verb{$ui()} in a Shiny
module, you'll need to provide \code{id = ns("your_id")} where \code{ns} is the
namespacing function from \code{\link[shiny:NS]{shiny::NS()}}.}
    }
    \if{html}{\out{</div>}}
  }
  \subsection{Returns}{
    A UI component containing the chat interface.
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-server"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-server}{}}}
\subsection{\code{QueryChat$server()}}{
  Initialize the querychat server logic.

This method must be called within a Shiny server function. It sets up the
reactive logic for the chat interface and returns session-specific
reactive values.

\if{html}{\out{<div class="sourceCode r">}}\preformatted{qc <- QueryChat$new(mtcars)

server <- function(input, output, session) \{
  qc_vals <- qc$server(enable_bookmarking = TRUE)

  output$data <- renderDataTable(qc_vals$df())
  output$query <- renderText(qc_vals$sql())
  output$title <- renderText(qc_vals$title() \%||\% "No Query")
\}
}\if{html}{\out{</div>}}
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$server(
  data_source = NULL,
  client = NULL,
  enable_bookmarking = FALSE,
  ...,
  id = NULL,
  session = shiny::getDefaultReactiveDomain()
)}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{data_source}}{Optional data source to use. If provided, sets the
data_source property before initializing server logic. This is useful
for the deferred pattern where data_source is not known at
initialization time (e.g., when the data source depends on session-
specific authentication).}
      \item{\code{client}}{Optional chat client override for this session. Can be an
\link[ellmer:Chat]{ellmer::Chat} object or a string (e.g., \code{"openai/gpt-4o"}). If provided,
overrides the client set at initialization for this session only —
other sessions are unaffected. This is useful when the client must be
created within a session scope (e.g., Posit Connect managed credentials).}
      \item{\code{enable_bookmarking}}{Whether to enable bookmarking for the chat
state. Default is \code{FALSE}. When enabled, the chat state (including
current query, title, and chat history) will be saved and restored
with Shiny bookmarks. This requires that the Shiny app has bookmarking
enabled via \code{shiny::enableBookmarking()} or the \code{enableBookmarking}
parameter of \code{shiny::shinyApp()}.}
      \item{\code{...}}{Ignored.}
      \item{\code{id}}{Optional module ID for the QueryChat instance. If not provided,
will use the ID provided at initialization. When used in Shiny modules,
this \code{id} should match the \code{id} used in the corresponding UI function
(i.e., \code{qc$ui(id = ns("your_id"))} pairs with \code{qc$server(id = "your_id")}).}
      \item{\code{session}}{The Shiny session object.}
    }
    \if{html}{\out{</div>}}
  }
  \subsection{Returns}{
    A list containing session-specific reactive values and the chat
client with the following elements:
\itemize{
\item \code{df}: Reactive expression returning the current filtered data frame
\item \code{sql}: Reactive value for the current SQL query string
\item \code{title}: Reactive value for the current title
\item \code{client}: The session-specific chat client instance
}
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-generate_greeting"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-generate_greeting}{}}}
\subsection{\code{QueryChat$generate_greeting()}}{
  Generate a welcome greeting for the chat.

By default, \code{QueryChat$new()} generates a greeting at the start of every
new conversation, which is convenient for getting started and
development, but also might add unnecessary latency and cost. Use this
method to generate a greeting once and save it for reuse.

\if{html}{\out{<div class="sourceCode r">}}\preformatted{# Create QueryChat object
qc <- QueryChat$new(mtcars)

# Generate a greeting and save it
greeting <- qc$generate_greeting()
writeLines(greeting, "mtcars_greeting.md")

# Later, use the saved greeting
qc2 <- QueryChat$new(mtcars, greeting = "mtcars_greeting.md")
}\if{html}{\out{</div>}}
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$generate_greeting(echo = c("none", "output"))}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{echo}}{Whether to print the greeting to the console. Options are
\code{"none"} (default, no output) or \code{"output"} (print to console).}
    }
    \if{html}{\out{</div>}}
  }
  \subsection{Returns}{
    The greeting string in Markdown format.
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-cleanup"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-cleanup}{}}}
\subsection{\code{QueryChat$cleanup()}}{
  Clean up resources associated with the data source.

This method releases any resources (e.g., database connections)
associated with the data source. Call this when you are done using the
QueryChat object to avoid resource leaks.

Note: If \code{auto_cleanup} was set to \code{TRUE} in the constructor, this will
be called automatically when the Shiny app stops.
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$cleanup()}
    \if{html}{\out{</div>}}
  }
  \subsection{Returns}{
    Invisibly returns \code{NULL}. Resources are cleaned up internally.
  }
}

\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-QueryChat-clone"></a>}}
\if{latex}{\out{\hypertarget{method-QueryChat-clone}{}}}
\subsection{\code{QueryChat$clone()}}{
  The objects of this class are cloneable with this method.
  \subsection{Usage}{
    \if{html}{\out{<div class="r">}}
    \preformatted{QueryChat$clone(deep = FALSE)}
    \if{html}{\out{</div>}}
  }
  \subsection{Arguments}{
    \if{html}{\out{<div class="arguments">}}
    \describe{
      \item{\code{deep}}{Whether to make a deep clone.}
    }
    \if{html}{\out{</div>}}
  }
}

}
