Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 39 additions & 27 deletions pkg-r/R/QueryChat.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#' library(querychat)
#'
#' # Create a QueryChat object
#' qc <- QueryChat$new(mtcars, "mtcars")
#' qc <- QueryChat$new(mtcars)
#'
#' # Quick start: run a complete app
#' qc$app()
Expand All @@ -46,18 +46,18 @@
#' @examples
#' \dontrun{
#' # Basic usage with a data frame
#' qc <- QueryChat$new(mtcars, "mtcars")
#' qc <- QueryChat$new(mtcars)
#' app <- qc$app()
#'
#' # With a custom greeting
#' greeting <- "Welcome! Ask me about the mtcars dataset."
#' qc <- QueryChat$new(mtcars, "mtcars", greeting = greeting)
#' qc <- QueryChat$new(mtcars, greeting = greeting)
#'
#' # With a specific LLM provider
#' qc <- QueryChat$new(mtcars, "mtcars", client = "anthropic/claude-sonnet-4-5")
#' qc <- QueryChat$new(mtcars, client = "anthropic/claude-sonnet-4-5")
#'
#' # Generate a greeting for reuse
#' qc <- QueryChat$new(mtcars, "mtcars")
#' qc <- QueryChat$new(mtcars)
#' greeting <- qc$generate_greeting(echo = "text")
#' # Save greeting for next time
#' writeLines(greeting, "mtcars_greeting.md")
Expand All @@ -82,8 +82,9 @@ QueryChat <- R6::R6Class(
#' connection).
#' @param table_name A string specifying the table name to use in SQL queries.
#' If `data_source` is a data.frame, this is the name to refer to it by in
#' queries (typically the variable name). If `data_source` is a database
#' connection, this is the name of the table in the database.
#' queries (typically the variable name). If not provided, will be inferred
#' from the variable name for data.frame inputs. For database connections,
#' this parameter is required.
#' @param ... Additional arguments (currently unused).
#' @param id Optional module ID for the QueryChat instance. If not provided,
#' will be auto-generated from `table_name`. The ID is used to namespace
Expand Down Expand Up @@ -119,12 +120,13 @@ QueryChat <- R6::R6Class(
#' @examples
#' \dontrun{
#' # Basic usage
#' qc <- QueryChat$new(mtcars)
#'
#' qc <- QueryChat$new(mtcars, "mtcars")
#'
#' # With options
#' qc <- QueryChat$new(
#' mtcars,
#' "mtcars",
#' greeting = "Welcome to the mtcars explorer!",
#' client = "openai/gpt-4o",
#' data_description = "Motor Trend car road tests dataset"
Expand All @@ -138,7 +140,7 @@ QueryChat <- R6::R6Class(
#' }
initialize = function(
data_source,
table_name,
table_name = rlang::missing_arg(),
...,
id = NULL,
greeting = NULL,
Expand All @@ -151,6 +153,10 @@ QueryChat <- R6::R6Class(
) {
rlang::check_dots_empty()

if (rlang::is_missing(table_name) && is.data.frame(data_source)) {
table_name <- deparse1(substitute(data_source))
}

private$.data_source <- normalize_data_source(data_source, table_name)

# Validate table name
Expand Down Expand Up @@ -225,7 +231,7 @@ QueryChat <- R6::R6Class(
#' \dontrun{
#' library(querychat)
#'
#' qc <- QueryChat$new(mtcars, "mtcars")
#' qc <- QueryChat$new(mtcars)
#' qc$app()
#' }
#'
Expand Down Expand Up @@ -255,7 +261,7 @@ QueryChat <- R6::R6Class(
#' \dontrun{
#' library(querychat)
#'
#' qc <- QueryChat$new(mtcars, "mtcars")
#' qc <- QueryChat$new(mtcars)
#' app <- qc$app_obj()
#' shiny::runApp(app)
#' }
Expand Down Expand Up @@ -386,7 +392,7 @@ QueryChat <- R6::R6Class(
#'
#' @examples
#' \dontrun{
#' qc <- QueryChat$new(mtcars, "mtcars")
#' qc <- QueryChat$new(mtcars)
#'
#' ui <- page_sidebar(
#' qc$sidebar(),
Expand Down Expand Up @@ -415,7 +421,7 @@ QueryChat <- R6::R6Class(
#'
#' @examples
#' \dontrun{
#' qc <- QueryChat$new(mtcars, "mtcars")
#' qc <- QueryChat$new(mtcars)
#'
#' ui <- fluidPage(
#' qc$ui()
Expand Down Expand Up @@ -443,7 +449,7 @@ QueryChat <- R6::R6Class(
#'
#' @examples
#' \dontrun{
#' qc <- QueryChat$new(mtcars, "mtcars")
#' qc <- QueryChat$new(mtcars)
#'
#' server <- function(input, output, session) {
#' qc_vals <- qc$server()
Expand Down Expand Up @@ -484,14 +490,14 @@ QueryChat <- R6::R6Class(
#' @examples
#' \dontrun{
#' # Create QueryChat object
#' qc <- QueryChat$new(mtcars, "mtcars")
#' 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, "mtcars", greeting = "mtcars_greeting.md")
#' qc2 <- QueryChat$new(mtcars, greeting = "mtcars_greeting.md")
#' }
generate_greeting = function(echo = c("none", "output")) {
echo <- match.arg(echo)
Expand Down Expand Up @@ -531,7 +537,6 @@ QueryChat <- R6::R6Class(
)
)


#' QueryChat convenience functions
#'
#' Convenience functions for wrapping [QueryChat] creation (i.e., `querychat()`)
Expand All @@ -541,8 +546,9 @@ QueryChat <- R6::R6Class(
#' connection).
#' @param table_name A string specifying the table name to use in SQL queries.
#' If `data_source` is a data.frame, this is the name to refer to it by in
#' queries (typically the variable name). If `data_source` is a database
#' connection, this is the name of the table in the database.
#' queries (typically the variable name). If not provided, will be inferred
#' from the variable name for data.frame inputs. For database connections,
#' this parameter is required.
#' @param ... Additional arguments (currently unused).
#' @param id Optional module ID for the QueryChat instance. If not provided,
#' will be auto-generated from `table_name`. The ID is used to namespace
Expand Down Expand Up @@ -581,32 +587,31 @@ QueryChat <- R6::R6Class(
#' @examples
#' \dontrun{
#' # Quick start - chat with mtcars dataset in one line
#' querychat_app(mtcars, "mtcars")
#' querychat_app(mtcars)
#'
#' # Add options
#' querychat_app(
#' mtcars,
#' "mtcars",
#' greeting = "Welcome to the mtcars explorer!",
#' client = "openai/gpt-4o"
#' )
#'
#' # Chat with a database table
#' # Chat with a database table (table_name required)
#' library(DBI)
#' conn <- dbConnect(RSQLite::SQLite(), ":memory:")
#' dbWriteTable(conn, "mtcars", mtcars)
#' querychat_app(conn, "mtcars")
#'
#' # Create QueryChat class object
#' qc <- querychat(mtcars, "mtcars")
#' qc <- querychat(mtcars)
#'
#' # Run the app later
#' qc$app()
#'
#' }
querychat <- function(
data_source,
table_name,
table_name = rlang::missing_arg(),
...,
id = NULL,
greeting = NULL,
Expand All @@ -617,6 +622,10 @@ querychat <- function(
prompt_template = NULL,
cleanup = NA
) {
if (rlang::is_missing(table_name) && is.data.frame(data_source)) {
table_name <- deparse1(substitute(data_source))
}

QueryChat$new(
data_source = data_source,
table_name = table_name,
Expand All @@ -632,7 +641,6 @@ querychat <- function(
)
}


#' @rdname querychat-convenience
#' @param bookmark_store The bookmarking storage method. Passed to
#' [shiny::enableBookmarking()]. If `"url"` or `"server"`, the chat state
Expand All @@ -642,7 +650,7 @@ querychat <- function(
#' @export
querychat_app <- function(
data_source,
table_name,
table_name = rlang::missing_arg(),
...,
id = NULL,
greeting = NULL,
Expand All @@ -654,6 +662,11 @@ querychat_app <- function(
cleanup = TRUE,
bookmark_store = "url"
) {

if (rlang::is_missing(table_name) && is.data.frame(data_source)) {
table_name <- deparse1(substitute(data_source))
}

qc <- QueryChat$new(
data_source = data_source,
table_name = table_name,
Expand All @@ -671,7 +684,6 @@ querychat_app <- function(
qc$app(bookmark_store = bookmark_store)
}


normalize_data_source <- function(data_source, table_name) {
if (is_data_source(data_source)) {
data_source
Expand Down
16 changes: 3 additions & 13 deletions pkg-r/R/data_source.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,18 @@
#' @return A querychat_data_source object
#' @keywords internal
#' @export
as_querychat_data_source <- function(x, table_name = NULL, ...) {
as_querychat_data_source <- function(x, table_name, ...) {
UseMethod("as_querychat_data_source")
}

#' @export
as_querychat_data_source.data.frame <- function(x, table_name = NULL, ...) {
if (is.null(table_name)) {
# Infer table name from dataframe name, if not already added
table_name <- deparse(substitute(x))
if (is.null(table_name) || table_name == "NULL" || table_name == "x") {
rlang::abort(
"Unable to infer table name. Please specify `table_name` argument explicitly."
)
}
}

as_querychat_data_source.data.frame <- function(x, table_name, ...) {
is_table_name_ok <- is.character(table_name) &&
length(table_name) == 1 &&
grepl("^[a-zA-Z][a-zA-Z0-9_]*$", table_name, perl = TRUE)
if (!is_table_name_ok) {
rlang::abort(
"`table_name` argument must be a string containing a valid table name."
"`table_name` argument must be a string containing alphanumeric characters and underscores, starting with a letter."
)
}

Expand Down
4 changes: 2 additions & 2 deletions pkg-r/R/querychat-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
#' ```r
#' library(querychat)
#'
#' # Create a QueryChat object
#' qc <- QueryChat$new(mtcars, "mtcars")
#' # Create a QueryChat object (table name inferred from variable)
#' qc <- QueryChat$new(mtcars)
#'
#' # Option 1: Run a complete app with sensible defaults
#' qc$app()
Expand Down
12 changes: 4 additions & 8 deletions pkg-r/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ The fastest way to get started is with the built-in app:
```r
library(querychat)

qc <- QueryChat$new(mtcars, "mtcars")
qc <- QueryChat$new(mtcars)
qc$app()
```

Expand All @@ -43,7 +43,7 @@ library(bslib)
library(querychat)

# 1. Create a QueryChat instance with your data
qc <- QueryChat$new(mtcars, "mtcars")
qc <- QueryChat$new(mtcars)

ui <- page_sidebar(
# 2. Use qc$sidebar() in a bslib::page_sidebar.
Expand Down Expand Up @@ -139,14 +139,14 @@ This gives the user a few ideas to explore on their own.
You can use the `$generate_greeting()` method to help create a greeting:

```r
qc <- QueryChat$new(mtcars, "mtcars")
qc <- QueryChat$new(mtcars)
greeting <- qc$generate_greeting(echo = "text")

# Save it for reuse
writeLines(greeting, "greeting.md")

# Then use it in your app
qc <- QueryChat$new(mtcars, "mtcars", greeting = "greeting.md")
qc <- QueryChat$new(mtcars, greeting = "greeting.md")
```

Alternatively, you can completely suppress the greeting by passing `greeting = ""`.
Expand Down Expand Up @@ -200,7 +200,6 @@ which you can then pass via:
```r
qc <- QueryChat$new(
mtcars,
"mtcars",
data_description = "data_description.md"
)
```
Expand All @@ -214,7 +213,6 @@ You can add additional instructions of your own to the end of the system prompt,
```r
qc <- QueryChat$new(
mtcars,
"mtcars",
extra_instructions = c(
"You're speaking to a British audience--please use appropriate spelling conventions.",
"Use lots of emojis! 😃 Emojis everywhere, 🌍 emojis forever. ♾️",
Expand All @@ -236,7 +234,6 @@ library(ellmer)

qc <- QueryChat$new(
mtcars,
"mtcars",
client = ellmer::chat_anthropic(model = "claude-3-7-sonnet-latest")
)
```
Expand All @@ -249,7 +246,6 @@ Alternatively, you can use a provider-model string, which will be passed to `ell
```r
qc <- QueryChat$new(
mtcars,
"mtcars",
client = "anthropic/claude-3-7-sonnet-latest"
)
```
Expand Down
2 changes: 1 addition & 1 deletion pkg-r/inst/examples-shiny/01-hello-app/app.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ library(querychat)
library(palmerpenguins)

# Create a QueryChat object and generate a complete app with $app()
qc <- QueryChat$new(penguins, "penguins")
qc <- QueryChat$new(penguins)
qc$app()

# That's it! The app includes:
Expand Down
2 changes: 0 additions & 2 deletions pkg-r/inst/examples-shiny/02-sidebar-app/app.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ Try asking:
# Create QueryChat object with custom options
qc <- QueryChat$new(
penguins,
"penguins",
greeting = greeting,
data_description = paste(
"The Palmer Penguins dataset contains measurements of bill",
Expand All @@ -34,7 +33,6 @@ qc <- QueryChat$new(
)
)


# Define custom UI with sidebar
ui <- page_sidebar(
title = "Palmer Penguins Chat Explorer",
Expand Down
Loading
Loading