Skip to content

[py] querychat 0.7.0

Latest

Choose a tag to compare

@cpsievert cpsievert released this 10 Jul 21:23
· 3 commits to main since this release

New features

  • QueryChat() now supports multiple related tables. Register additional tables with add_table() and the LLM can reason across all of them — joins, cross-table filters, aggregations. Per-table reactive state (df(), sql(), title()) is accessible via qc_vals.table("name") on the value returned by server(). 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 DataDict type — 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/QueryChatExpress keep a user's chat around across page reloads and browser sessions, backed by shinychat's history support. The default restore_mode="browser" stores the active conversation in the browser's localStorage, but you can pass history=shinychat.types.HistoryOptions(restore_mode="url") to restore via a plain, shareable URL instead, or restore_mode="bookmark" to fold the conversation into a full Shiny bookmark. Disable with history=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=False in mod_ui() or QueryChat.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 with pip 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 greeting renders instantly when the app loads, and when no greeting is 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 to QueryChat() are described in the greeting automatically; opt additional tables in with include_in_greeting=True on add_table()/add_tables(), or fine-tune which tables and which template the greeting uses via qc.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_schema tool — and only when it needs to. When a DataDict is 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=expanded to restore the previous behavior. (#239)

  • Fixed data_description and extra_instructions being 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_source property has been removed. Use qc.table("name").data_source to read a table's data source, and qc.add_table(df, "name", replace=True) to replace it. The data_source parameter to server() (Shiny) has also been removed; call add_table() before server() instead. (#195)

  • .app()'s bookmark_store parameter has been removed. Pass history=shinychat.types.HistoryOptions(restore_mode="bookmark") to get the same shareable-bookmark behavior; any other history value disables Shiny-level bookmarking for the generated app. .app() defaults to restore_mode="bookmark" when no history is 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 pass history=False or a non-bookmark HistoryOptions().

Deprecated

  • .server()'s and QueryChatExpress's enable_bookmarking parameter is deprecated in favor of history. Pass history=shinychat.types.HistoryOptions(restore_mode="bookmark") instead of enable_bookmarking=True for the equivalent behavior.