QueryChat

QueryChat(
    data_source=None,
    table_name=None,
    *,
    id=None,
    greeting=None,
    client=None,
    tools=DEFAULT_TOOLS,
    data_dict=None,
    extra_instructions=None,
    prompt_template=None,
    categorical_threshold=20,
    data_description=None,
)

Create a QueryChat instance for Shiny applications.

QueryChat enables natural language interaction with your data through an LLM-powered chat interface. It can be used in Shiny applications, as a standalone chat client, or in an interactive console.

Examples

Basic Shiny app:

from querychat import QueryChat

qc = QueryChat(my_dataframe, "my_data")
qc.app()

Standalone chat client:

from querychat import QueryChat
import pandas as pd

df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
qc = QueryChat(df, "my_data")

# Get a chat client with all tools
client = qc.client()
response = client.chat("What's the average of column a?")

# Start an interactive console chat
qc.console()

Privacy-focused mode: Only allow dashboard filtering, ensuring the LLM can’t see any raw data.

qc = QueryChat(df, "my_data", tools="filter")
qc.app()

Parameters

Name Type Description Default
data_source IntoFrame | sqlalchemy.Engine | ibis.Table | None Either a Narwhals-compatible data frame (e.g., Polars or Pandas) or a SQLAlchemy engine containing the table to query against. None
table_name str | None If a data_source is a data frame, a name to use to refer to the table in SQL queries (usually the variable name of the data frame, but it doesn’t have to be). If a data_source is a SQLAlchemy engine, the table_name is the name of the table in the database to query against. None
id Optional[str] An optional ID for the QueryChat module. If not provided, an ID will be generated based on the table_name. None
greeting Optional[str | Path] A string in Markdown format, containing the initial message. If a pathlib.Path object is passed, querychat will read the contents of the path into a string with .read_text(). You can use querychat.greeting() to help generate a greeting from a querychat configuration. If no greeting is provided, one will be generated at the start of every new conversation. None
client Optional[str | chatlas.Chat] A chatlas.Chat object or a string to be passed to chatlas.ChatAuto()’s provider_model parameter, describing the provider and model combination to use (e.g. "openai/gpt-4.1", “anthropic/claude-sonnet-4-5”, “google/gemini-2.5-flash”. etc). If client is not provided, querychat consults the QUERYCHAT_CLIENT environment variable. If that is not set, it defaults to "openai". None
tools TOOL_GROUPS | tuple[TOOL_GROUPS, …] | None Which querychat tools to include in the chat client by default. Can be: - A single tool string: "filter" or "query" - A tuple of tools: ("filter", "query", "visualize") - None or () to disable all tools Default is ("filter", "query"). The visualization tool ("visualize") can be opted into by including it in the tuple. Pass only "filter" to restrict the LLM to dashboard filtering, omitting both the "query" and "visualize" tools so the LLM cannot access or display any raw data values. The legacy name "update" is still accepted as an alias for "filter". The tools can be overridden per-client by passing a different tools parameter to the .client() method. DEFAULT_TOOLS
data_dict DataDict | str | Path | None A :class:~querychat.DataDict instance, or a path (str or pathlib.Path) to a YAML file, that provides rich per-table and per-column metadata. When set, documented columns use the dict’s values, range, and description fields instead of querying the data source for statistics, which speeds up schema generation and improves LLM context. Supersedes data_description. None
extra_instructions Optional[str | Path] Additional instructions for the chat model. If a pathlib.Path object is passed, querychat will read the contents of the path into a string with .read_text(). None
prompt_template Optional[str | Path] Path to or a string of a custom prompt file. If not provided, the default querychat template will be used. This should be a Markdown file that contains the system prompt template. The mustache template can use the following variables: - {db_engine}: The database engine used (e.g., “DuckDB”) - {schema}: The schema of the data source, generated by data_source.get_schema() - {data_description}: The optional data description provided - {extra_instructions}: Any additional instructions provided None
categorical_threshold int Threshold for determining if a column is categorical based on number of unique values. 20
data_description Optional[str | Path] Optional plain-text or Markdown description of the data, as a string or file path. Superseded by data_dict for new code. None

