Skip to contents

Format ellmer content for shinychat

Usage

contents_shinychat(content)

Arguments

content

An ellmer::Content object.

Value

Returns text, HTML, or web component tags formatted for use in chat_ui().

Extending contents_shinychat()

You can extend contents_shinychat() to handle custom content types in your application. contents_shinychat() is an S7 generic. If you haven't worked with S7 before, you can learn more about S7 classes, generics and methods in the S7 documentation.

We'll work through a short example creating a custom display for the results of a tool that gets local weather forecasts. We first need to create a custom class that extends ellmer::ContentToolResult.

library(ellmer)

WeatherToolResult <- S7::new_class(
  "WeatherToolResult",
  parent = ContentToolResult,
  properties = list(
    location_name = S7::class_character
  )
)

Next, we'll create a simple ellmer::tool() that gets the weather forecast for a location and returns our custom WeatherToolResult class. The custom class works just like a regular ContentToolResult, but it has an additional location_name property.

get_weather_forecast <- tool(
  function(lat, lon, location_name) {
    WeatherToolResult(
      weathR::point_tomorrow(lat, lon, short = FALSE),
      location_name = location_name
    )
  },
  name = "get_weather_forecast",
  description = "Get the weather forecast for a location.",
  arguments = list(
    lat = type_number("Latitude"),
    lon = type_number("Longitude"),
    location_name = type_string("Name of the location for display to the user")
  )
)

Finally, we can extend contents_shinychat() to render our custom content class for display in the chat interface. The basic process is to define a contents_shinychat() external generic and then implement a method for your custom class.

contents_shinychat <- S7::new_external_generic(
  package = "shinychat",
  name = "contents_shinychat",
  dispatch_args = "contents"
)

S7::method(contents_shinychat, WeatherToolResult) <- function(content) {
  # Your custom rendering logic here
}

You can use this pattern to completely customize how the content is displayed inside shinychat by returning HTML objects directly from this method.

You can also use this pattern to build upon the default shinychat display for tool requests and results. By using S7::super(), you can create the object shinychat uses for tool results (or tool requests), and then modify it to suit your needs.

S7::method(contents_shinychat, WeatherToolResult) <- function(content) {
  # Call the super method for ContentToolResult to get shinychat's defaults
  res <- contents_shinychat(S7::super(content, ContentToolResult))

  # Then update the result object with more specific content
  # In this case, we render the tool result dataframe as a {gt} table...
  res$value <- gt::as_raw_html(gt::gt(content@value))
  res$value_type <- "html"
  # ...and update the tool result title to include the location name
  res$title <- paste("Weather Forecast for", content@location_name)

  res
}

Note that you do not need to create a new class or extend contents_shinychat() to customize the tool display. Rather, you can use the strategies discussed in the Tool Calling UI article to customize the tool request and result display by providing a display list in the extra argument of the tool result.