Skip to contents

Create a simple Shiny app for live chatting using an ellmer::Chat object. Note that these functions will mutate the input client object as you chat because your turns will be appended to the history.

The app created by chat_app() is suitable for interactive use by a single user. For multi-user Shiny apps, use the Shiny module chat functions – chat_mod_ui() and chat_mod_server() – and be sure to create a new chat client for each user session.

Usage

chat_app(client, ..., bookmark_store = "url")

chat_mod_ui(id, ..., client = deprecated(), messages = NULL)

chat_mod_server(
  id,
  client,
  greeting = NULL,
  bookmark_on_input = TRUE,
  bookmark_on_response = TRUE
)

Arguments

client

A chat object created by ellmer, e.g. ellmer::chat_openai() and friends. This argument is deprecated in chat_mod_ui() because the client state is now managed by chat_mod_server().

...

In chat_app(), additional arguments are passed to shiny::shinyApp(). In chat_mod_ui(), additional arguments are passed to chat_ui().

bookmark_store

The bookmarking store to use for the app. Passed to enable_bookmarking in shiny::shinyApp(). Defaults to "url", which uses the URL to store the chat state. URL-based bookmarking is limited in size; use "server" to store the state on the server side without size limitations; or disable bookmarking by setting this to "disable".

id

The chat module ID.

messages

Initial messages shown in the chat, used only when client (in chat_mod_ui()) doesn't already contain turns. Passed to messages in chat_ui().

greeting

Optional greeting to set when the module initializes. Accepts a static value (string, htmltools::HTML(), htmltools::tagList(), or chat_greeting()) or a function that generates the greeting dynamically. See the Greeting section below for details.

bookmark_on_input

A logical value determines if the bookmark should be updated when the user submits a message. Default is TRUE.

bookmark_on_response

A logical value determines if the bookmark should be updated when the response stream completes. Default is TRUE.

Value

  • chat_app() returns a shiny::shinyApp() object.

  • chat_mod_ui() returns the UI for a shinychat module.

  • chat_mod_server() includes the shinychat module server logic, and returns an environment containing:

    • last_input: A reactive value containing the last user input.

    • last_turn: A reactive value containing the last assistant turn.

    • update_user_input(): A function to update the chat input or submit a new user input. Takes the same arguments as update_chat_user_input(), except for id and session, which are supplied automatically.

    • append(): A function to append a new message to the chat UI. Takes the same arguments as chat_append(), except for id and session, which are supplied automatically.

    • clear(): A function to clear the chat history and the chat UI. clear() takes an optional list of messages used to initialize the chat after clearing. messages should be a list of messages, where each message is a list with role and content fields. The client_history argument controls how the chat client's history is updated after clearing. It can be one of: "clear" the chat history; "set" the chat history to messages; "append" messages to the existing chat history; or "keep" the existing chat history.

    • set_greeting(): A function to set, stream, or clear the chat greeting. Pass a chat_greeting() object, a plain string, or NULL to clear. Streaming greetings run inside an shiny::ExtendedTask so the session stays responsive; if called while a greeting is already streaming, the new greeting is queued. If the greeting has already been dismissed, calling set_greeting() updates the content but does not make it visible again; call clear(greeting = TRUE) first to show a new greeting after dismissal.

    • status: A reactive value indicating the current chat interaction state. Returns "idle" when no response is in progress, or "streaming" while a response is actively being received.

    • client: The current chat client object (an active binding that always reflects the latest client, even after set_client() is called).

    • set_client(new_client, sync = TRUE): Replace the chat client used by the module. When sync is TRUE (the default), the new client inherits conversation turns, system prompt, and tools from the previous client so the conversation continues seamlessly. Set sync = FALSE to use the new client as-is. If a response is currently streaming, the swap is deferred until the stream completes. If called multiple times while streaming, only the most recent new client is used.

Functions

  • chat_app(): A simple Shiny app for live chatting. Note that this app is suitable for interactive use by a single user; do not use chat_app() in a multi-user Shiny app context.

  • chat_mod_ui(): A simple chat app module UI.

  • chat_mod_server(): A simple chat app module server.

Greeting

When greeting is a function, the module calls it each time the greeting_requested event fires — on first view when the chat is empty, and again after clear(greeting = TRUE). The function should return a chat_greeting() (typically wrapping a stream). Static values (strings, chat_greeting() objects) are set once at init and do not regenerate.

The module detects named arguments in the greeting function to decide what to pass. Currently the only recognized argument is client.

function(client) (recommended). The module clones the client passed to chat_mod_server(), wipes its turn history, and passes the fresh clone as client. This avoids manually creating and configuring a separate client:

chat_mod_server("chat", client, greeting = function(client) {
  stream <- client$stream_async("Generate a short welcome message.")
  chat_greeting(stream)
})

function() (zero arguments). You create and manage your own client:

chat_mod_server("chat", client, greeting = function() {
  greeter <- ellmer::chat_openai(model = "gpt-4o")
  stream <- greeter$stream_async("Generate a short welcome message.")
  chat_greeting(stream)
})

Static value. Set once; does not regenerate after clear():

chat_mod_server("chat", client, greeting = "## Welcome!\n\nHow can I help?")

The returned set_greeting() helper is available for cases where you need to set a greeting outside the greeting lifecycle.

Examples

if (FALSE) { # \dontrun{
# Interactive in the console ----
client <- ellmer::chat_anthropic()
chat_app(client)

# Inside a Shiny app ----
library(shiny)
library(bslib)
library(shinychat)

ui <- page_fillable(
  titlePanel("shinychat example"),

  layout_columns(
    card(
      card_header("Chat with Claude"),
      chat_mod_ui(
        "claude",
        messages = list(
          "Hi! Use this chat interface to chat with Anthropic's `claude-3-5-sonnet`."
        )
      )
    ),
    card(
      card_header("Chat with ChatGPT"),
      chat_mod_ui(
        "openai",
        messages = list(
          "Hi! Use this chat interface to chat with OpenAI's `gpt-4o`."
        )
      )
    )
  )
)

server <- function(input, output, session) {
  claude <- ellmer::chat_anthropic(model = "claude-3-5-sonnet-latest") # Requires ANTHROPIC_API_KEY
  openai <- ellmer::chat_openai(model = "gpt-4o") # Requires OPENAI_API_KEY

  chat_mod_server("claude", claude)
  chat_mod_server("openai", openai)
}

shinyApp(ui, server)
} # }