Attributes

Name Description
data_source Removed. Use add_table() and remove_table() to manage tables.
greeter Greeting configuration and generator for this QueryChat instance.
system_prompt Get the system prompt.

Methods

Name Description
add_table Add or replace a table in the QueryChat instance.
add_tables Add multiple tables from a SQLAlchemy engine or Ibis backend in a single call.
app Quickly chat with a dataset.
cleanup Clean up resources associated with all data sources.
client Create a chat client with registered tools.
console Launch an interactive console chat with the data.
generate_greeting Generate a welcome greeting for the chat.
remove_table Remove a table from the QueryChat instance.
server Initialize Shiny server logic.
sidebar Create a sidebar containing the querychat UI.
table_names Return the names of all registered tables.
ui Create the UI for the querychat component.

add_table

QueryChat.add_table(
    data_source,
    table_name,
    *,
    replace=False,
    include_in_greeting=False,
)

Add or replace a table in the QueryChat instance.

Parameters

Name Type Description Default
data_source IntoFrame | sqlalchemy.Engine | BaseBoard The data source (DataFrame, LazyFrame, database connection, or pins board). required
table_name str Name for the table. required
replace bool If True, replace an existing table with the same name. If False (default), raise ValueError if the table already exists. False
include_in_greeting bool If True, include this table’s schema in the greeting system prompt. False

Raises

Name Type Description
TypeError If include_in_greeting is not a bool.
ValueError If table_name already exists (and replace=False) or is invalid.
RuntimeError If called after server() has been invoked.

add_tables

QueryChat.add_tables(
    data_source,
    tables=None,
    *,
    replace=False,
    include_in_greeting=False,
)

Add multiple tables from a SQLAlchemy engine or Ibis backend in a single call.

Unlike calling :meth:add_table repeatedly, this method builds the system prompt exactly once after all tables have been staged, avoiding N-1 spurious intermediate rebuilds.

Parameters

Name Type Description Default
data_source sqlalchemy.Engine | SQLBackend A SQLAlchemy engine or Ibis SQL backend. Pass individual DataFrames or other sources via :meth:add_table. required
tables list[str] | None Table names to register. When None, all tables returned by the backend’s table-discovery method are used. None
replace bool If True, replace any existing table whose name appears in tables. If False (default), raise ValueError if any name already exists. False
include_in_greeting bool | list[str] True to include all added tables in the greeting, False (default) for none, or a list of table names to include. Any other type raises TypeError. False

Raises

Name Type Description
TypeError If data_source is not a sqlalchemy.Engine or Ibis SQL backend.
ValueError If the resolved table list is empty, any name is invalid, or any name already exists (and replace=False).
RuntimeError If called after :meth:server has been invoked.

Examples

Register all tables from a SQLAlchemy engine:

>>> qc = QueryChat()
>>> qc.add_tables(engine)

Register a specific subset:

>>> qc.add_tables(engine, ["orders", "customers"])

Register all tables from an Ibis backend:

>>> import ibis
>>> backend = ibis.duckdb.connect("mydb.duckdb")
>>> qc.add_tables(backend)

app

QueryChat.app(bookmark_store='url')

Quickly chat with a dataset.

Creates a Shiny app with a chat sidebar and data view – providing a quick-and-easy way to start chatting with your data.

Parameters

Name Type Description Default
bookmark_store Literal['url', 'server', 'disable'] The bookmarking store to use for the Shiny app. Options are: - "url": Store bookmarks in the URL (default). - "server": Store bookmarks on the server. - "disable": Disable bookmarking. 'url'

Returns

Name Type Description
App A Shiny App object that can be run with app.run() or served with shiny run.

cleanup

QueryChat.cleanup()

Clean up resources associated with all data sources.

client

QueryChat.client(
    tools=MISSING,
    update_dashboard=None,
    reset_dashboard=None,
    visualize=None,
)

Create a chat client with registered tools.

