Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg-py/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

If `client` is not provided, querychat will use the `QUERYCHAT_CLIENT` environment variable, which should be a provider-model string. If the envvar is not set, querychat uses OpenAI with the default model from `chatlas.ChatOpenAI()`.

* `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)

## [0.1.0] - 2025-05-24

Expand Down
3 changes: 2 additions & 1 deletion pkg-py/examples/app-database-sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
"titanic",
greeting=greeting,
data_description=data_desc,
create_chat_callback=use_github_models,
client=use_github_models,
)

# Create UI
Expand All @@ -48,6 +48,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
),
title="querychat with Python (SQLite)",
fillable=True,
class_="bslib-page-dashboard",
)


Expand Down
3 changes: 2 additions & 1 deletion pkg-py/examples/app-dataframe-pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
"titanic",
greeting=greeting,
data_description=data_desc,
create_chat_callback=use_github_models,
client=use_github_models,
)

# Create UI
Expand All @@ -39,6 +39,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
),
title="querychat with Python",
fillable=True,
class_="bslib-page-dashboard",
)


Expand Down
12 changes: 9 additions & 3 deletions pkg-py/examples/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
querychat_config = qc.init(
data_source=titanic,
table_name="titanic",
create_chat_callback=use_github_models,
client=use_github_models,
)

# Create UI
Expand All @@ -32,7 +32,13 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
# Alternatively, use qc.ui(id) elsewhere if you don't want your
# chat interface to live in a sidebar.
qc.sidebar("chat"),
ui.output_data_frame("data_table"),
ui.card(
ui.card_header("Titanic Data"),
ui.output_data_frame("data_table"),
fill=True,
),
fillable=True,
class_="bslib-page-dashboard"
)


Expand All @@ -49,4 +55,4 @@ def data_table():


# Create Shiny app
app = App(app_ui, server)
app = App(app_ui, server)
5 changes: 2 additions & 3 deletions pkg-py/src/querychat/querychat.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,7 @@ def mod_ui() -> ui.TagList:

return ui.TagList(
ui.include_css(css_path),
# Chat interface goes here - placeholder for now
# This would need to be replaced with actual chat UI components
ui.chat_ui("chat"),
ui.chat_ui("chat", class_="querychat"),
)


Expand Down Expand Up @@ -494,6 +492,7 @@ def sidebar(
mod_ui(id),
width=width,
height=height,
class_="querychat-sidebar",
**kwargs,
)

Expand Down
96 changes: 9 additions & 87 deletions pkg-py/src/querychat/static/css/styles.css
Original file line number Diff line number Diff line change
@@ -1,93 +1,15 @@
:root {
--bslib-sidebar-main-bg: #f8f8f8;
}

.querychat-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}

.querychat-messages {
flex: 1;
overflow-y: auto;
padding: 10px;
display: flex;
flex-direction: column;
}

.querychat-input-container {
display: flex;
padding: 10px;
border-top: 1px solid #ccc;
}

.querychat-input {
flex: 1;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
resize: none;
min-height: 40px;
margin-right: 8px;
}

.querychat-send-button {
padding: 8px 16px;
background-color: #0d6efd;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}

.querychat-send-button:hover {
background-color: #0a58ca;
}

.querychat-message {
max-width: 85%;
padding: 8px 12px;
margin-bottom: 8px;
border-radius: 8px;
word-wrap: break-word;
}

.querychat-user-message {
align-self: flex-end;
background-color: #0d6efd;
color: white;
}

.querychat-assistant-message {
align-self: flex-start;
background-color: #e9ecef;
}

.querychat-message table {
width: 100%;
border-collapse: collapse;
margin: 10px 0;
}

.querychat-message table td,
.querychat-message table th {
border: 1px solid #ccc;
.querychat shiny-chat-message table td,
.querychat shiny-chat-message table th {
border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color);
padding: 3px;
}

.querychat-message table th {
background-color: #f0f0f0;
.querychat shiny-chat-message table td {
font-family: var(--bs-font-monospace);
}

.querychat-message pre {
background-color: #f4f4f4;
padding: 8px;
border-radius: 4px;
overflow-x: auto;
/* querychat takes up the full sidebar, so move the collapse toggle out of the way */
.bslib-sidebar-layout:has(.querychat-sidebar):not(.sidebar-collapsed)>.collapse-toggle {
right: 4px;
top: 4px;
}

.querychat-message code {
font-family: monospace;
}
2 changes: 2 additions & 0 deletions pkg-r/NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@
* 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)
46 changes: 29 additions & 17 deletions pkg-r/R/querychat.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@
#' This will perform one-time initialization that can then be shared by all
#' Shiny sessions in the R process.
#'
#' @param data_source A querychat_data_source object created by `querychat_data_source()`.
#' @param data_source A querychat_data_source object created by
#' `querychat_data_source()`.
#'
#' To create a data source:
#' - For data frame: `querychat_data_source(df, tbl_name = "my_table")`
#' - For database: `querychat_data_source(conn, "table_name")`
#' @param greeting A string in Markdown format, containing the initial message
#' to display to the user upon first loading the chatbot. If not provided, the
#' LLM will be invoked at the start of the conversation to generate one.
#' @param data_description A string containing a data description for the chat model. We have found
#' that formatting the data description as a markdown bulleted list works best.
#' @param extra_instructions A string containing extra instructions for the chat model.
#' @param data_description A string containing a data description for the chat
#' model. We have found that formatting the data description as a markdown
#' bulleted list works best.
#' @param extra_instructions A string containing extra instructions for the
#' chat model.
#' @param client An `ellmer::Chat` object, a string to be passed to
#' [ellmer::chat()] describing the model to use (e.g. `"openai/gpt-4o"`), or a
#' function that creates a chat client. When using a function, the function
Expand All @@ -26,11 +30,11 @@
#' using [ellmer::chat_openai()].
#' @param create_chat_func `r lifecycle::badge('deprecated')`. Use the `client`
#' argument instead.
#' @param system_prompt A string containing the system prompt for the chat model.
#' The default generates a generic prompt, which you can enhance via the `data_description` and
#' `extra_instructions` arguments.
#' @param auto_close_data_source Should the data source connection be automatically
#' closed when the shiny app stops? Defaults to TRUE.
#' @param system_prompt A string containing the system prompt for the chat
#' model. The default generates a generic prompt, which you can enhance via
#' the `data_description` and `extra_instructions` arguments.
#' @param auto_close_data_source Should the data source connection be
#' automatically closed when the shiny app stops? Defaults to TRUE.
#'
#' @returns An object that can be passed to `querychat_server()` as the
#' `querychat_config` argument. By convention, this object should be named
Expand Down Expand Up @@ -124,14 +128,15 @@ querychat_init <- function(
#' UI components for querychat
#'
#' These functions create UI components for the querychat interface.
#' `querychat_ui` creates a basic chat interface, while `querychat_sidebar`
#' wraps the chat interface in a `bslib::sidebar` component designed to be used
#' as the `sidebar` argument to `bslib::page_sidebar`.
#' `querychat_ui()` creates a basic chat interface, while `querychat_sidebar()`
#' wraps the chat interface in a [bslib::sidebar()] component designed to be
#' used as the `sidebar` argument to [bslib::page_sidebar()].
#'
#' @param id The ID of the module instance.
#' @param width The width of the sidebar (when using `querychat_sidebar`).
#' @param height The height of the sidebar (when using `querychat_sidebar`).
#' @param ... Additional arguments passed to `bslib::sidebar` (when using `querychat_sidebar`).
#' @param width,height In `querychat_sidebar()`: the width and height of the
#' sidebar.
#' @param ... In `querychat_sidebar()`: additional arguments passed to
#' [bslib::sidebar()].
#'
#' @return A UI object that can be embedded in a Shiny app.
#'
Expand All @@ -141,8 +146,10 @@ querychat_sidebar <- function(id, width = 400, height = "100%", ...) {
bslib::sidebar(
width = width,
height = height,
class = "querychat-sidebar",
...,
querychat_ui(id) # purposely NOT using ns() here, we're just a passthrough
# purposely NOT using ns() for `id`, we're just a passthrough
querychat_ui(id)
)
}

Expand All @@ -159,7 +166,12 @@ querychat_ui <- function(id) {
script = "querychat.js",
stylesheet = "styles.css"
),
shinychat::chat_ui(ns("chat"), height = "100%", fill = TRUE)
shinychat::chat_ui(
ns("chat"),
height = "100%",
fill = TRUE,
class = "querychat"
)
)
}

Expand Down
3 changes: 2 additions & 1 deletion pkg-r/R/querychat_app.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ querychat_app <- function(config, ..., bookmark_store = "url") {
config$data_source$table_name,
"</code></span>"
)),
class = "bslib-page-dashboard",
sidebar = querychat_sidebar("chat"),
bslib::card(
fill = FALSE,
Expand Down Expand Up @@ -130,7 +131,7 @@ querychat_app <- function(config, ..., bookmark_store = "url") {
})
}

app <- shiny::shinyApp(ui, server, ..., enableBookmarking = bookmark_store)
app <- shiny::shinyApp(ui, server, enableBookmarking = bookmark_store)
Comment thread
gadenbuie marked this conversation as resolved.
tryCatch(shiny::runGadget(app), interrupt = function(cnd) NULL)
invisible(chat)
}
36 changes: 7 additions & 29 deletions pkg-r/inst/htmldep/styles.css
Original file line number Diff line number Diff line change
@@ -1,37 +1,15 @@
:root {
--bslib-sidebar-main-bg: #f8f8f8;
}

.popover {
--bs-popover-header-bg: #222;
--bs-popover-header-color: #fff;
}

.popover .btn-close {
filter: var(--bs-btn-close-white-filter);
}
shiny-chat-message table td,
shiny-chat-message table th {
.querychat shiny-chat-message table td,
.querychat shiny-chat-message table th {
border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color);
padding: 3px;
}

shiny-chat-message table td {
.querychat shiny-chat-message table td {
font-family: var(--bs-font-monospace);
}

#show_title:empty,
#show_query:empty {
/* Prevent empty title/query blocks from taking any space */
border: 0;
padding: 0;
margin-bottom: 0;
}

#show_title:empty,
#show_query {
/* We can't affect the flex parent's gap, so instead we use a negative margin
to counteract it. In the case of #show_query, we don't even want the gap
even when it's showing, as it results in too much space between the two. */
margin-top: calc(-1 * var(--bslib-mb-spacer));
/* querychat takes up the full sidebar, so move the collapse toggle out of the way */
.bslib-sidebar-layout:has(.querychat-sidebar):not(.sidebar-collapsed)>.collapse-toggle {
right: 4px;
top: 4px;
}
22 changes: 13 additions & 9 deletions pkg-r/man/querychat_init.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading