Added a new "visualize" tool that lets querychat
render interactive charts inline in the chat. When enabled (via
tools = c("filter", "query", "visualize")), the LLM can
answer questions with charts by writing ggsql (SQL with a
VISUALISE clause) instead of only tables. Charts can be
expanded to fullscreen and their underlying query inspected. Requires
the ggsql package and bslib >= 0.11.0.
(#224)
Added stream cancellation support. A stop button now appears
during LLM streaming, allowing users to cancel in-progress responses by
clicking it or pressing Escape. Cancellation is enabled by default and
can be disabled via enable_cancel = FALSE in the UI.
(#241)
Added support for Snowflake Semantic Views. When connected to
Snowflake via DBI, querychat automatically discovers available Semantic
Views and includes their definitions in the system prompt. This helps
the LLM generate correct queries using the SEMANTIC_VIEW()
table function with certified business metrics and dimensions.
(#200)
QueryChat$new() now supports deferred data source.
Pass data_source = NULL at initialization time, then
provide the actual data source via the data_source
parameter of $server() or by setting the
$data_source property. This enables use cases where the
data source depends on session-specific authentication or per-user
database connections. (#202)
QueryChat$server() now accepts a client
parameter for session-scoped chat client overrides. This enables Posit
Connect managed OAuth workflows where API credentials are only available
inside the Shiny server function. The client spec is stored lazily at
construction time and resolved only when needed, so
QueryChat$new(NULL, "table") no longer requires an API key.
(#205)
The query tool result card now starts collapsed by default. Users
can still expand it to see the SQL query and results. Set
QUERYCHAT_TOOL_DETAILS=expanded (or
options(querychat.tool_details = "expanded")) to restore
the previous behavior. (#239)
Query suggestions generated by the LLM now render reliably as clickable cards in the chat. (#236, #238)
The tools parameter now uses "filter"
as the preferred name (instead of "update") for the
dashboard-filtering tool group. The default is now
c("filter", "query"). The legacy name "update"
is still accepted everywhere. (#222)
When a custom prompt_template is provided that
doesn’t contain Mustache references to {{schema}}, the
expensive get_schema() call is now skipped entirely. This
allows users with large databases to avoid slow startup by providing
their own prompt that includes schema information inline (or omits it).
(#208)
DBISource now uses database-agnostic SQL for column and
type detection, replacing LIMIT syntax with
WHERE 1=0 and dbFetch(n=1). This fixes
compatibility with SQL Server and other databases that don’t support
LIMIT. (#112, #197)The update tool now requires that the SQL query returns all columns from the original data source, ensuring that the dashboard can display the complete data frame after filtering or sorting. If the query does not return all columns, an informative error message will be provided. (#180)
Obvious SQL keywords that lead to data modification (e.g.,
INSERT, UPDATE, DELETE,
DROP, etc.) are now prohibited in queries run via the query
tool or update tool, to prevent accidental data changes. If such
keywords are detected, an informative error message will be provided.
(#180)
querychat() and QueryChat$new() now use
either {duckdb} or {SQLite} for the in-memory
database backend for data frames, depending on which package is
installed. If both are installed, {duckdb} will be
preferred. You can explicitly choose the engine in
DataFrameSource$new() or set
querychat.DataFrameSource.engine option to choose a global
default. (#178)
QueryChat$sidebar(), QueryChat$ui(),
and QueryChat$server() now support an optional
id parameter to enable use within Shiny modules. When used
in a module UI function, pass id = ns("your_id") where
ns is the namespacing function from
shiny::NS(). In the corresponding module server function,
pass the unwrapped ID to QueryChat$server(id = "your_id").
This enables multiple independent QueryChat instances from the same
QueryChat object. (#172)
QueryChat$client() can now create standalone
querychat-enabled chat clients with configurable tools and callbacks,
enabling use outside of Shiny applications. (#168)
QueryChat$console() was added to launch interactive
console-based chat sessions with your data source, with persistent
conversation state across invocations. (#168)
The tools used in a QueryChat chatbot are now
configurable. Use the new tools parameter of
querychat() or QueryChat$new() to select
either or both "query" or "update" tools.
Choose tools = "update" if you only want QueryChat to be
able to update the dashboard (useful when you want to be 100% certain
that the LLM will not see any raw data). (#168)
querychat_app() will now only automatically clean up
the data source if QueryChat creates the data source internally from a
data frame. (#164)
Breaking change: The $sql() method
now returns NULL instead of "" (empty string)
when no query has been set, aligning with the behavior of
$title() for consistency. Most code using
isTruthy() or similar falsy checks will continue working
without changes. Code that explicitly checks sql() == ""
should be updated to use falsy checks (e.g.,
!isTruthy(sql())) or explicit null checks
(is.null(sql())). (#146)
Tool detail cards can now be expanded or collapsed by default
when querychat runs a query or updates the dashboard via the
querychat.tool_details R option or the
QUERYCHAT_TOOL_DETAILS environment variable. Valid values
are "expanded", "collapsed", or
"default". (#137)
Added bookmarking support to QueryChat$server() and
querychat_app(). When bookmarking is enabled (via
bookmark_store = "url" or "server" in
querychat_app() or $app_obj(), or via
enable_bookmarking = TRUE in $server()), the
chat state (including current query, title, and chat history) will be
saved and restored with Shiny bookmarks. (#107)
Nearly the entire functional API (i.e.,
querychat_init(), querychat_sidebar(),
querychat_server(), etc) has been hard deprecated in favor
of a simpler OOP-based API. Namely, the new QueryChat$new()
class is now the main entry point (instead of
querychat_init()) and has methods to replace old functions
(e.g., $sidebar(), $server(), etc). (#109)
querychat_data_source() was renamed to
as_querychat_data_source(), and remains exported for a
developer extension point, but users no longer have to explicitly create
a data source. (#109)Added prompt_template support for
querychat_system_prompt(). (Thank you, @oacar! #37, #45)
querychat_init() now accepts a client,
replacing the previous create_chat_func argument. (#60)
The client can be:
ellmer::Chat object,ellmer::Chat object,"openai/gpt-4.1", to
be passed to ellmer::chat().If client is not provided, querychat will use
querychat.client R option, which can be any of the
above options,QUERYCHAT_CLIENT environment variable, which should
be a provider-model string,ellmer::chat_openai().querychat_server() now uses a
shiny::ExtendedTask for streaming the chat response, which
allows the dashboard to update and remain responsive while the chat
response is streaming in. (#63)
querychat now requires ellmer version 0.3.0 or later
and uses rich tool cards for dashboard updates and database queries.
(#65)
New querychat_app() function lets you quickly launch
a Shiny app with a querychat chat interface. (#66)
querychat_ui() now adds a .querychat
class to the chat container and querychat_sidebar() adds a
.querychat-sidebar class to the sidebar, allowing for
easier customization via CSS. (#68)
querychat now uses a separate tool to reset the dashboard. (#80)
querychat_greeting() can be used to generate a
greeting message for your querychat bot. (#87)
querychat’s system prompt and tool descriptions were rewritten for clarity and future extensibility. (#90)