Skip to content

Conversation

@cpsievert
Copy link
Contributor

@cpsievert cpsievert commented Nov 12, 2025

The PR deprecates essentially the entire current (functional) API in favor of a class-based approach (namely QueryChat). The new API looks something like this:

Express

from seaborn import load_dataset
from shiny.express import render, ui
from querychat.express import QueryChat

titanic = load_dataset("titanic")

qc = QueryChat(titanic, "titanic")
qc.sidebar("chat")

with ui.card(fill=True):
    with ui.card_header():
        @render.text
        def title():
            return qc.title() or "Titanic Dataset"

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

Core

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

titanic = load_dataset("titanic")

qc = QueryChat(titanic, "titanic")

app_ui = ui.page_fluid(
    qc.sidebar(),
    ui.output_data_frame("data_table"),
)

def server(input, output, session):
    qc.server()

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


app = App(app_ui, server)

Closes #97

TODO

  • Update reference/examples/docs (maybe in follow up PR)?

@cpsievert cpsievert changed the title feat(pkg-py): First pass at new QueryChat() API feat(pkg-py): First pass at new QueryChat() API Nov 12, 2025
@cpsievert cpsievert requested a review from Copilot November 13, 2025 16:27

This comment was marked as resolved.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@cpsievert cpsievert requested a review from gadenbuie November 13, 2025 16:35
@cpsievert cpsievert marked this pull request as ready for review November 13, 2025 16:36
gadenbuie

This comment was marked as resolved.

@cpsievert

This comment was marked as outdated.

@gadenbuie

This comment was marked as resolved.

This comment was marked as resolved.

Copy link
Contributor

@gadenbuie gadenbuie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started reviewing but have talked myself into thinking we should do a clean break API change rather than try to maintain the older functions in a deprecated state. (See #101 (comment))

Comment on lines +8 to +9
"QueryChat",
"express",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include express in __all__? I kind of think it'd be better to require explicitly reaching into querychat.express.

Suggested change
"QueryChat",
"express",
"QueryChat",

Copy link
Contributor Author

@cpsievert cpsievert Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By including express here, it makes this possible:

import querychat

querychat.express.QueryChat

or, somewhat equivalently:

from querychat import *

express.QueryChat

It's the same reason why we include reactive, ui, etc in shiny/__init__.py...

client: chatlas.Chat


def init_impl(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you using this pattern -- having QueryChat methods shell out to _impl functions -- to maintain the deprecated functions or because it's a structure you prefer?

If it's primarily about the deprecated functions, I'm inclined to say that we should just have a clean break and do a hard deprecation immediately.

  1. The new syntax is so much better; I want to get people into the new flow as quickly as possible.
  2. Deprecation warnings are easy to miss; the breaking change forces code upgrades. People can pin to previous versions if they're not ready to migrate yet.
  3. We can write up a migration guide now as part of this PR. We tend to rely on deprecation warnings to guide through changes, but I think as a user it's a better experience to be pointed to a page that describes the changes, why they happened and how to migrate.
  4. We can keep the deprecated functions as shells that error out and point to that article.

Overall, I think that a clean break from the old API would be better for us in maintaining the code as well as for our users.

Copy link
Contributor Author

@cpsievert cpsievert Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, I started with soft deprecation since it seemed like the least controversial approach, but you're right that hard deprecating simplifies things significantly enough that I'm up for it 👍.

See 732d699

@cpsievert cpsievert changed the title feat(pkg-py): First pass at new QueryChat() API feat(pkg-py): Add new QueryChat() API; hard deprecate old API Nov 14, 2025
@cpsievert cpsievert requested a review from Copilot November 14, 2025 23:20

This comment was marked as off-topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Revisit Python API

3 participants