Releases: posit-dev/querychat
Release list
[py] querychat 0.7.0
New features
-
QueryChat()now supports multiple related tables. Register additional tables withadd_table()and the LLM can reason across all of them — joins, cross-table filters, aggregations. Per-table reactive state (df(),sql(),title()) is accessible viaqc_vals.table("name")on the value returned byserver(). For SQLAlchemy engines and Ibis backends,add_tables()registers all tables (or a named subset) in a single call. (#195)qc = QueryChat(orders_df, "orders") qc.add_table(customers_df, "customers") # Or, register all tables from a SQLAlchemy engine or Ibis backend at once: qc = QueryChat() qc.add_tables(engine) # SQLAlchemy engine qc.add_tables(ibis_backend) # Ibis backend qc_vals = qc.server() qc_vals.table("orders").df() qc_vals.table("customers").sql()
-
A new
DataDicttype — integrating with the data-dict spec — lets you annotate tables and columns with plain-English descriptions loaded from a YAML file. This is the preferred way to provide additional context for the data, especially when multiple tables are relevant. The LLM receives these descriptions when it fetches the schema, helping it interpret ambiguous or domain-specific column names without any extra prompting. (#195)QueryChat(data_dict="data_dict.yaml")
-
Conversation history is now enabled by default.
QueryChat/QueryChatExpresskeep a user's chat around across page reloads and browser sessions, backed by shinychat's history support. The defaultrestore_mode="browser"stores the active conversation in the browser's localStorage, but you can passhistory=shinychat.types.HistoryOptions(restore_mode="url")to restore via a plain, shareable URL instead, orrestore_mode="bookmark"to fold the conversation into a full Shiny bookmark. Disable withhistory=False. -
File attachments are now enabled by default in the Shiny chat UI. Users can attach images, PDFs, and text files to their messages and the LLM will receive them. Disable with
allow_attachments=Falseinmod_ui()orQueryChat.ui(). (#253) -
Added
PinSource, a data source for chatting with datasets pinned to a pins board. Works with parquet, CSV, JSON, and Arrow pins, and uses the pin's title, description, and tags as the default data description. Install the optional dependency withpip install querychat[pins]. (#246) -
The SQL panel in
.app()is now an editable code editor. Users can tweak the generated SQL directly and apply it with Ctrl/Cmd+Enter or by clicking away — no extra button required. The editor stays in sync when the LLM updates the query or the active table changes. (#265)
Improvements
-
Chat greetings now use shinychat's greeting API (requires shinychat >= 0.4.0). A provided
greetingrenders instantly when the app loads, and when nogreetingis given one is generated on demand — now schema-aware, so it can describe the data it's about to help you explore — without being added to the conversation history. Generated greetings are preserved across bookmark/restore. Tables passed toQueryChat()are described in the greeting automatically; opt additional tables in withinclude_in_greeting=Trueonadd_table()/add_tables(), or fine-tune which tables and which template the greeting uses viaqc.greeter. (#249, #261) -
The system prompt is now lighter: full schema is no longer embedded upfront. Instead the LLM fetches per-table schema on demand via the new
querychat_get_schematool — and only when it needs to. When aDataDictis provided, the tool skips columns that already have descriptions, so the LLM only pays for what isn't already documented. (#195) -
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=expandedto restore the previous behavior. (#239) -
Fixed
data_descriptionandextra_instructionsbeing HTML-escaped in the system prompt. Special characters like<,>, and&in developer-provided descriptions and instructions are now passed to the LLM verbatim. (#258)
Breaking Changes
-
The
data_sourceproperty has been removed. Useqc.table("name").data_sourceto read a table's data source, andqc.add_table(df, "name", replace=True)to replace it. Thedata_sourceparameter toserver()(Shiny) has also been removed; calladd_table()beforeserver()instead. (#195) -
.app()'sbookmark_storeparameter has been removed. Passhistory=shinychat.types.HistoryOptions(restore_mode="bookmark")to get the same shareable-bookmark behavior; any otherhistoryvalue disables Shiny-level bookmarking for the generated app..app()defaults torestore_mode="bookmark"when nohistoryis set anywhere, so existing.app()callers keep working without changes. Note this default is a storage-mechanism change, not just a rename: the old default (bookmark_store="url") encoded the entire bookmark state in the URL itself, requiring no server storage; the new default requires server-side bookmark storage (bookmark_store="server"), with just a short state ID in the URL. Deployments that relied on.app()being fully stateless should passhistory=Falseor a non-bookmarkHistoryOptions().
Deprecated
.server()'s andQueryChatExpress'senable_bookmarkingparameter is deprecated in favor ofhistory. Passhistory=shinychat.types.HistoryOptions(restore_mode="bookmark")instead ofenable_bookmarking=Truefor the equivalent behavior.
[r] querychat 0.3.0
New features
-
Added a new
"visualize"tool that lets querychat render interactive charts inline in the chat. When enabled (viatools = c("filter", "query", "visualize")), the LLM can answer questions with charts by writing ggsql (SQL with aVISUALISEclause) instead of only tables. Charts can be expanded to fullscreen and their underlying query inspected. Requires theggsqlpackage andbslib >= 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 = FALSEin 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. Passdata_source = NULLat initialization time, then provide the actual data source via thedata_sourceparameter of$server()or by setting the$data_sourceproperty. This enables use cases where the data source depends on session-specific authentication or per-user database connections. (#202) -
QueryChat$server()now accepts aclientparameter 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, soQueryChat$new(NULL, "table")no longer requires an API key. (#205)
Improvements
-
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(oroptions(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
toolsparameter now uses"filter"as the preferred name (instead of"update") for the dashboard-filtering tool group. The default is nowc("filter", "query"). The legacy name"update"is still accepted everywhere. (#222) -
When a custom
prompt_templateis provided that doesn't contain Mustache references to{{schema}}, the expensiveget_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)
Bug fixes
[py] querychat 0.6.1
New features
- 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=Falsein the UI. (#241)
Improvements
- The
toolsparameter now uses"filter"as the preferred name (instead of"update") for the dashboard-filtering tool group. The default is now("filter", "query"). The legacy name"update"is still accepted everywhere. (#222) - Suggestion prompts now render more reliably as interactive cards across LLM providers. (#236, #238)
- Bumped minimum
ggsqlversion to >=0.3.2. (#233)
[py] querychat 0.6.0
What's New
Features
Bug Fixes
- Gracefully handle Snowflake semantic view discovery errors (#220)
- Add minimum narwhals version constraint (>=2.2.0) (#218)
- Add pyarrow to polars extra for duckdb DataFrame registration (#214)
- Skip schema inference when prompt template doesn't reference schema (#209)
- Polish visualize fullscreen layout (#230)
Other Changes
- Prepare querychat for ggsql 0.3.0 (#225)
- Require latest released versions of ggsql, shiny, shinychat (#229)
- Refactor shared viz assets and footer integration (#228)
- Remove stale ggsql casing guidance (#226)
- Adopt hatch-vcs and add py.typed marker (#215)
Full Changelog: py/v0.5.2...py/v0.6.0
[py] querychat 0.5.1
New features
QueryChat()now supports deferred data source initialization for Shiny Core applications. Passdata_source=Noneat initialization time, then provide the actual data source via thedata_sourceparameter ofserver()or by setting thedata_sourceproperty. This enables use cases where the data source depends on session-specific authentication or per-user database connections. (#202)
[py] querychat 0.5.0
New features
- Added support for Gradio, Dash, and Streamlit web frameworks in addition to Shiny. Import from the new submodules:
from querychat.gradio import QueryChatfrom querychat.dash import QueryChatfrom querychat.streamlit import QueryChat
Each framework's QueryChat provides .app() for quick standalone apps and .ui() for custom layouts. Install framework dependencies with pip extras: pip install querychat[gradio], pip install querychat[dash], or pip install querychat[streamlit]. (#190)
QueryChat()gains support for more data sources:polars.LazyFrame: queries execute lazily viapolars.SQLContext. In this case,.df()et al. methods will return apolars.LazyFrame. (#191)ibis.Table: queries execute lazily via the Ibis backend's SQL interface (DuckDB, PostgreSQL, BigQuery, etc.). In this case,.df()et al. methods will return anibis.Table. (#193)pyarrow.Table: queries execute in-memory viaduckdb. In this case,.df()et al. methods will return apyarrow.Table. (#196)
Improvements
- Improved typing support for return types on
.df()et al. (#196)
Changes
DataFrameSourcemethods now (once again) return the input DataFrame type (e.g.,pandas.DataFrame) instead ofnw.DataFrame. (#196)
[py] querychat 0.4.0
Breaking Changes
- Methods like
execute_query(),get_data(), anddf()now return anarwhals.DataFrameinstead of apandas.DataFrame. This allows querychat to drop itspandasdependency, and for you to use anynarwhals-compatible dataframe of your choosing.- If this breaks existing code, note you can call
.to_native()on the new dataframe value to get yourpandasdataframe back. - Note that
polarsorpandaswill be needed to realize asqlalchemyconnection query as a dataframe. Install withpip install querychat[pandas]orpip install querychat[polars]
- If this breaks existing code, note you can call
New features
-
QueryChat.console()was added to launch interactive console-based chat sessions with your data source, with persistent conversation state across invocations. (#168) -
QueryChat.client()can now create standalone querychat-enabled chat clients with configurable tools and callbacks, enabling use outside of Shiny applications. (#168) -
The tools used in a
QueryChatchatbot are now configurable. Use the newtoolsparameter ofQueryChat()to select either or both"query"or"update"tools. Choosetools=["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.sidebar(),QueryChat.ui(), andQueryChat.server()now support an optionalidparameter to create multiple chat instances from a singleQueryChatobject. (#172)
Improvements
-
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)
[r] querychat 0.2.0
-
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()andQueryChat$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 theengineinDataFrameSource$new()or setquerychat.DataFrameSource.engineoption to choose a global default. (#178) -
QueryChat$sidebar(),QueryChat$ui(), andQueryChat$server()now support an optionalidparameter to enable use within Shiny modules. When used in a module UI function, passid = ns("your_id")wherensis the namespacing function fromshiny::NS(). In the corresponding module server function, pass the unwrapped ID toQueryChat$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
QueryChatchatbot are now configurable. Use the newtoolsparameter ofquerychat()orQueryChat$new()to select either or both"query"or"update"tools. Choosetools = "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 returnsNULLinstead of""(empty string) when no query has been set, aligning with the behavior of$title()for consistency. Most code usingisTruthy()or similar falsy checks will continue working without changes. Code that explicitly checkssql() == ""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_detailsR option or theQUERYCHAT_TOOL_DETAILSenvironment variable. Valid values are"expanded","collapsed", or"default". (#137) -
Added bookmarking support to
QueryChat$server()andquerychat_app(). When bookmarking is enabled (viabookmark_store = "url"or"server"inquerychat_app()or$app_obj(), or viaenable_bookmarking = TRUEin$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 newQueryChat$new()class is now the main entry point (instead ofquerychat_init()) and has methods to replace old functions (e.g.,$sidebar(),$server(), etc). (#109)- In addition,
querychat_data_source()was renamed toas_querychat_data_source(), and remains exported for a developer extension point, but users no longer have to explicitly create a data source. (#109)
- In addition,
-
Added
prompt_templatesupport forquerychat_system_prompt(). (Thank you, @oacar! #37, #45) -
querychat_init()now accepts aclient, replacing the previouscreate_chat_funcargument. (#60)The
clientcan be:- an
ellmer::Chatobject, - a function that returns an
ellmer::Chatobject, - or a provider-model string, e.g.
"openai/gpt-4.1", to be passed toellmer::chat().
If
clientis not provided, querychat will use- the
querychat.clientR option, which can be any of the above options, - the
QUERYCHAT_CLIENTenvironment variable, which should be a provider-model string, - or the default model from
ellmer::chat_openai().
- an
-
querychat_server()now uses ashiny::ExtendedTaskfor streaming the chat response, which allows the dashboard to update and remain responsive while the chat response is streaming in. (#63) -
querychat now requires
ellmerversion 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.querychatclass to the chat container andquerychat_sidebar()adds a.querychat-sidebarclass 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)
[py] querychat 0.3.0
Breaking Changes
-
The entire functional API (i.e.,
init(),sidebar(),server(), etc) has been hard deprecated in favor of a simpler OOP-based API. Namely, the newQueryChat()class is now the main entry point (instead ofinit()) and has methods to replace old functions (e.g.,.sidebar(),.server(), etc). (#101) -
The
.sql()method now returnsNoneinstead of""(empty string) when no query has been set, aligning with the behavior of.title()for consistency. Most code using theoroperator orreq()for falsy checks will continue working without changes. Code that explicitly checkssql() == ""should be updated to use falsy checks (if not sql()) or explicit null checks (if sql() is None). (#146)
New features
-
New
QueryChat.app()method enables quicker/easier chatting with a dataset. (#104) -
Enabled bookmarking by default in both
.app()and.server()methods. In latter case, you'll need to also specify thebookmark_store(either inshiny.App()orshiny.express.app_opts()) for it to take effect. (#104) -
The current SQL query and title can now be programmatically set through the
.sql()and.title()methods ofQueryChat(). (#98, #101) -
New
querychat.datamodule provides sample datasets (titanic()andtips()) to make it easier to get started without external dependencies. (#118) -
Added a
.generate_greeting()method to help you create a greeting message for your querychat bot. (#87) -
Added
querychat_reset_dashboard()tool for easily resetting the dashboard filters when asked by the user. (#81)
Improvements
-
Added rich tool UI support using shinychat development version and chatlas >= 0.11.1. (#67)
-
querychat's system prompt and tool descriptions were rewritten for clarity and future extensibility. (#90)
-
Tool detail cards can now be expanded or collapsed by default when querychat runs a query or updates the dashboard via the
QUERYCHAT_TOOL_DETAILSenvironment variable. Valid values are"expanded","collapsed", or"default". (#137)
[py] querychat v0.2.2
- Fixed another issue with data sources that aren't already narwhals DataFrames (#83)