Parameters

Name Type Description Default
tools TOOL_GROUPS | tuple[TOOL_GROUPS, …] | None | MISSING_TYPE Which tools to include: "filter", "query", "visualize", or a combination. The legacy name "update" is still accepted as an alias for "filter". MISSING
update_dashboard Callable[[UpdateDashboardData], None] | None Callback when update_dashboard tool succeeds. None
reset_dashboard ResetDashboardCallback | None Callback when reset_dashboard tool is invoked. None
visualize Callable[[VisualizeData], None] | None Callback when visualize tool succeeds. None

Returns

Name Type Description
chatlas.Chat A configured chat client.

console

QueryChat.console(new=False, tools='query', **kwargs)

Launch an interactive console chat with the data.

generate_greeting

QueryChat.generate_greeting(echo='none')

Generate a welcome greeting for the chat.

remove_table

QueryChat.remove_table(table_name)

Remove a table from the QueryChat instance.

Parameters

Name Type Description Default
table_name str Name of the table to remove. required

Raises

Name Type Description
ValueError If table doesn’t exist or is the last remaining table.
RuntimeError If called after server() has been invoked.

server

QueryChat.server(client=MISSING, enable_bookmarking=False, id=None)

Initialize Shiny server logic.

This method is intended for use in Shiny Code mode, where the user must explicitly call .server() within the Shiny server function. In Shiny Express mode, you can use querychat.express.QueryChat instead of querychat.QueryChat, which calls .server() automatically.

Parameters

Name Type Description Default
client str | chatlas.Chat | MISSING_TYPE Optional chat client to use for this session. If provided, overrides any client set at initialization time for this call only. This is useful for the deferred pattern where the client cannot be created at initialization time (e.g., when using Posit Connect managed OAuth credentials that require session access). MISSING
enable_bookmarking bool Whether to enable bookmarking for the querychat module. False
id Optional[str] Optional module ID for the QueryChat instance. If not provided, will use the ID provided at initialization. This must match the ID used in the .ui() or .sidebar() methods. None

Examples

from shiny import App, render, ui
from seaborn import load_dataset
from querychat import QueryChat

titanic = load_dataset("titanic")

qc = QueryChat(titanic, "titanic")


def app_ui(request):
    return ui.page_sidebar(
        qc.sidebar(),
        ui.card(
            ui.card_header(ui.output_text("title")),
            ui.output_data_frame("data_table"),
        ),
        title="Titanic QueryChat App",
        fillable=True,
    )


def server(input, output, session):
    qc_vals = qc.server(enable_bookmarking=True)

    @render.data_frame
    def data_table():
        return qc_vals.df()

    @render.text
    def title():
        return qc_vals.title() or "My Data"


app = App(app_ui, server, bookmark_store="url")

Returns

Name Type Description
ServerValues[IntoFrameT] A ServerValues dataclass containing session-specific reactive values and the chat client. See ServerValues documentation for details on the available attributes.

sidebar

QueryChat.sidebar(width=400, height='100%', fillable=True, id=None, **kwargs)

Create a sidebar containing the querychat UI.

Parameters

Name Type Description Default
width int Width of the sidebar in pixels. 400
height str Height of the sidebar. '100%'
fillable bool Whether the sidebar should be fillable. Default is True. True
id Optional[str] Optional ID for the QueryChat instance. If not provided, will use the ID provided at initialization. None
**kwargs Additional arguments passed to shiny.ui.sidebar(). {}

Returns

Name Type Description
ui.Sidebar A sidebar UI component.

table_names

QueryChat.table_names()

Return the names of all registered tables.

Returns

Name Type Description
list[str] List of table names in the order they were added.

ui

QueryChat.ui(id=None, **kwargs)

Create the UI for the querychat component.

Parameters

Name Type Description Default
id Optional[str] Optional ID for the QueryChat instance. If not provided, will use the ID provided at initialization. None
**kwargs Additional arguments to pass to shinychat.chat_ui(). {}

Returns

Name Type Description
A UI component.